OpenCV中的GUI特性 —— 绘图+鼠标画笔+轨迹栏调色板
这一部分内容主要包括OpenCV的绘图函数、鼠标回调函数与画图的结合和轨迹栏的使用,绘图函数的传参是关键,鼠标回调函数也是一个相当重要的概念,OpenCV没有提供按钮功能,而轨迹栏可以实现类似的功能,当轨迹栏作为调色板时会有什么样的体验嘞
目录
1.1 OpenCV中的绘图功能
在这一部分内容中我们会学习使用OpenCV绘制一些不同几何形状的功能函数:**cv.line(),cv.circle(),cv.rectangle(),cv.ellipse(),cv.putText()**,这些所有的功能函数,都有着相似的传递参数
- 第一个参数img:要绘制形状的图像(在目前阶段我们可以理解为在绘图之前需要一个画板,而这个img参数就是我们的画板图像)
- 第二个参数color:顾名思义这个参数的含义就是设置图画的颜色,对于BGR我们常常通过一个三元组作为参数传递
- 第三个参数厚度:厚度即是线或圈的粗细程度(这里需要注意一个点:如果我们的图像是一个封闭图像,我们在设置厚度时如果传入-1作为参数,那么这个封闭图像将被color纯色填充),默认的厚度为1
- 第四个参数LineType:这个参数也是同样的顾名思义,没错这就是线的类型
在开下面的内容之前我们补充一个拓展小知识: np.zerps()的两种用法
- np.zeros()函数返回一个元素全为0且给定形状和类型的数组 np.zeros(shape,dtype=float, order=‘C’)
- np.zeros()得到一个图像,这个用法有两个参数,一个是创建的图片矩阵大小,另一个是数据类型512,512是像素(第一个512像素高,第二个是512像素宽),3指BGR三种颜色,uint8是用0-255表示所有颜色
在绘制一下常见的几何图形时,我们要从它们本身的特性入手,这些特性与他们的特异参数以及这些参数的来源和意义息息相关
- 画线:如果需要绘制一条线,那么我们就会想到两点确定一条直线,故在cv.line()函数中我们只需要传入这条线的起止位置的坐标和其他公共参数,就可以完成对直线的绘制
# 创建黑色的图像
img = np.zeros((512,512,3), np.uint8)# 绘制一条厚度为5的蓝色对角线
cv.line(img,(0,0),(511,511),(255,0,0),5)
- 画矩形:怎么才能确定一个矩形呢?没错就是得到一个矩形的左上角和右下角两个点的坐,我们就能画出这个矩形
cv.rectangle(img,(384,0),(510,128),(0,255,0),3)
- 画圆圈:一个圆心,一条半径就可以确定一个圆,所以我们只需要函数中传入这个圆圈的圆心坐标和半径长度就能画出这个圆
cv.circle(img,(447,63),63,(0,0,255),-1)# 没错!圆圈是一个封闭的图形,我们在厚度参数的位置传入-1.就可以得到这个用纯色填充的圆圈
- 画椭圆:结合我们高中学过的知识,绘制一个椭圆的关键有三个,中心、长轴和短轴,但是在这里多了几个参数,angle、startAngle和endAngle,angle指这个椭圆按逆时针旋转的角度,而startAngle和endAngle是指沿顺时针方向测量的椭圆弧的开始和结束(它决定了绘制椭圆的哪些部分)
cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
- 画多边形:绘制一个封闭的多边形,我们就要得到它的几个顶点的坐标,把这些顶点连接起来就绘制了我们的目标图形,通常我们把这些点的坐标组成形状为ROWSx1x2的数组,其中ROWS是顶点数,第三个参数Ture 或 False表示要不要得到一个封闭多边形,如果传入了False则会得到一个连接了所有点的折线
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))# pts.reshape()函数表示自适应该维度大小,如果数组有ROWSx1x2个元素,用reshape()函数返回一个 shape = (ROWS,1,2)的数组
- 在图像中添加文本:要将文本放入图像中,需要指定以下内容,1.您要写入的文字数据 ;2.要放置它的位置坐标(即数据开始的左下角);3.字体类型;4.字体比例;5.公共参数(颜色厚度等)
为了获得更好的外观,建议使用lineType = cv.LINE_AA
综合代码实现
import cv2 as cv
from matplotlib import pyplot as plt
import numpy as np
# 创建黑色图像
img = np.zeros((512,512,3), np.uint8)# 1.绘制一条厚度为2的蓝色的线
cv.line(img,(511,511),(444,333),(255,0,0),2)# 2.绘制一个矩形(矩形所需要的参数与直线相似:画布、起始坐标、结束坐标、颜色、厚度)
cv.rectangle(img,(384,0),(510,128),(0,255,0),3)# 3.绘制一个圆圈(画圆圈有5个参数)
cv.circle(img,(447,63),63,(0,0,255),-1)# 4.绘制一个椭圆(画椭圆需要8个参数)
cv.ellipse(img,(256,256),(100,50),60,0,90,255,-1)# 5.绘制多边形
pts = np.array([[100,50],[200,300],[500,200],[500,100]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))# 6.向图像中添加文本
cv.putText(img,'Hello OpenCV',(10,500), font,2,255,2, cv.LINE_AA)
cv.namedWindow('picture')
cv.imshow('picture', img)
cv.waitKey(0)
cv.destroyAllWindows()
1.2 鼠标画笔
这一部分的内容主要呈现了OpenCV图像绘制和OpenCV鼠标事件处理的小结合,关于OpenCV的鼠标事件处理关系到一个很重要的函数:cv.setMouseCallback()
我们主要通过一个小应用程序来学习本部分的内容:双击鼠标绘制一个圆!
首先我们需要创建一个鼠标回调函数,这个函数在发生鼠标双击事件时被触发(鼠标事件可以是与鼠标相关的一切事物),它为我们提供了鼠标的当前位置坐标,提通过这个坐标我们可以做很多操作
创建鼠标回调函数具有特定的格式,该格式在所有地方都相同,它仅在功能上有所不同,现在我们要做的是让这个鼠标回调函数具有双击鼠标绘制一个圆圈的功能
import numpy as np
import cv2 as cv
# 鼠标回调函数defdraw_circle(event,x,y,flags,param):if event == cv.EVENT_LBUTTONDBLCLK:
cv.circle(img,(x,y),100,(255,0,0),-1)# 创建一个黑色的图像,一个窗口,并绑定到窗口的功能
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image',draw_circle)while(1):
cv.imshow('image',img)if cv.waitKey(20)&0xFF==27:break
cv.destroyAllWindows()
更高级的实现
下面我们学习一个关于鼠标回调函数与图形绘制的小高级联动程序:通过拖动鼠标来绘制矩形或圆形(取决于我们选择的模式) ,就像我们在 Paint 应用程序中所做的那样。所以我们的鼠标回调函数有两部分,一部分用于绘制矩形,另一部分用于绘制圆形,键盘键入“ m ”以切换功能
import numpy as np
import cv2 as cv
drawing =False# 如果按下鼠标,则为真
mode =True# 如果为真,绘制矩形。按 m 键可以切换到曲线
ix, iy =-1,-1# 鼠标回调函数defdraw_circle(event, x, y, flags, param):global ix, iy, drawing, mode
if event == cv.EVENT_LBUTTONDOWN:
drawing =True
ix, iy = x, y
elif event == cv.EVENT_MOUSEMOVE:if drawing:if mode:
cv.rectangle(img,(ix, iy),(x, y),(0,255,0),-1)else:
cv.circle(img,(x, y),20,(0,0,255),-1)elif event == cv.EVENT_LBUTTONUP:
drawing =Falseif mode:
cv.rectangle(img,(ix, iy),(x, y),(0,255,0),-1)else:
cv.circle(img,(x, y),20,(0,0,255),-1)# 创建一个黑色图像,并绑定到窗口的功能
img = np.zeros((512,512,3), np.uint8)
cv.namedWindow('image')
cv.setMouseCallback('image', draw_circle)while1:
cv.imshow('image', img)
k = cv.waitKey(1)&0xFFif k ==ord('m'):
mode =not mode
if k ==27:break
cv.destroyAllWindows()
1.3 轨迹栏调色板
这一部分我们同样通过一个实例来学习,我们实现这样一个功能:有一个显示颜色的窗口,以及三个用于指定B/G/R的跟踪栏,通过滑动轨迹栏来改变窗口的颜色(默认条件下窗口为黑色)
要实现这样一个功能,我们要熟练掌握两个关键函数::cv.getTrackbarPos和cv.createTrackbar
cv.getTrackbarPos()函数详解:这个函数有五个关键参数,第一个参数是轨迹栏名称,第二个参数是它附加到的窗口名称,第三个参数是默认值(初始状态的取值),第四个参数是最大值,第五个参数是执行的回调函数,这个回调函数会每次跟踪栏值的改变并作出相应的反映
我们加入一个方便我们操作的模块:开关。默认情况下OpenCV不具有按钮功能,但是我们可以使用轨迹栏来获得此类功能
代码实现
import numpy as np
import cv2 as cv
defnothing(x):pass# 创建一个黑色的图像,一个窗口
img = np.zeros((300,512,3), np.uint8)
cv.namedWindow('image')# 创建颜色变化的轨迹栏
cv.createTrackbar('R','image',0,255,nothing)
cv.createTrackbar('G','image',0,255,nothing)
cv.createTrackbar('B','image',0,255,nothing)# 为 ON/OFF 功能创建开关
switch ='0 : OFF \n1 : ON'
cv.createTrackbar(switch,'image',0,1,nothing)while(1):
cv.imshow('image',img)
k = cv.waitKey(1)&0xFFif k ==27:break# 得到四条轨迹的当前位置
r = cv.getTrackbarPos('R','image')
g = cv.getTrackbarPos('G','image')
b = cv.getTrackbarPos('B','image')
s = cv.getTrackbarPos(switch,'image')if s ==0:
img[:]=0else:
img[:]=[b,g,r]
cv.destroyAllWindows()
(注:文章内容参考OpenCV4.1中文官方文档)
如果文章对您有所帮助,记得一键三连支持一下哦~
版权归原作者 ErrorError! 所有, 如有侵权,请联系我们删除。