继续填坑。
如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:
【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855
如果你想了解更多有关于计算机视觉、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;
}
其他的大家自己做一下测试,今天的内容就讲到这里啦,希望大家能够多多练习,才能真正学懂啊!