形态学滤波—— 开运算、闭运算、形态学梯度、顶帽、黑帽

版权声明:本文为CSDN博主「tiankong19999」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guoyunfei123/article/details/81710535

原理

 

 

 

程序


 
 
  1. #include<opencv2/opencv.hpp>
  2. using namespace std;
  3. using namespace cv;
  4. /*
  5. 宏定义
  6. */
  7. #define ORIGINAL_WINDOW_NAME "【原始图】"
  8. #define OPEN_CLOSE_WINDOW_NAME "【开运算/闭运算】"
  9. #define ERODE_DILATE_WINDOW_NAME "【腐蚀/膨胀】"
  10. #define TOP_BLACK_HAT_WINDOW_NAME "【顶帽/黑帽】"
  11. #define GRADIENT_WINDOW_NAME "形态学梯度"
  12. /*
  13. 全局变量声明
  14. */
  15. Mat g_srcImage, g_dstImage; //原始图和效果图
  16. int g_nElementShape = MORPH_RECT; //元素结构的形状
  17. //变量接收的TrackBar位置参数
  18. int g_nMaxIteratorNum = 10;
  19. int g_nOpenCloseNum = 0;
  20. int g_nErodeDilateNum = 0;
  21. int g_nTopBlackHatNum = 0;
  22. int g_nGradientNum = 0;
  23. /*
  24. 全局函数声明
  25. */
  26. static void onOpenClose(int, void *);
  27. static void onErodeDilate(int, void *);
  28. static void onTopBlackHat(int, void *);
  29. static void onGradient(int, void *);
  30. /*
  31. main()函数
  32. */
  33. int main()
  34. {
  35. //载入原图
  36. g_srcImage = imread( "test.jpg");
  37. if (!g_srcImage.data)
  38. {
  39. printf( "读取srcImage错误!\n");
  40. return -1;
  41. }
  42. //显示原始图
  43. namedWindow(ORIGINAL_WINDOW_NAME);
  44. imshow(ORIGINAL_WINDOW_NAME, g_srcImage);
  45. //创建四个窗口
  46. namedWindow(OPEN_CLOSE_WINDOW_NAME);
  47. namedWindow(ERODE_DILATE_WINDOW_NAME);
  48. namedWindow(TOP_BLACK_HAT_WINDOW_NAME);
  49. namedWindow(GRADIENT_WINDOW_NAME);
  50. //参数赋值
  51. g_nOpenCloseNum = 9;
  52. g_nErodeDilateNum = 9;
  53. g_nTopBlackHatNum = 2;
  54. g_nGradientNum = 9;
  55. //分别为四个窗口创建滚动条
  56. createTrackbar( "迭代值", OPEN_CLOSE_WINDOW_NAME, &g_nOpenCloseNum, g_nMaxIteratorNum * 2 + 1, onOpenClose);
  57. createTrackbar( "迭代值", ERODE_DILATE_WINDOW_NAME, &g_nErodeDilateNum, g_nMaxIteratorNum * 2 + 1, onErodeDilate);
  58. createTrackbar( "迭代值", TOP_BLACK_HAT_WINDOW_NAME, &g_nTopBlackHatNum, g_nMaxIteratorNum * 2 + 1, onTopBlackHat);
  59. createTrackbar( "迭代值", GRADIENT_WINDOW_NAME, &g_nGradientNum, g_nMaxIteratorNum * 2 + 1, onGradient);
  60. //轮询获取按键信息
  61. while ( true)
  62. {
  63. int c;
  64. //执行回调函数
  65. onOpenClose(g_nOpenCloseNum, NULL);
  66. onErodeDilate(g_nErodeDilateNum, NULL);
  67. onTopBlackHat(g_nTopBlackHatNum, NULL);
  68. //获取按键
  69. c = waitKey( 0);
  70. //按下键盘按键Q或者ESC, 程序退出
  71. if (( char)c == 'q' || ( char)c == 27)
  72. {
  73. break;
  74. }
  75. //按下键盘按键1,使用椭圆(Ellipse)结构元素MORPH_ELLIPSE
  76. if (( char)c == 49) //键盘按键1的ASCII码为49
  77. {
  78. printf( "使用椭圆结构元素");
  79. g_nElementShape = MORPH_ELLIPSE;
  80. }
  81. //按下键盘按键2,使用矩形(Rectangle)结构元素MORPH_RECT
  82. else if (( char)c == 50) //键盘按键2的ASCII码为50
  83. {
  84. printf( "使用矩形结构元素");
  85. g_nElementShape = MORPH_RECT;
  86. }
  87. //按下键盘按键3,使用十字形(Cross-shaped)结构元素MORPH_RECT
  88. else if (( char)c == 51) //键盘按键3的ASCII码为50
  89. {
  90. printf( "使用十字形结构元素");
  91. g_nElementShape = MORPH_CROSS;
  92. }
  93. //按下键盘空格,在矩形、椭圆、十字形结构元素中循环
  94. else if (( char)c == ' ')
  95. {
  96. printf( "在矩形、椭圆、十字形结构元素中循环");
  97. g_nElementShape = (g_nElementShape + 1) % 3;
  98. }
  99. }
  100. destroyAllWindows();
  101. return 0;
  102. }
  103. /*
  104. 开运算/闭运算窗口的回调函数
  105. */
  106. static void onOpenClose(int, void *)
  107. {
  108. //偏移量的定义
  109. int offset = g_nOpenCloseNum - g_nMaxIteratorNum; //偏移量
  110. int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量绝对值
  111. //自定义核
  112. Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));
  113. //进行操作
  114. if (offset < 0)
  115. {
  116. printf( "开运算...\n");
  117. morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
  118. }
  119. else
  120. {
  121. printf( "闭运算...\n");
  122. morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
  123. }
  124. imshow(OPEN_CLOSE_WINDOW_NAME, g_dstImage);
  125. }
  126. /*
  127. 腐蚀/膨胀窗口的回调函数
  128. */
  129. static void onErodeDilate(int, void *)
  130. {
  131. //偏移量的定义
  132. int offset = g_nErodeDilateNum - g_nMaxIteratorNum; //偏移量
  133. int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量绝对值
  134. //自定义核
  135. Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));
  136. //进行操作
  137. if (offset < 0)
  138. {
  139. printf( "腐蚀运算...\n");
  140. erode(g_srcImage, g_dstImage, element);
  141. }
  142. else
  143. {
  144. printf( "膨胀运算...\n");
  145. dilate(g_srcImage, g_dstImage, element);
  146. }
  147. imshow(ERODE_DILATE_WINDOW_NAME, g_dstImage);
  148. }
  149. /*
  150. 顶帽/黑帽窗口的回调函数
  151. */
  152. static void onTopBlackHat(int, void *)
  153. {
  154. //偏移量的定义
  155. int offset = g_nTopBlackHatNum - g_nMaxIteratorNum; //偏移量
  156. int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量绝对值
  157. //自定义核
  158. Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));
  159. //进行操作
  160. if (offset < 0)
  161. {
  162. printf( "顶帽运算...\n");
  163. morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
  164. }
  165. else
  166. {
  167. printf( "黑帽运算...\n");
  168. morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
  169. }
  170. imshow(TOP_BLACK_HAT_WINDOW_NAME, g_dstImage);
  171. }
  172. /*
  173. 形态学梯度窗口的回调函数
  174. */
  175. static void onGradient(int, void *)
  176. {
  177. //偏移量的定义
  178. int offset = g_nGradientNum - g_nMaxIteratorNum; //偏移量
  179. int AbsoluteOffset = offset > 0 ? offset : -offset; //偏移量绝对值
  180. //自定义核
  181. Mat element = getStructuringElement(g_nElementShape, Size(AbsoluteOffset * 2 + 1, AbsoluteOffset * 2 + 1), Point(AbsoluteOffset, AbsoluteOffset));
  182. //进行操作
  183. printf( "形态学梯度运算...\n");
  184. morphologyEx(g_srcImage, g_dstImage, MORPH_GRADIENT, element);
  185. imshow(GRADIENT_WINDOW_NAME, g_dstImage);
  186. }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值