2

opencv 绘图及交互(python)

 1 year ago
source link: https://blog.51cto.com/u_14926062/5365165
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

opencv 绘图及交互(python)

原创

暴风雨中的白杨 2022-06-08 00:07:58 博主文章分类:openCV ©著作权

文章标签 python 背景图 阈值处理 文章分类 其他 人工智能 阅读数159

绘图及交互

Opencv提供了方便的绘图功能,使用其中的绘图函数可以绘制直线、矩形、圆、椭圆等多种几何图形,还能在图像中的指定位置添加文字说明。

OpenCV提供了鼠标事件,使用户可以通过鼠标与图像交互。鼠标事件能够识别常用的鼠标操作,例如:针对不同按键的单击、双击,鼠标的滑动、拖曳等。

OpenCV还提供了滚动条用于实现交互功能。用户可以拖动滚动条在某一个范围内设置特定的值,并将该值应用于后续的图像处理中。而且,如果设置为二值形式,滚动条还可以作为开关选择器使用。

OpenCV提供了绘制直线的函数cv2.line()、绘制矩形的函数cv2.rectangle()、绘制圆的函数cv2.circle()、绘制椭圆的函数cv2.ellipse()、绘制多边形的函数cv2.polylines()、在图像内添加文字的函数cv2.putText()等多种绘图函数。

这些绘图函数有一些共有的参数,主要用于设置源图像、颜色、线条属性等。

共有参数简单的介绍:

  • img:在其上面绘制图形的载体图像(绘图的容器载体,也称为画布、画板)。

  • color:绘制形状的颜色。通常使用BGR模型表示颜色,例如,(0, 255, 0)表示绿色。对于灰度图像,只能传入灰度值。需要注意,颜色通道的顺序是BGR,而不是RGB。

  • thickness:线条的粗细。默认值是1,如果设置为-1,表示填充图形(即绘制的图形是实心的)。

  • lineType:线条的类型,默认是8连接类型。

    opencv 绘图及交互(python)_背景图
  • shift:数据精度。该参数用来控制数值(例如圆心坐标等)的精度,一般情况下不需要设置。

OpenCV提供了函数cv2.line()用来绘制直线(线段)。

该函数的语法格式为:

img = cv2.line( img, pt1, pt2, color[, thickness[, lineType ]])
  • 参数img、color、thickness、lineType的含义如前面的说明所示。
  • pt1表示线段的第1个点(起点)。
  • pt2表示线段的第2个点(终点)。

使用cv2.line()函数在一个黑色背景图像内绘制三条线段。

import numpy as np 
import cv2 
n = 300 
img = np.zeros((n+1, n+1,3), np.uint8) 
img = cv2.line(img, (0,0), (n, n), (255,0,0),3) 
img = cv2.line(img, (0,100), (n,100), (0,255,0),1) 
img = cv2.line(img, (100,0), (100, n), (0,0,255),6)  
cv2.namedWindow("test") 
cv2.imshow("test", img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_背景图_02

OpenCV提供了函数cv2.rectangle()用来绘制矩形。

该函数的语法格式为:

img = cv2.rectangle( img, pt1, pt2, color[, thickness[, lineType]] )
  • 参数img、color、thickness、lineType的含义如前面的说明所示。
  • pt1为矩形顶点。
  • pt2为矩形中与pt1对角的顶点。

使用函数cv2.rectangle()在一个白色背景图像内绘制一个实心矩形。

import numpy as np 
import cv2 
n = 300 
img = np.ones((n, n,3), np.uint8)*255 
img = cv2.rectangle(img, (50,50), (n-100, n-50), (0,0,255), -1) 
winname = 'test' 
cv2.namedWindow(winname) 
cv2.imshow(winname, img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_背景图_03

OpenCV提供了函数cv2.circle()用来绘制圆。

该函数的语法格式为:

img = cv2.circle( img, center, radius, color[, thickness[, lineType]] ) 
  • 参数img、color、thickness、lineType的含义如前面的说明所示。
  • center为圆心。
  • radius为半径。

使用函数cv2.circle()在一个白色背景图像内绘制一组同心圆。

import numpy as np 
import cv2 
d = 400 
img = np.ones((d, d,3), dtype="uint8")*255 
(centerX, centerY) = (round(img.shape[1] / 2), round(img.shape[0] / 2)) 
# 将图像的中心作为圆心,实际值为d/2 
red = (0,0,255) # 设置红色变量 
for r in range(5, round(d/2),12): 
    cv2.circle(img, (centerX, centerY), r, red,3) 
    # circle(载体图像,圆心,半径,颜色,宽度) 
cv2.imshow("test", img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_阈值处理_04

OpenCV提供了函数cv2.ellipse()用来绘制椭圆。

该函数的语法格式为:

img=cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType]]) 
  • 参数img、color、thickness、lineType的含义如前面的说明所示。
  • center为椭圆的圆心坐标。
  • axes为轴的长度。有两个轴,所以是个元组
  • angle为偏转的角度。
  • startAngle为圆弧起始角的角度
  • endAngle为圆弧终结角的角度

