Opencv调参神器——trackBar控件
调参需求介绍
想要学好计算机视觉,有一个库必不可少,那就是Opencv,Open即为开放的意思,说明这个库已经开源。cv是Computer Vision,即计算机视觉。Opencv底层是用C++编写的,保证了运行的速度。而Python在C++的基础上编写了调用接口API,这样我们可以使用更为简单的Python语言完成计算机视觉的任务。换句话来说,你只需要会调库,会用给定的函数就能不错的完成任务。
相信你一定听过一个词——调参,即调整参数,使得在该参数下程序达到最佳的效果。所以有人戏谑,只要当好调包侠和调参侠就是学号python-opencv,确实是这样的,“调包侠”好说,只要学会API的输入输出就可以了,但是调参是个非常难的任务。假设一个API有两个参数,每个参数有三种情况,那么就有9种情况,如果有两个API,那就是81种情况。而且在实际工程下,不仅API会很多,而且变化值也很多,很多都是可以连续变化的。
再没学习tarkbar之前,我调参也是一个一个去试,基本流程就是改变某个参数,运行,比较和上一个情况的优劣。常常会出现上个参数调好了,下一个参数的改变也会影响到上个参数。常常是写程序一小时,调参三小时。不知道你是否也会有这种苦恼,这篇文章就通过几个案例详细介绍trackBar控件,大大减少你的调参时间!
trackBar控件介绍
trackBar最大的作用就是将变量值以刻度条的形式呈现出来,在同一个界面中,支持多个刻度条同时变化,最终结果是在所以刻度条的共同作用下形成的。你可以拖动刻度条,给参数附不同的值,这样可以达到再不修改代码的前提下,快速确定最优参数
上图即为用trackBar控件设置Canny算子参数,对lena图片进行边缘检测。**可以看到上面有三个刻度条,你可以直接拖动刻度条给参数附不同的值,下面的图片实时变化,你可以观察这些参数变化对图片产生的影响,从而快速选择最合适的一组参数。这样的优点就是快速,便捷,且很直观。缺点就是会增加代码量,但是trackbar控件代码写起来也十分简单。 下面我们就通过几个案例具体学习一下trackBar,相信学完之后你会对调参有一个新的理解!
trackBar控件使用函数
trackBar控件在使用时需要两个函数,一个是创建函数,一个是获取值函数。在opencv中,给我们提供了相应的API,我们可以直接调用,非常方便。
创建函数
cv2.createTrackbar(trackbarname,winname,value,count,onChange)
- 功能:创建TrackBar控件
- trackbarname:名称
- winname:显示窗口
- value为trackbar的默认值
- count为bar的最大值,最小为0
- OnChange:回调函数
获取值函数
cv2.getTrackbarPos(trackbarname,winname)
- 功能获取TrackBar当前值
- trackbarname:上面创建的trackbar对象名称
- winname:显示窗口的名称
上面提到一个回调函数,回调函数就是函数指针的调用,即是一个通过函数指针调用的函数;如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就说这是回调函数。如果不理解也没关系,在写代码时,只需要用一个callback函数代替就可以了。
# 定义回调函数
def callback(value):
print(value)
案例一:trackBar控件调整图片颜色
学习过计算机视觉我们都知道不同的颜色实际上都是bgr三种颜色混合而成的,在这个案例里面我们通过trackBar控件将bgr设置成刻度条,通过滑动刻度条已形成不同的颜色。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv初步学习
@File :trackBar案例一:调整图片颜色.py
@IDE :PyCharm
@Author :咋
@Date :2023/1/27 19:39
"""
import cv2
import numpy as np
# 创建窗口
cv2.namedWindow("window",cv2.WINDOW_NORMAL)
cv2.resizeWindow("window",(640,480))
# 定义回调函数
def callback(value):
print(value)
# 创建三个Trackbar控件
cv2.createTrackbar("R","window",0,255,callback)
cv2.createTrackbar("G","window",0,255,callback)
cv2.createTrackbar("B","window",0,255,callback)
# 用np创建一个图像矩阵
image = np.zeros((480,640,3),np.uint8) # 注意这里的长宽是相反的,3是指通道数,np.uint8指无符号的整数
while True:
# 获取Trackbar控件的值
r = cv2.getTrackbarPos("R","window")
g = cv2.getTrackbarPos("G","window")
b = cv2.getTrackbarPos("B","window")
# 用获取的值来生成图片
image[:] = [r,g,b] # 替换像素
# 显示图片
cv2.imshow("window",image)
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
调整BGR三个刻度条的值,下面的图片颜色就会发生变化,这是trackBar最基本的案例,创建控件,获得控件的值,循环不断显示图片。这就是这个程序所做的,代码很简单,但是功能很强大!
案例二:trackBar控件调整Canny算子参数
将高斯模糊的高斯核和canny算子阈值的最大值最小值设为三个trackBar控件,探究这三个参数变化对图片产生的影响。完成代码和readme.md上传网盘,需要的同学可以自取:链接:https://pan.baidu.com/s/15IKTeFxVr6_VYnPD_IggTA?pwd=8b7k
提取码:8b7k
注意程序运行方式不是右键运行,而是在终端输入:
python find_edges.py image.jpg
程序主要是由两个py文件组成:find_edges.py和guiutils.py
find_edges.py:
"""
How to run:
python find_edges.py <image path>
"""
import argparse
import cv2
import os
from guiutils import EdgeFinder
def main():
parser = argparse.ArgumentParser(description='Visualizes the line for hough transform.')
parser.add_argument('filename',default="ICEWS18")
args = parser.parse_args()
img = cv2.imread(args.filename, cv2.IMREAD_GRAYSCALE)
cv2.imshow('input', img)
edge_finder = EdgeFinder(img, filter_size=13, threshold1=28, threshold2=115)
print ("Edge parameters:")
print ("GaussianBlur Filter Size: %f" % edge_finder.filterSize())
print ("Threshold1: %f" % edge_finder.threshold1())
print ("Threshold2: %f" % edge_finder.threshold2())
(head, tail) = os.path.split(args.filename)
(root, ext) = os.path.splitext(tail)
smoothed_filename = os.path.join(root + "-smoothed" + ext)
edge_filename = os.path.join(root + "-edges" + ext)
cv2.imwrite(smoothed_filename, edge_finder.smoothedImage())
cv2.imwrite(edge_filename, edge_finder.edgeImage())
print(smoothed_filename)
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
guiutils.py:
import cv2
class EdgeFinder:
def __init__(self, image, filter_size=1, threshold1=0, threshold2=0):
self.image = image
self._filter_size = filter_size
self._threshold1 = threshold1
self._threshold2 = threshold2
def onchangeThreshold1(pos):
self._threshold1 = pos
self._render()
def onchangeThreshold2(pos):
self._threshold2 = pos
self._render()
def onchangeFilterSize(pos):
self._filter_size = pos
self._filter_size += (self._filter_size + 1) % 2
self._render()
cv2.namedWindow('edges')
cv2.createTrackbar('threshold1', 'edges', self._threshold1, 255, onchangeThreshold1)
cv2.createTrackbar('threshold2', 'edges', self._threshold2, 255, onchangeThreshold2)
cv2.createTrackbar('filter_size', 'edges', self._filter_size, 20, onchangeFilterSize)
self._render()
print ("Adjust the parameters as desired. Hit any key to close.")
cv2.waitKey(0)
cv2.destroyWindow('edges')
cv2.destroyWindow('smoothed')
def threshold1(self):
return self._threshold1
def threshold2(self):
return self._threshold2
def filterSize(self):
return self._filter_size
def edgeImage(self):
return self._edge_img
def smoothedImage(self):
return self._smoothed_img
def _render(self):
self._smoothed_img = cv2.GaussianBlur(self.image, (self._filter_size, self._filter_size), sigmaX=0, sigmaY=0)
self._edge_img = cv2.Canny(self._smoothed_img, self._threshold1, self._threshold2)
cv2.imshow('smoothed', self._smoothed_img)
cv2.imshow('edges', self._edge_img)
这样我们就可以实时调整卷积核大小和最大阈值和最小阈值,图片实时更新,是不是非常方便?
案例三:trackBar控件调整图像融合参数
在Opencv中提供了图像融合的APIcv2.addWeighted,图像融合不是简单的加法,相当于拿图片做了线性运算new_img = img1w1+img2w2+bias
cv2.addWeighted(src1,alpha,src2,beta,gamma)
- src1:第一张图片
- alpha:第一张图片的权重
- src2:第二张图片
- beta:第二张图片的权重,没有要求两个权重加起来是1,但1的效果要好一点
- gamma:偏差b,可以理解为调节明亮度
在进行融合的时候,也要保证两张图片的尺寸一样。在融合中图片所占的权重对最终的图片有很大影响,我们可以用trackBar控件对两个权重做可视化处理。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project :Opencv初步学习
@File :案例三图像融合.py
@IDE :PyCharm
@Author :咋
@Date :2023/1/27 20:21
"""
import cv2
# 设置窗口大小
cv2.namedWindow("window",cv2.WINDOW_NORMAL)
cv2.resizeWindow("window",(640,480))
# 读取图片
dog = cv2.imread("dog.jpg")
cat = cv2.imread("cat.jpg")
dog = cv2.resize(dog,(400,500))
cat = cv2.resize(cat,(400,500))
# 定义回调函数
def callback(value):
print(value)
# 创建Trackbar控件
cv2.createTrackbar("weight_dog","window",0,100,callback)
cv2.createTrackbar("weight_cat","window",0,100,callback)
while True:
# 获取Trackbar控件的值
weight_dog = cv2.getTrackbarPos("weight_dog","window")
weight_cat = cv2.getTrackbarPos("weight_cat","window")
# 图像融合
add_dog_cat = cv2.addWeighted(dog, weight_dog/100, cat, weight_cat/100, 0)
# 显示图片
cv2.imshow("window",add_dog_cat )
if cv2.waitKey(1) == ord("q"):
break
cv2.waitKey(0)
cv2.destroyAllWindows()
通过上面的gif可以看到,调高dog的权重,dog的图片会更清楚,调高cat的权重,cat的图片会更清楚,这样动态的调整十分方便,不用一个数字一个数字去试了。
trackBar控件总结
通过这三个案例的学习,相信你对trackbar控件有了更深刻的理解,合理运用trackbar控件将会极大地加快你调参的速度,达到事半功倍的效果!这三个例子只是起到抛砖引玉的效果,在之后的项目中,你也可以把这种发放引入到你的工程中!
好啦,今天的分享就到这里,感兴趣的小伙伴欢迎私信博主或者评论交流哦!
✨ 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力! \textcolor{green}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \textcolor{green}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \textcolor{green}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!