本文共 3357 字,大约阅读时间需要 11 分钟。
继续填坑。
如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:
如果你想了解更多有关于计算机视觉、OpenCV、机器学习、深度学习等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!
首先我们先回顾一下形态学操作。
首先我们学习了形态学的两个基本操作,分别是:膨胀和腐蚀。
(1)膨胀:跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。
因为是最大像素,所以对于二值图像来说,膨胀就是可以让白色区域膨胀扩大。
(2)腐蚀:腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值。
因为是最小像素,所以对于二值图像来说,辅食就是黑色腐蚀区域扩大。
接下来我们学习了5个形态学操作,分别如下:
(1)开操作:先腐蚀后膨胀,可以去掉小的对象。
(2)闭操作:先膨胀后腐蚀,可以填充小对象。
(3)形态学梯度:膨胀减去腐蚀。
(4)顶帽:顶帽是原图像与开操作图像之间的差值图像。
(5)黑帽:黑帽是闭操作图像与原图像之间的差值图像。
今天我们来学习一下形态学两个非常重要的应用。
之前,我们每次使用形态学操作,需要设置核,核的大小需要我们自己设置,每次想要调整,都是需要不断停止运行,修改代码,然后再执行,这样太慢了,我们能不能运行的过程中,通过调整滑动条,让它自动调整核的大小呢?
opencv提供了trackbar功能。我们可以创建一个trackbar来动态调整核的大小,这样,我们就不用每次都重新修改代码,重新编译了。
创建trackbar的API是createTrackbar()。
int createTrackbar( const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0);
函数参数含义如下:
(1)String类型的trackbarname,滑动条轨迹名。
(2)string类型的winname,用作创建的轨迹栏父窗口的名称。即滑动条依附的窗口名。
(3)int类型的指针value,指向整数变量的可选指针,其值反映滑块的位置。创建时,滑块位置由该变量定义,滑块初始位置就是这个变量当前的值。
(4)int类型的count,滑块的最大位置。最小位置总是0。
(5)TrackbarCallback类型的onChange:指向每次滑块更改位置时要调用的函数的指针。此函数的原型应为
void Foo(int,void\*);其中第一个参数是trackbar位置,第二个参数是用户数据(请参阅下一个参数)。如果回调是空指针,则不调用回调,但只更新值。
(6)void类型的userdata:按原样传递给回调的用户数据,默认为0。它可以用来处理trackbar事件而不使用全局变量。如果第三个值为全局变量,忽略这个值。
讲完API,我们讲一个具体的例子,我们学习了形态学操作,我们希望可以滑动滑动条来控制核大小。
#include#include using namespace std;using namespace cv;Mat src, dst;char inimg[] = "【inputImage】";char outimg[] = "【outputImage】";void changeTrackbar(int pos, void*usrdata) { Mat kernel = getStructuringElement(MORPH_RECT, Size(2*pos+1, 2 * pos + 1), Point(-1, -1)); morphologyEx(src, dst, 0, kernel); imshow(outimg, dst);}int main(){ src = imread("E:/image/girl2.png"); if (!src.data) { cout << "could not load image !"; return -1; } namedWindow(inimg,CV_WINDOW_AUTOSIZE); namedWindow(outimg,CV_WINDOW_AUTOSIZE); imshow(inimg, src); int initValue = 2; int maxSize = 10; createTrackbar("kernel", outimg, &initValue, maxSize, changeTrackbar); waitKey(0); return 0;}
下图为pos为1时,1*2+1 = 3,size为(3*3)
下图为pos为9时,9*2+1 = 19,size为(19*19)
我们通过设置。滑动条,还可以调整形态学操作的类型。
大家应该还记得形态学操作类型会对应到不同的数字:
enum MorphTypes{ MORPH_ERODE = 0, //腐蚀 MORPH_DILATE = 1, //膨胀 MORPH_OPEN = 2, //开操作 MORPH_CLOSE = 3, //闭操作 MORPH_GRADIENT = 4, //梯度操作 MORPH_TOPHAT = 5, //顶帽操作 MORPH_BLACKHAT = 6, //黑帽操作};
所以我们可以通过滑动条来控制不同的类型。这次滑动条的最大值为6。
讲完API,我们讲一个具体的例子,我们学习了形态学操作,我们希望可以滑动滑动条来控制核大小。
#include#include using namespace std;using namespace cv;Mat src, dst;char inimg[] = "【inputImage】";char outimg[] = "【outputImage】";void changeTrackbar(int pos, void*usrdata) { Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1)); morphologyEx(src, dst, pos, kernel); imshow(outimg, dst);}int main(){ src = imread("E:/image/girl2.png"); if (!src.data) { cout << "could not load image !"; return -1; } namedWindow(inimg,CV_WINDOW_AUTOSIZE); namedWindow(outimg,CV_WINDOW_AUTOSIZE); imshow(inimg, src); int initValue = 2; int maxSize = 6; createTrackbar("kernel", outimg, &initValue, maxSize, changeTrackbar); waitKey(0); return 0;}
其他的大家自己做一下测试,今天的内容就讲到这里啦,希望大家能够多多练习,才能真正学懂啊!
转载地址:http://xzyni.baihongyu.com/