使用函数cv2.ellipse()在一个白色背景图像内随机绘制一组空心椭圆。

import numpy as np 
import cv2 
d = 400 
img = np.ones((d, d,3), dtype="uint8")*255 
# 生成白色背景 
center=(round(d/2), round(d/2)) 
# 注意数值类型,不可以使用语句center=(d/2, d/2)

size=(100,200) 
# 轴的长度

for i in range(0,10): 
    angle = np.random.randint(0,361) 
    # 偏移角度

    color = np.random.randint(0, high = 256, size = (3, )).tolist() 
    # 生成随机颜色,3个[0,256)的随机数 
    thickness = np.random.randint(1,9) 
    cv2.ellipse(img, center, size, angle, 0, 360, color, thickness) 
cv2.imshow("test", img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_python_05
opencv 绘图及交互(python)_背景图_06
绘制多边形

cv2.polylines()用来绘制多边形。

该函数的语法格式为:

img = cv2.polylines( img, pts, isClosed, color[, thickness[, lineType[, shift]]]) 
  • 参数img、color、thickness、lineType和shift的含义如前面的说明所示。
  • pts为多边形的各个顶点。
  • isClosed为闭合标记,用来指示多边形是否是封闭的。若该值为True,则将最后一个点与第一个点连接,让多边形闭合;否则,仅仅将各个点依次连接起来,构成一条曲线。

在使用函数cv2.polylines()绘制多边形时,需要给出每个顶点的坐标。

这些点的坐标构建了一个大小等于“顶点个数12”的数组,这个数组的数据类型必须为numpy.int32。

使用函数cv2.polylines()在一个白色背景图像内绘制一个多边形。

import numpy as np 
import cv2 
d = 400 
img = np.ones((d, d,3), dtype="uint8")*255 
# 生成白色背景 
pts=np.array([[200,50], [300,200], [200,350], [100,200]], np.int32) 
# 生成各个顶点,注意数据类型为int32 
pts=pts.reshape((-1,1,2)) 
# 第1个参数为-1,表明它未设置具体值,它所表示的维度值是通过其他参数值计算得到的 
cv2.polylines(img, [pts], True, (0,255,0),8) 
# 调用函数cv2.polylines()完成多边形绘图。注意,第3个参数控制多边形是否封闭 
cv2.imshow("test", img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_背景图_07

可以使用函数cv2.polylines()来绘制多条首尾相连的线段。只要把线段的各个点放在一个数组中,将这个数组传给函数cv2.polylines()的第2个参数pts,并且isClosed为False。

注意pts参数的维度

OpenCV提供了函数cv2.putText()用来在图形上绘制文字。

该函数的语法格式为:

img=cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) 
  • 参数img、color、thickness、lineType和shift的含义如前面的说明所示。

  • text为要绘制的文本。

  • org为绘制字体的位置,以文字的左下角为起点。

  • fontFace表示字体类型

    opencv 绘图及交互(python)_python_08
  • fontScale表示字体大小。

  • bottomLeftOrigin用于控制文字的方向。默认值为False,当设置为True时,文字是垂直镜像的效果。

使用函数cv2.putText()在一个白色背景图像内绘制文字。

import numpy as np 
import cv2 
d = 400 
img = np.ones((d, d,3), dtype="uint8")*255 
# 生成白色背景 
font=cv2.FONT_HERSHEY_SIMPLEX 
cv2.putText(img, 'OpenCV', (0,200), font, 3, (0,255,0),15) 
cv2.putText(img, 'OpenCV', (0,200), font, 3, (0,0,255),5) 
cv2.imshow("test", img) 
cv2.waitKey(0) 
cv2.destroyAllWindows()
opencv 绘图及交互(python)_阈值处理_09
import numpy as np 
import cv2 
d = 400 
img = np.ones((d, d,3), dtype="uint8")*255 
# 生成白色背景 
font=cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'OpenCV', (0,150), font, 3, (0,0,255),15) 
cv2.putText(img, 'OpenCV', (0,250), font, 3, (0,255,0),15, cv2.LINE_8, True)
cv2.imshow("test", img) 
cv2.waitKey(0) 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_阈值处理_10

