1 trackbar控件
1 引入
我们经常会接触到一些软件有这样的功能,通过拖动一个控件,然后使得其他内容发生改变。
比如我们可以通过拖动控件输出不同的角色,通过拖动控件调整物体的大小,拖动控件调整音量等等。
在计算机视觉中,我们也需要动态调整,查看不同的解决,做出更好地参数选择,这时候,我们就用到了一个新的控件。
2 控件介绍
OpenCV中提供了一个叫做 trackbar 的控件。
这个控件用于动态调整代码中的一些参数,从而得到不同的效果。
比如在后面我们经常需要调整阈值,初始阈值设为多少合适,针对不同的图像,得到的结果也是不同的,这个时候,我们就需要不断试验不同的阈值,但如果每试验一次,就重新修改并运行一次代码就很麻烦,如果能在结果查看界面动态调整,就更加方便了。
话不多说,让我们走进这个控件,来看一下它的功能吧!
3 控件调用API
OpenCV提供了两个API来完成控件的一系列操作。一个API是 createTrackbar ,该API实现的功能是:
为指定窗口创建轨迹栏 trackbar 。
API定义如下:
def createTrackbar(trackbarName, windowName, value, count, onChange)
API的参数含义如下:
(1)trackbarname:滑动条轨迹名。(2)winname:用作创建的轨迹栏父窗口的名称。即滑动条依附的窗口名。(3)value:滑块的位置。创建时,滑块位置由该变量定义,滑块初始位置就是这个变量当前的值。(4)count:滑块的最大位置。最小位置总是0。(5)onChange:指向每次滑块更改位置时要调用的函数,一般默认有一个参数,就是滑块当前的位置。
对于第2个参数窗口名称,之前我们必须要使用API namedWindow 创建该窗口,我们需要自己写调用函数,在后面,我们会举具体的例子。
另一个API是 getTrackbarPos ,该API实现的功能是:
获取轨迹栏中滑块的位置。
API定义如下:
def getTrackbarPos(trackbarname, winname)
API的参数含义如下:
(1)trackbarname:滑动条轨迹名。(2)winname:用作创建的轨迹栏父窗口的名称。即滑动条依附的窗口名。
函数返回值为trackbar的位置。
2 trackbar修改背景颜色
1 回调函数我们要写好trackbar的回调函数,方便我们后面调用。
在这个例子中,我们的回调函数不用执行任何功能。所以我们写回调函数如下:
def nothing(x): pass
2 其他代码及执行结果
有了回调函数,我们就需要创建一个图像,并完成相关的控件创建,我们要创建三个用于表示三个颜色通道的trackbar。代码如下:
import numpy as np
import cv.cv2 as cv
img = np.zeros((500,1200,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)
然后我们通过调整颜色,不断输出修改后的背景色,代码如下:
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:
break
r = cv.getTrackbarPos('R','image')
g = cv.getTrackbarPos('G','image')
b = cv.getTrackbarPos('B','image')
img[:] = [b, g, r]
cv.destroyAllWindows()
为了让大家更好地看到效果,我为大家录了一段执行的视频如下:
3 修改绘制图大小
1 回调函数我们绘制一个圆,通过修改trackbar调整圆的大小,所以我们需要定义一个绘制圆的函数,函数参数r是通过trackbar获得的:
import numpy as np
import cv.cv2 as cv
def draw_circle(r):
src = np.ones((200, 400, 3), np.uint8) * 255
cv.circle(src, (200, 100), r, (156, 25, 25), -1, cv.LINE_AA)
cv.imshow('draw circle', src)
2 其他代码及执行结果
代码如下:
src = np.ones((200,400,3), np.uint8)*255
cv.namedWindow('draw circle')
cv.createTrackbar('r','draw circle',5,30,draw_circle)
cv.waitKey(0)
cv.destroyAllWindows()
执行结果如下:
3 对比
对比两种方式,如果我们使用回调函数时候,不做操作,而是获取相关的数据做后续操作,我们就需要使用循环,每获取一次,重新执行一次。
如果我们使用回调函数,将操作写在回调函数里面,那就通过trackbar的创建执行相关操作,就不需要循环执行了。
所以一般来说写好回调函数比不使用回调函数代码更加简洁,但是对于初学者来说,使用变量获取trackbar的位置再进行动态调整,逻辑上更容易理解。