版权声明:本文为优快云博主「tiankong19999」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/guoyunfei123/article/details/81710535
原理
程序
-
#include<opencv2/opencv.hpp>
-
-
using
namespace
std;
-
using
namespace cv;
-
-
/*
-
宏定义
-
*/
-
#define ORIGINAL_WINDOW_NAME "【原始图】"
-
#define OPEN_CLOSE_WINDOW_NAME "【开运算/闭运算】"
-
#define ERODE_DILATE_WINDOW_NAME "【腐蚀/膨胀】"
-
#define TOP_BLACK_HAT_WINDOW_NAME "【顶帽/黑帽】"
-
#define GRADIENT_WINDOW_NAME "形态学梯度"
-
-
/*
-
全局变量声明
-
*/
-
Mat g_srcImage, g_dstImage;
//原始图和效果图
-
int g_nElementShape = MORPH_RECT;
//元素结构的形状
-
-
//变量接收的TrackBar位置参数
-
int g_nMaxIteratorNum =
10;
-
int g_nOpenCloseNum =
0;
-
int g_nErodeDilateNum =
0;
-
int g_nTopBlackHatNum =
0;
-
int g_nGradientNum =
0;
-
-
/*
-
全局函数声明
-
*/
-
static void onOpenClose(int, void *);
-
static void onErodeDilate(int, void *);
-
static void onTopBlackHat(int, void *);
-
static void onGradient(int, void *);
-
-
/*
-
main()函数
-
*/
-
int main()
-
{
-
//载入原图
-
g_srcImage = imread(
"test.jpg");
-
if (!g_srcImage.data)
-
{
-
printf(
"读取srcImage错误!\n");
-
return
-1;
-
}
-
-
//显示原始图
-
namedWindow(ORIGINAL_WINDOW_NAME);
-
imshow(ORIGINAL_WINDOW_NAME, g_srcImage);
-
-
//创建四个窗口
-
namedWindow(OPEN_CLOSE_WINDOW_NAME);
-
namedWindow(ERODE_DILATE_WINDOW_NAME);
-
namedWindow(TOP_BLACK_HAT_WINDOW_NAME);
-
namedWindow(GRADIENT_WINDOW_NAME);
-
-
//参数赋值
-
g_nOpenCloseNum =
9;
-
g_nErodeDilateNum =
9;
-
g_nTopBlackHatNum =
2;
-
g_nGradientNum =
9;
-
-
//分别为四个窗口创建滚动条
-
createTrackbar(
"迭代值", OPEN_CLOSE_WINDOW_NAME, &g_nOpenCloseNum, g_nMaxIteratorNum *
2 +
1, onOpenClose);
-
createTrackbar(
"迭代值", ERODE_DILATE_WINDOW_NAME, &g_nErodeDilateNum, g_nMaxIteratorNum *
2 +
1, onErodeDilate);
-
createTrackbar(
"迭代值", TOP_BLACK_HAT_WINDOW_NAME, &g_nTopBlackHatNum, g_nMaxIteratorNum *
2 +
1, onTopBlackHat);
-
createTrackbar(
"迭代值", GRADIENT_WINDOW_NAME, &g_nGradientNum, g_nMaxIteratorNum *
2 +
1, onGradient);
-
-
//轮询获取按键信息
-
while (
true)
-
{
-
int c;
-
-
//执行回调函数
-
onOpenClose(g_nOpenCloseNum,
NULL);
-
onErodeDilate(g_nErodeDilateNum,
NULL);
-
onTopBlackHat(g_nTopBlackHatNum,
NULL);
-
-
//获取按键
-
c = waitKey(
0);
-
-
//按下键盘按键Q或者ESC, 程序退出
-
if ((
char)c ==
'q' || (
char)c ==
27)
-
{
-
break;
-
}
-
-
//按下键盘按键1,使用椭圆(Ellipse)结构元素MORPH_ELLIPSE
-
if ((
char)c ==
49)
//键盘按键1的ASCII码为49
-
{
-
printf(
"使用椭圆结构元素");
-
g_nElementShape = MORPH_ELLIPSE;
-
}
-
//按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
-
else
if ((
char)c ==
50)
//键盘按键2的ASCII码为50
-
{
-
printf(
"使用矩形结构元素");
-
g_nElementShape = MORPH_RECT;
-
}
-
//按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_RECT
-
else
if ((
char)c ==
51)
//键盘按键3的ASCII码为50
-
{
-
printf(
"使用十字形结构元素");
-
g_nElementShape = MORPH_CROSS;
-
}
-
//按下键盘空格,在矩形、椭圆、十字形结构元素中循环
-
else
if ((
char)c ==
' ')
-
{
-
printf(
"在矩形、椭圆、十字形结构元素中循环");
-
g_nElementShape = (g_nElementShape +
1) %
3;
-
}
-
}
-
-
destroyAllWindows();
-
-
return
0;
-
}
-
-
/*
-
开运算/闭运算窗口的回调函数
-
*/
-
static void onOpenClose(int, void *)
-
{
-
//偏移量的定义
-
int offset = g_nOpenCloseNum - g_nMaxIteratorNum;
//偏移量
-
int AbsoluteOffset = offset >
0 ? offset : -offset;
//偏移量绝对值
-
-
//自定义核
-
Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset *
2 +
1, AbsoluteOffset *
2 +
1), Point(AbsoluteOffset, AbsoluteOffset));
-
-
//进行操作
-
if (offset <
0)
-
{
-
printf(
"开运算...\n");
-
morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
-
}
-
else
-
{
-
printf(
"闭运算...\n");
-
morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
-
}
-
-
imshow(OPEN_CLOSE_WINDOW_NAME, g_dstImage);
-
}
-
-
/*
-
腐蚀/膨胀窗口的回调函数
-
*/
-
static void onErodeDilate(int, void *)
-
{
-
//偏移量的定义
-
int offset = g_nErodeDilateNum - g_nMaxIteratorNum;
//偏移量
-
int AbsoluteOffset = offset >
0 ? offset : -offset;
//偏移量绝对值
-
-
//自定义核
-
Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset *
2 +
1, AbsoluteOffset *
2 +
1), Point(AbsoluteOffset, AbsoluteOffset));
-
-
//进行操作
-
if (offset <
0)
-
{
-
printf(
"腐蚀运算...\n");
-
erode(g_srcImage, g_dstImage, element);
-
}
-
else
-
{
-
printf(
"膨胀运算...\n");
-
dilate(g_srcImage, g_dstImage, element);
-
}
-
-
imshow(ERODE_DILATE_WINDOW_NAME, g_dstImage);
-
}
-
-
/*
-
顶帽/黑帽窗口的回调函数
-
*/
-
static void onTopBlackHat(int, void *)
-
{
-
//偏移量的定义
-
int offset = g_nTopBlackHatNum - g_nMaxIteratorNum;
//偏移量
-
int AbsoluteOffset = offset >
0 ? offset : -offset;
//偏移量绝对值
-
-
//自定义核
-
Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset *
2 +
1, AbsoluteOffset *
2 +
1), Point(AbsoluteOffset, AbsoluteOffset));
-
-
//进行操作
-
if (offset <
0)
-
{
-
printf(
"顶帽运算...\n");
-
morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
-
}
-
else
-
{
-
printf(
"黑帽运算...\n");
-
morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
-
}
-
-
imshow(TOP_BLACK_HAT_WINDOW_NAME, g_dstImage);
-
}
-
-
-
/*
-
形态学梯度窗口的回调函数
-
*/
-
static void onGradient(int, void *)
-
{
-
//偏移量的定义
-
int offset = g_nGradientNum - g_nMaxIteratorNum;
//偏移量
-
int AbsoluteOffset = offset >
0 ? offset : -offset;
//偏移量绝对值
-
-
//自定义核
-
Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset *
2 +
1, AbsoluteOffset *
2 +
1), Point(AbsoluteOffset, AbsoluteOffset));
-
-
//进行操作
-
printf(
"形态学梯度运算...\n");
-
morphologyEx(g_srcImage, g_dstImage, MORPH_GRADIENT, element);
-
-
imshow(GRADIENT_WINDOW_NAME, g_dstImage);
-
}