OpenCV4入门系列教程29:腐蚀与膨胀

索引地址:系列教程索引地址

上一篇:OpenCV4入门系列教程28:其他阈值算法

OpenCV图片默认背景色为黑色

腐蚀的作用是消除物体边界点,使目标缩小,可以消除小于结构元素的噪声点;

膨胀的作用是将与物体接触的所有背景点合并到物体中,使目标增大,可添补目标中的空洞。

简单来说,腐蚀会放大黑色区域使图片变黑,膨胀会缩小黑色区域使图片变白。

腐蚀

腐蚀函数:

1
2
3
4
5
6
7
8
void cv::erode  (InputArray     src,
OutputArray dst,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar & borderValue =morphologyDefaultBorderValue()
)
  • InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
  • OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。
  • Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于中心。
  • iterations,迭代使用erode()函数的次数,默认值为1。
  • borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
  • borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue,一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter函数得到更详细的解释。

腐蚀膨胀操作需要的核获取腐蚀固定,调用函数获取就行了。

使用erode函数,一般我们只需要填前面的三个参数,后面的四个参数都有默认值。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
//载入原图
Mat srcImage = imread("1.jpg");
//显示原图
imshow("Original", srcImage);
//进行腐蚀操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstImage;
erode(srcImage, dstImage, element);
//显示效果图
imshow("Result", dstImage);
waitKey(0);

return 0;
}

腐蚀结果:

erode

可以看出图片中黑色像素增加了。

膨胀

1
2
3
4
5
6
7
8
void cv::dilate (InputArray      src,
OutputArray dst,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar & borderValue=orphologyDefaultBorderValue()
);

参数为输入,输出,处理核等等,和腐蚀类似。

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
//载入原图
Mat image = imread("1.jpg");
//显示原图
imshow("Original Image", image);

//进行膨胀操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat out;
dilate(image, out, element);

//显示效果图
imshow("Result", out);
waitKey(0);//如果没有,界面会立刻退出

return 0;
}

结果如下:

dilate

结果中白色像素增加,整体变亮。

动态显示

通过滑动栏动态调整参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

//描述:全局变量声明
Mat g_srcImage, g_dstImage;//原始图和效果图
int g_nTrackbarNumer = 0;//0表示腐蚀erode, 1表示膨胀dilate
int g_nStructElementSize = 3; //结构元素(内核矩阵)的尺寸

//描述:全局函数声明
void Process();//膨胀和腐蚀的处理函数
void on_TrackbarNumChange(int, void *);//回调函数
void on_ElementSizeChange(int, void *);//回调函数

int main( )
{
//载入原图
g_srcImage = imread("../data/images/1.jpg");
if( !g_srcImage.data ) { printf("读取srcImage错误~!\n"); return false; }

//显示原始图
imshow("Original", g_srcImage);

//进行初次腐蚀操作并显示效果图
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(2*g_nStructElementSize+1, 2*g_nStructElementSize+1),Point( g_nStructElementSize, g_nStructElementSize ));
erode(g_srcImage, g_dstImage, element);
imshow("Result", g_dstImage);

//创建轨迹条
createTrackbar("腐蚀/膨胀", "Result", &g_nTrackbarNumer, 1, on_TrackbarNumChange);
createTrackbar("内核尺寸", "Result", &g_nStructElementSize, 21, on_ElementSizeChange);

//输出一些帮助信息
cout<<endl<<"\t运行成功,请调整滚动条观察图像效果~\n\n"
<<"\t按下“q”键时,程序退出。\n";

//轮询获取按键信息,若下q键,程序退出
while(char(waitKey(1)) != 'q') {}

return 0;
}

//描述:进行自定义的腐蚀和膨胀操作
void Process()
{
//获取自定义核
Mat element = getStructuringElement(MORPH_RECT, Size(2*g_nStructElementSize+1, 2*g_nStructElementSize+1),Point( g_nStructElementSize, g_nStructElementSize ));

//进行腐蚀或膨胀操作
if(g_nTrackbarNumer == 0) {
erode(g_srcImage, g_dstImage, element);
}
else {
dilate(g_srcImage, g_dstImage, element);
}

//显示效果图
imshow("Result", g_dstImage);
}

//描述:腐蚀和膨胀之间切换开关的回调函数
void on_TrackbarNumChange(int, void *)
{
//腐蚀和膨胀之间效果已经切换,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来
Process();
}

//描述:腐蚀和膨胀操作内核改变时的回调函数
void on_ElementSizeChange(int, void *)
{
//内核尺寸已改变,回调函数体内需调用一次Process函数,使改变后的效果立即生效并显示出来
Process();
}

代码没什么难点,就是函数整合。需要了解前面所说的回调函数。当然了C++不会的话我也没办法。

效果在B站中:腐蚀膨胀动态效果

下一篇:OpenCV4入门系列教程30:开操作与闭操作