参数bottomLeftOrigin的值被设置为True,实现绘制镜像文字效果

用户单击鼠标,就画一个圆。通常的做法是,创建一个OnMouseAction()响应函数,将要实现的操作写在该响应函数内。

响应函数是按照固定的格式创建的,其格式为:

def OnMouseAction(event, x, y, flags, param):
  • event表示触发了何种事件,具体事件如表所示。

    opencv 绘图及交互(python)_背景图_11
  • x, y代表触发鼠标事件时,鼠标在窗口中的坐标(x, y)

  • flags代表鼠标的拖曳事件,以及键盘鼠标联合事件

    opencv 绘图及交互(python)_背景图_12
  • param为函数ID,标识所响应的事件函数,相当于自定义一个OnMouseAction()函数的ID

  • OnMouseAction为响应函数的名称,该名称可以自定义。

定义响应函数以后,要将该函数与一个特定的窗口建立联系(绑定),让该窗口内的鼠标触发事件时,能够找到该响应函数并执行。

要将函数与窗口绑定,可以通过函数cv2.setMouseCallback()实现,其基本语法格式是:

cv2.setMouseCallback(winname, onMouse)
  • winname为绑定的窗口名。
  • onMouse为绑定的响应函数名。

例子: 设计一个程序,对触发的鼠标事件进行判断:

import cv2 
import numpy as np 
def Demo(event, x, y, flags, param): 
    if event == cv2.EVENT_LBUTTONDOWN: 
        print("单击了鼠标左键") 
    elif event==cv2.EVENT_RBUTTONDOWN : 
        print("单击了鼠标右键") 
    elif flags==cv2.EVENT_FLAG_LBUTTON: 
        print("按住左键拖动了鼠标") 
    elif event==cv2.EVENT_MBUTTONDOWN : 
        print("单击了中间键") 
# 创建名称为Demo的响应(回调)函数OnMouseAction 
# 将响应函数Demo与窗口“test”建立连接(实现绑定) 
img = np.ones((300,300,3), np.uint8)*255 
cv2.namedWindow('test') 
cv2.setMouseCallback('test', Demo) 
cv2.imshow('test', img) 
cv2.waitKey() 
cv2.destroyAllWindows() 

按住鼠标左键拖动鼠标,会依次触发单击左键事件“cv2.EVENT_LBUTTONDOWN”和左键拖动事件“cv2.EVENT_FLAG_LBUTTON”

例子: 实现一个双击鼠标绘制矩形的简单程序。

