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 npimport 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 npimport 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)*255cv.namedWindow('draw circle')
cv.createTrackbar('r','draw circle',5,30,draw_circle)cv.waitKey(0)cv.destroyAllWindows()


执行结果如下:


【OpenCV教程】08 trackbar操作及实例详解_c++


【OpenCV教程】08 trackbar操作及实例详解_c++_02


3 对比

对比两种方式,如果我们使用回调函数时候,不做操作,而是获取相关的数据做后续操作,我们就需要使用循环,每获取一次,重新执行一次。


如果我们使用回调函数,将操作写在回调函数里面,那就通过trackbar的创建执行相关操作,就不需要循环执行了。


所以一般来说写好回调函数比不使用回调函数代码更加简洁,但是对于初学者来说,使用变量获取trackbar的位置再进行动态调整,逻辑上更容易理解。