OpenCV4入门系列教程测试3:腐蚀膨胀开闭顶帽黑帽综合操作实例

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

上一篇:OpenCV4入门系列教程31:顶帽和黑帽

动态控制腐蚀膨胀开闭顶帽黑帽函数参数,观察其效果。

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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//--------------------------------------【程序说明】-------------------------------------------
// 程序说明:《OpenCV3编程入门》OpenCV3版书本配套示例程序48
// 程序描述:形态学图像处理——开运算、闭运算、形态学梯度、顶帽、黑帽
// 2014年11月 Created by @浅墨_毛星云
// 2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】----------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

//-----------------------------------【全局变量声明部分】-----------------------------------
// 描述:全局变量声明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage; //原始图和效果图
int g_nElementShape = MORPH_RECT; //元素结构的形状

//变量接收的TrackBar位置参数
int g_nMaxIterationNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;

//-----------------------------------【全局函数声明部分】--------------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void *); //回调函数
static void on_ErodeDilate(int, void *); //回调函数
static void on_TopBlackHat(int, void *); //回调函数
static void ShowHelpText();

//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main() {
ShowHelpText();

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

//显示原始图
namedWindow("【原始图】");
imshow("【原始图】", g_srcImage);

//创建三个窗口
namedWindow("【开运算/闭运算】", 1);
namedWindow("【腐蚀/膨胀】", 1);
namedWindow("【顶帽/黑帽】", 1);

//参数赋值
g_nOpenCloseNum = 9;
g_nErodeDilateNum = 9;
g_nTopBlackHatNum = 2;

//分别为三个窗口创建滚动条
createTrackbar("迭代值", "【开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1,
on_OpenClose);
createTrackbar("迭代值", "【腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1,
on_ErodeDilate);
createTrackbar("迭代值", "【顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1,
on_TopBlackHat);

//轮询获取按键信息
while (1) {
int c;

//执行回调函数
on_OpenClose(g_nOpenCloseNum, 0);
on_ErodeDilate(g_nErodeDilateNum, 0);
on_TopBlackHat(g_nTopBlackHatNum, 0);

//获取按键
c = waitKey(0);

//按下键盘按键Q或者ESC,程序退出
if ((char)c == 'q' || (char)c == 27)
break;
//按下键盘按键1,使用椭圆(Elliptic)结构元素结构元素MORPH_ELLIPSE
if ((char)c == 49) //键盘按键1的ASII码为49
g_nElementShape = MORPH_ELLIPSE;
//按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
else if ((char)c == 50) //键盘按键2的ASII码为50
g_nElementShape = MORPH_RECT;
//按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_CROSS
else if ((char)c == 51) //键盘按键3的ASII码为51
g_nElementShape = MORPH_CROSS;
//按下键盘按键space,在矩形、椭圆、十字形结构元素中循环
else if ((char)c == ' ')
g_nElementShape = (g_nElementShape + 1) % 3;
}

return 0;
}

//-----------------------------------【on_OpenClose( )函数】----------------------------------
// 描述:【开运算/闭运算】窗口的回调函数
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void *) {
//偏移量的定义
int offset = g_nOpenCloseNum - g_nMaxIterationNum; //偏移量
int Absolute_offset = offset > 0 ? offset : -offset; //偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape,
Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1),
Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
//此句代码的OpenCV2版为:
// morphologyEx(g_srcImage, g_dstImage, CV_MOP_OPEN, element);
//此句代码的OpenCV3版为:
morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
else
//此句代码的OpenCV2版为:
// morphologyEx(g_srcImage, g_dstImage, CV_MOP_CLOSE, element);
//此句代码的OpenCV3版为:
morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);

//显示图像
imshow("【开运算/闭运算】", g_dstImage);
}

//-----------------------------------【on_ErodeDilate( )函数】----------------------------------
// 描述:【腐蚀/膨胀】窗口的回调函数
//-----------------------------------------------------------------------------------------------
static void on_ErodeDilate(int, void *) {
//偏移量的定义
int offset = g_nErodeDilateNum - g_nMaxIterationNum; //偏移量
int Absolute_offset = offset > 0 ? offset : -offset; //偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape,
Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1),
Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
erode(g_srcImage, g_dstImage, element);
else
dilate(g_srcImage, g_dstImage, element);
//显示图像
imshow("【腐蚀/膨胀】", g_dstImage);
}

//-----------------------------------【on_TopBlackHat( )函数】--------------------------------
// 描述:【顶帽运算/黑帽运算】窗口的回调函数
//----------------------------------------------------------------------------------------------
static void on_TopBlackHat(int, void *) {
//偏移量的定义
int offset = g_nTopBlackHatNum - g_nMaxIterationNum; //偏移量
int Absolute_offset = offset > 0 ? offset : -offset; //偏移量绝对值
//自定义核
Mat element = getStructuringElement(g_nElementShape,
Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1),
Point(Absolute_offset, Absolute_offset));
//进行操作
if (offset < 0)
morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
else
morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
//显示图像
imshow("【顶帽/黑帽】", g_dstImage);
}

//-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText() {
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV3版的第48个配套示例程序\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");

//输出一些帮助信息
printf("\n\t请调整滚动条观察图像效果\n\n");
printf("\n\t按键操作说明: \n\n"
"\t\t键盘按键【ESC】或者【Q】- 退出程序\n"
"\t\t键盘按键【1】- 使用椭圆(Elliptic)结构元素\n"
"\t\t键盘按键【2】- 使用矩形(Rectangle )结构元素\n"
"\t\t键盘按键【3】- 使用十字型(Cross-shaped)结构元素\n"
"\t\t键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环\n");
}

测试效果:

dyna

下一篇:OpenCV4入门系列教程32:图像梯度


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!