import cv2 
import numpy as np 
d = 400 
def draw(event, x, y, flags, param): 
    if event==cv2.EVENT_LBUTTONDBLCLK: 
        p1x=x 
        p1y=y 
        p2x=np.random.randint(1, d-50) 
        p2y=np.random.randint(1, d-50) 
        color = np.random.randint(0, high = 256, size = (3, )).tolist() 
        cv2.rectangle(img, (p1x, p1y), (p2x, p2y), color,2) 
img = np.ones((d, d,3), dtype="uint8")*255
cv2.namedWindow('test') 
cv2.setMouseCallback('test', draw)

while(1): 
    cv2.imshow('test', img)   # 刷新界面
    if cv2.waitKey(20)==27: 
        break 
cv2.destroyAllWindows() 

**例子: ** 通过键盘与鼠标的组合控制显示不同的形状或文字。

import cv2 
import numpy as np 
thickness=-1 
mode=1 
d=400 
def draw_circle(event, x, y, flags, param): 
    if event==cv2.EVENT_LBUTTONDOWN: 
        a=np.random.randint(1, d-50) 
        r=np.random.randint(1, d/5) 
        angle = np.random.randint(0,361) 
        color = np.random.randint(0, high = 256, size = (3, )).tolist() 
        if mode==1: 
            cv2.rectangle(img, (x, y), (a, a), color, thickness) 
        elif mode==2: 
            cv2.circle(img, (x, y), r, color, thickness) 
        elif mode==3: 
            cv2.line(img, (a, a), (x, y), color,3) 
        elif mode==4: 
            cv2.ellipse(img, (x, y), (100,150), angle, 0, 360, color, thickness) 
        elif mode==5: 
            cv2.putText(img, 'OpenCV', (0, round(d/2)),cv2.FONT_HERSHEY_SIMPLEX, 2, color,5)
            
img=np.ones((d, d,3), np.uint8)*255 
cv2.namedWindow('image') 
cv2.setMouseCallback('image', draw_circle) 
while(1): 
    cv2.imshow('image', img) 
    k=cv2.waitKey(1)&0xff
    if k==ord('r'): 
        mode=1 
    elif k==ord('c'): 
        mode=2 
    elif k==ord('l'): 
        mode=3 
    elif k==ord('e'): 
        mode=4 
    elif k==ord('t'): 
        mode=5 
    elif k==ord('f'): 
        thickness=-1 
    elif k==ord('u'): 
        thickness=3 
    elif k==27: 
        break 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_背景图_13

滚动条(Trackbar)在OpenCV中是非常方便的交互工具,它依附于特定的窗口而存在。

通过调节滚动条能够设置、获取指定范围内的特定值。

在OpenCV中,函数cv2.createTrackbar()用来定义滚动条,其语法格式为:

cv2.createTrackbar(trackbarname, winname, value, count, onChange) 
  • trackbarname为滚动条的名称。

  • winname为滚动条所依附窗口的名称。

  • value为初始值,该值决定滚动条中滑块的位置。

  • count为滚动条的最大值。通常情况下,其最小值是0。

  • onChange为回调函数。一般情况下,将滚动条改变后要实现的操作写在回调函数内。

    注意: 该回调函数需要有一个参数,接收当前滚动条的值

函数cv2.createTrackbar()用于生成一个滚动条。拖动滚动条,就可以设置滚动条的值,并让滚动条返回对应的值。滚动条的值可以通过函数cv2.getTrackbarPos()获取,其语法格式为:

retval=getTrackbarPos( trackbarname, winname )
  • retval为返回值,获取函数cv2.createTrackbar()生成的滚动条的值。
  • trackbarname为滚动条的名称
  • winname为滚动条所依附的窗口的名称。
用滚动条实现调色板

在RGB颜色空间中,任何颜色都是由红(R)、绿(G)、蓝(B)三种颜色构成的,每一种颜色分量的区间是[0, 255]。

用函数cv2.createTrackbar()和函数cv2.getTrackbarPos()设计一个模拟调色板:在窗体中,有三个滚动条分别用来设置R、G、B的值,调色板会根据当前的R、G、B值实时显示其所对应的颜色。

