形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽
一、开运算
开运算,就是先腐蚀后膨胀的过程
数学表达式:
dst = open(src,element) = dilate(erode(src, element))
开运算可以用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积。
二、闭运算
闭运算,就是先膨胀后腐蚀的过程
数学表达式:
dst = open(src,element) = erode(dilate(src, element))
闭运算可以用来排除小型黑洞(黑色区域)
三、形态学梯度
形态学梯度,就是膨胀图与腐蚀图之差
数学表达式:
dst = morph-grad(src,element) = dilate(src, element) -erode(src, element)
对二值图进行这一操作可以将团块的边缘突出出来,我们可以用形态学梯度来保留物体的边缘轮廓
四、顶帽
顶帽(礼帽)运算,就是原图像与“开运算”的结果图之差
数学表达式:
dst = tophat(src,element) = src -open(src,element)
因为开运算带来的结果是放大了裂缝或者局部低亮度的区域。因此从原图中减去开运算后的图,得到的效果
图突出了比原图轮廓周围的区域更明亮的区域,且这一操作与选择的核的的大小相关。
顶帽运算往往用来分离比临近点亮一些的斑块,在一幅图像具有大幅的背景,而微小物品比较有规律的情况下,
可以使用顶帽运算进行背景提取
五、黑帽
黑帽运算,就是“闭运算”的结果图与原图像之差
数学表达式:
dst = blackhat(src,element) = close(src,element) -src
黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关
黑帽运算用来分离比临近点暗一些的斑块,效果图有着非常完美的轮廓
六、核心函数:morphologyEx()
1 void morphologyEx( InputArray src, OutputArray dst, 2 int op, InputArray kernel, 3 Point anchor = Point(-1,-1), int iterations = 1, 4 int borderType = BORDER_CONSTANT, 5 const Scalar& borderValue = morphologyDefaultBorderValue() );
1 #include<opencv2/opencv.hpp>
2 #include<iostream>
3
4 using namespace std;
5 using namespace cv;
6
7 Mat g_srcImage, g_dstImage;
8 int g_nElementShap = MORPH_RECT; //元素结构的形状
9
10 //变量接收的TrackBar位置参数
11 int g_nMaxIterationNum = 10;
12 int g_nOpenCloseNum = 0;
13 int g_nErodeDilateNum = 0;
14 int g_nTopBlackHatNum = 0;
15
16 static void on_OpenClose(int, void *); //回调函数
17 static void on_ErodeDilate(int, void *);
18 static void on_TopBlackHat(int, void *);
19
20
21 int main()
22 {
23 //载入原图
24 g_srcImage = imread("C:\Users\Administrator\Pictures\Camera Roll\05.jpg");
25 if (!g_srcImage.data) {
26 cout << "图片载入失败!" << endl;
27 return false;
28 }
29
30 //显示原始图
31 namedWindow("【原始图】");
32 imshow("【原始图】", g_srcImage);
33
34 //创建三个窗口
35 namedWindow("【开运算/闭运算】", 1);
36 namedWindow("【腐蚀/膨胀】", 1);
37 namedWindow("【顶帽/黑帽】", 1);
38
39 //分别为三个窗口创建滚动条
40 createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose);
41 createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate);
42 createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);
43
44 //轮询获取按键信息
45 while (1)
46 {
47 int c;
48
49 //执行回调函数
50 on_OpenClose(g_nOpenCloseNum, 0);
51 on_ErodeDilate(g_nErodeDilateNum, 0);
52 on_TopBlackHat(g_nTopBlackHatNum, 0);
53
54 //获取按键
55 c = waitKey(0);
56
57 //按下键盘Q或者ESC,程序退出
58 if (c == 'q' || c == 27)
59 break;
60 //按下键盘按键1,使用椭圆(Elliptic)结构元素MORPH_ELLIPSE
61 if (c == 'a')
62 g_nElementShap = MORPH_ELLIPSE;
63 //按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
64 if (c == 'b')
65 g_nElementShap = MORPH_RECT;
66 //按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_CROSS
67 if (c == 'c')
68 g_nElementShap = MORPH_CROSS;
69 //按下键盘按键space,在矩形、椭圆、十字形结构元素中循环
70 if (c == ' ')
71 g_nElementShap = (g_nElementShap + 1) % 3;
72 }
73 return 0;
74 }
75 static void on_OpenClose(int, void *) {
76 //偏移量的定义
77 int offset = g_nOpenCloseNum - g_nMaxIterationNum; //偏移量
78 int Absolute_offset = offset > 0 ? offset : -offset; //偏移量的绝对值
79 //自定义核
80 Mat element = getStructuringElement(g_nElementShap, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
81
82 //进行操作
83 if (offset < 0)
84 morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
85 else
86 morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
87
88 //显示图像
89 imshow("【开运算/闭运算】", g_dstImage);
90 }
91
92 static void on_ErodeDilate(int, void *) {
93 int offset = g_nOpenCloseNum - g_nMaxIterationNum; //偏移量
94 int Absolute_offset = offset > 0 ? offset : -offset; //偏移量的绝对值
95 //自定义核
96 Mat element = getStructuringElement(g_nElementShap, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
97
98 //进行操作
99 if (offset < 0)
100 erode(g_srcImage, g_dstImage, element);
101 else
102 dilate(g_srcImage, g_dstImage, element);
103
104 //显示图像
105 imshow("【腐蚀/膨胀】", g_dstImage);
106 }
107
108 static void on_TopBlackHat(int, void *) {
109 int offset = g_nOpenCloseNum - g_nMaxIterationNum; //偏移量
110 int Absolute_offset = offset > 0 ? offset : -offset; //偏移量的绝对值
111 //自定义核
112 Mat element = getStructuringElement(g_nElementShap, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
113
114 //进行操作
115 if (offset < 0)
116 morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
117 else
118 morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
119
120 //显示图像
121 imshow("【顶帽/黑帽】", g_dstImage);
122 }
123
总结
以上是生活随笔为你收集整理的形态学滤波(2):开运算、闭运算、形态学梯度、顶帽、黑帽的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 体温计腋下要量多久
- 下一篇: 浑浑噩噩是什么意思(形容荒废度日的成语)