原理
程序
#include
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);
}