设计一个滚动条交互程序,通过滚动条模拟调色板效果。

import cv2 
import numpy as np 
def changeColor(x): 
    r=cv2.getTrackbarPos('R', 'image') 
    g=cv2.getTrackbarPos('G', 'image') 
    b=cv2.getTrackbarPos('B', 'image') 
    img[:]=[b, g, r]
    
img=np.zeros((100,700,3), np.uint8) 
cv2.namedWindow('image') 
cv2.createTrackbar('R', 'image',0,255, changeColor) 
cv2.createTrackbar('G', 'image',0,255, changeColor) 
cv2.createTrackbar('B', 'image',0,255, changeColor) 
while(1): 
    cv2.imshow('image', img) 
    k=cv2.waitKey(1)&0xff
    if k==27: 
        break 
cv2.destroyAllWindows() 
opencv 绘图及交互(python)_背景图_14
用滚动条控制阈值处理参数

设计一个滚动条交互程序,通过滚动条控制函数cv2.threshold()中的阈值和模式。

回顾一下函数cv2.threshold()的语法格式:

retval, dst=cv2.threshold(src, thresh, maxval, type)
  • src:源图像。
  • thresh:阈值。
  • maxval:当type参数的值为THRESH_BINARY或者THRESH_BINARY_INV时,需要设定的最大值。
  • type:阈值处理的方式(类型)
  • dst:处理结果
  • retval:返回的阈值
import cv2 
Type=0  # 阈值处理方式 
Value=0 # 使用的阈值 
def onType(a): 
    Type= cv2.getTrackbarPos(tType, windowName) 
    Value= cv2.getTrackbarPos(tValue, windowName) 
    ret, dst = cv2.threshold(o, Value,255, Type) 
    cv2.imshow(windowName, dst)   # 在这里显示

def onValue(a): 
    Type= cv2.getTrackbarPos(tType, windowName) 
    Value= cv2.getTrackbarPos(tValue, windowName) 
    ret, dst = cv2.threshold(o, Value, 255, Type) 
    cv2.imshow(windowName, dst)   # 在这里显示

o = cv2.imread("./img/hand1.png",0) 
windowName = "test"  #窗体名 
cv2.namedWindow(windowName) 
cv2.imshow(windowName, o) 
# 创建两个滚动条 
tType = "Type"     # 用来选取阈值处理方式的滚动条 
tValue = "Value"   # 用来选取阈值的滚动条 
cv2.createTrackbar(tType, windowName, 0, 4, onType) 
cv2.createTrackbar(tValue, windowName,0, 255, onValue) 
if cv2.waitKey(0) == 27: 
    cv2.destroyAllWindows() 
opencv 绘图及交互(python)_阈值处理_15
用滚动条作为开关

滚动条只有两种值“0”和“1”,当滚动条的值为0时,代表False;当滚动条的值为1时,代表True。

设计一个滚动条交互程序,用滚动条控制绘制的矩形是实心的还是空心的。

import cv2 
import numpy as np 
d=400 
global thickness 
thickness=-1 
def fill(x): 
    pass 
def draw(event, x, y, flags, param): 
    if event==cv2.EVENT_LBUTTONDBLCLK: 
        p1x=x 
        p1y=y 
        p2x=np.random.randint(1, d-50) 
        p2y=np.random.randint(1, d-50) 
        color = np.random.randint(0, high = 256, size = (3, )).tolist() 
        cv2.rectangle(img, (p1x, p1y), (p2x, p2y), color, thickness) 

img=np.ones((d, d,3), np.uint8)*255 
cv2.namedWindow('image') 
cv2.setMouseCallback('image', draw) 
cv2.createTrackbar('R', 'image',0,1, fill) 
while(1): 
    cv2.imshow('image', img) 
    
    g=cv2.getTrackbarPos('R', 'image') 
    if g==0: 
        thickness=-1 
    else: 
        thickness=2
    k=cv2.waitKey(1)&0xff
    if k==27: 
        break 
cv2.destroyAllWindows() 

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK