openCV学习笔记(二十三) —— 形态学滤波—— 开运算、闭运算、形态学梯度、顶帽、黑帽 本是古典 何须时尚 2021-09-27 07:38 278阅读 0赞 # 原理 # ![70][] ![70 1][] ![70 2][] ![70 3][] ![70 4][] ![70 5][] ![70 6][] # 程序 # #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); } [70]: /images/20210923/256416cebd8f4758b78ab480fd062f9f.png [70 1]: /images/20210923/6be55869fa5c4414be5f6399f38b6930.png [70 2]: /images/20210923/6d3a7a590ae44f309d88eb28a89590f3.png [70 3]: /images/20210923/c210c2550345451eaa1eaeabab256ffd.png [70 4]: /images/20210923/2c645170539b440db591d91f7ddc25d8.png [70 5]: /images/20210923/c5c426a14085429193c6c77a0398f9e8.png [70 6]: /images/20210923/9fc993e221104138b2bcdb9a3f3c1f2c.png
还没有评论,来说两句吧...