【opencv学习笔记】012之形态学操作应用(trackbar应用)

一、前言

继续填坑。

如果想看其他有关于OpenCV学习方法介绍、学习教程、代码实战、常见报错及解决方案等相关内容,可以直接看我的OpenCV分类:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

如果你想了解更多有关于计算机视觉、OpenCV、机器学习、深度学习等相关技术的内容,想与更多大佬一起沟通,那就扫描下方二维码加入我们吧!

二、形态学操作

1、回顾

首先我们先回顾一下形态学操作。

首先我们学习了形态学的两个基本操作,分别是:膨胀和腐蚀。

(1)膨胀:跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。

因为是最大像素,所以对于二值图像来说,膨胀就是可以让白色区域膨胀扩大。

(2)腐蚀:腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值。

因为是最小像素,所以对于二值图像来说,辅食就是黑色腐蚀区域扩大。

接下来我们学习了5个形态学操作,分别如下:

(1)开操作:先腐蚀后膨胀,可以去掉小的对象。

(2)闭操作:先膨胀后腐蚀,可以填充小对象。

(3)形态学梯度:膨胀减去腐蚀。

(4)顶帽:顶帽是原图像与开操作图像之间的差值图像。

(5)黑帽:黑帽是闭操作图像与原图像之间的差值图像。

今天我们来学习一下形态学两个非常重要的应用。

三、OpenCV中的形态学应用-滑动条应用

1、滑动条用于核

之前,我们每次使用形态学操作,需要设置核,核的大小需要我们自己设置,每次想要调整,都是需要不断停止运行,修改代码,然后再执行,这样太慢了,我们能不能运行的过程中,通过调整滑动条,让它自动调整核的大小呢?

opencv提供了trackbar功能。我们可以创建一个trackbar来动态调整核的大小,这样,我们就不用每次都重新修改代码,重新编译了。

创建trackbar的API是createTrackbar()

1.API

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事件而不使用全局变量。如果第三个值为全局变量,忽略这个值。

 

2.代码展示

讲完API,我们讲一个具体的例子,我们学习了形态学操作,我们希望可以滑动滑动条来控制核大小。

#include<opencv2\opencv.hpp>
#include<iostream>

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;
}

3.执行结果

原图

下图为pos为1时,1*2+1 = 3,size为(3*3)

Size = (3,3)

下图为pos为9时,9*2+1 = 19,size为(19*19)  

Size = (19,19)

2、滑动条用于类型

我们通过设置。滑动条,还可以调整形态学操作的类型。

大家应该还记得形态学操作类型会对应到不同的数字:

enum MorphTypes{
    MORPH_ERODE    = 0,  //腐蚀
    MORPH_DILATE   = 1,  //膨胀
    MORPH_OPEN     = 2,  //开操作
    MORPH_CLOSE    = 3,  //闭操作
    MORPH_GRADIENT = 4,  //梯度操作
    MORPH_TOPHAT   = 5,  //顶帽操作
    MORPH_BLACKHAT = 6,  //黑帽操作
};

所以我们可以通过滑动条来控制不同的类型。这次滑动条的最大值为6。

2.代码展示

讲完API,我们讲一个具体的例子,我们学习了形态学操作,我们希望可以滑动滑动条来控制核大小。

#include<opencv2\opencv.hpp>
#include<iostream>

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;
}

3.执行结果

原图

其他的大家自己做一下测试,今天的内容就讲到这里啦,希望大家能够多多练习,才能真正学懂啊!

发布了251 篇原创文章 · 获赞 506 · 访问量 51万+

猜你喜欢

转载自blog.csdn.net/shuiyixin/article/details/104387257