havendblog

【opencv入门之八】形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽

参考网站:

http://blog.csdn.net/poem_qianmo/article/details/24599073

 

1、开运算(Opening Operation)

  先腐蚀,后膨胀的过程。

  开运算可以用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。

 

2、闭运算(Closing Operation)

  先膨胀,后腐蚀的过程。

  闭运算能够排除小型黑洞(黑色区域)

 

3、形态学梯度(MorphologicalGradient)

  其为膨胀图与腐蚀图之差。

  可以用形态学梯度来保留物体的边缘轮廓。

 

4、顶帽(Top Hat)

  又称“礼帽”运算,其为原图像与 “开运算” 的结果图之差。

  开运算的结果,放大了裂缝或者局部低亮度的区域。

  所以顶帽的结果,突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。

  顶帽运算用来分离比领近点亮一些的斑块。

  当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取 。

 

5、黑帽(Black Hat)

  “闭运算”的结果与原图像之差。

  黑帽运算后的效果突出了比原图轮廓周围的区域更暗的区域,这一操作和选择的核的大小相关。

  黑帽运算用来分离比领近点暗一些的斑块。

 

6、morphologyEx函数

void morphologyEx(  
          InputArray src,  
          OutputArray dst,  
          int op,        //表示形态学运算的类型
          InputArraykernel,    //形态学运算的内核,使用getStructuringElement()函数
          Pointanchor=Point(-1,-1),
          intiterations=1,
          intborderType=BORDER_CONSTANT,
          constScalar& borderValue=morphologyDefaultBorderValue() );

  第三个参数可以选择如下:

    • MORPH_OPEN:开运算(opening operation)
    • MORPH_CLOSE:闭运算(Closing operation)
    • MORPH_GRADIENT:形态学梯度(Morphological gradient)
    • MORPH_TOPHAT:顶帽(“Top hat”)
    • MORPH_BLACKHAT:黑帽(“Black hat”)

 

7、综合实践

  1 //******************************【程序说明】*****************************
  2 //    程序名称:形态学图像处理(二):开运算、闭运算、形态学梯度、顶帽、黑帽
  3 //    opencv版本:2.4.13
  4 //    日期:2017/9/21
  5 //**********************************************************************
  6 
  7 
  8 //******************************【头文件包含部分】*****************************
  9 //    描述:包含程序所依赖的头文件
 10 //*****************************************************************************
 11 #include <opencv2/core/core.hpp>
 12 #include <opencv2/highgui/highgui.hpp>
 13 #include <opencv2/imgproc/imgproc.hpp>
 14 //#include <iostream>
 15 
 16 
 17 //******************************【命名空间声明部分】*****************************
 18 //    描述:包含程序所使用的命名空间
 19 //*****************************************************************************
 20 using namespace std;
 21 using namespace cv;
 22 
 23 
 24 //******************************【全局变量声明部分】*****************************
 25 //    描述:全局变量声明
 26 //*****************************************************************************
 27 Mat g_srcImage, g_dstImage;    //原始图、效果图
 28 int g_nElementShape = MORPH_RECT;    //元素结构的运算
 29 
 30 //变量接收的TrackBar位置参数
 31 int g_nMaxIterationNum = 10;
 32 int g_nOpenCloseNum = 0;
 33 int g_nErodeDilateNum = 0;
 34 int g_nTopBlackHatNum = 0;
 35 
 36 
 37 //******************************【全局函数声明部分】*****************************
 38 //    描述:全局函数声明
 39 //*****************************************************************************
 40 static void on_OpenClose( int, void* );    //回调函数
 41 static void on_ErodeDilate ( int, void* );    //回调函数
 42 static void on_TopBlackHat( int, void* );    //回调函数
 43 static void ShowHelpText();                //帮助文字显示
 44 
 45 
 46 //******************************【main()部分】*****************************
 47 //    描述:控制台应用程序的入口函数,我们的程序从这里开始
 48 //*****************************************************************************
 49 int main()
 50 {
 51     //【0】初始化
 52     system("color 2F");
 53     ShowHelpText();
 54 
 55     //【1】读取原图
 56     g_srcImage = imread( "1.jpg", 1 );    //工程目录下需要有一张名为1.jpg的素材图
 57     if(!g_srcImage.data) { printf("Oh,no,读取srcImage错误!!!!\n"); return false; }
 58 
 59     //【2】显示原图
 60     namedWindow("【<0>原图窗口】", 1 );
 61     imshow("【<0>原图窗口】", g_srcImage );
 62 
 63     //【3】创建三个窗口
 64     namedWindow("【<1>开运算/闭运算】", 1);
 65     namedWindow("【<2>腐蚀/膨胀】", 1);
 66     namedWindow("【<3>顶帽/黑帽】", 1);
 67 
 68     //【4】参数赋值
 69     g_nOpenCloseNum = 9;
 70     g_nErodeDilateNum = 9;
 71     g_nTopBlackHatNum = 2;
 72 
 73     //【5】分别为三个窗口创建轨迹条
 74     createTrackbar( "迭代值", "【<1>开运算/闭运算】", &g_nOpenCloseNum, g_nMaxIterationNum*2+1, on_OpenClose );
 75     createTrackbar( "迭代值", "【<2>腐蚀/膨胀】", &g_nErodeDilateNum, g_nMaxIterationNum*2+1, on_ErodeDilate );
 76     createTrackbar( "迭代值", "【<3>顶帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum*2+1, on_TopBlackHat );
 77     
 78     //【5】轮询获取按键信息
 79     while(1)
 80     {
 81         int c;
 82 
 83         //【1】执行回调函数
 84         on_OpenClose( g_nOpenCloseNum, 0 );
 85         on_ErodeDilate( g_nErodeDilateNum, 0 );
 86         on_TopBlackHat( g_nTopBlackHatNum, 0 );
 87 
 88         //【2】获取按键
 89         c = waitKey(0);
 90 
 91         //【3】按下键盘Q或者ESC,程序退出
 92         if( (char)c==\'q\' || (char)c==27 )    
 93             break;
 94 
 95         //【4】按下键盘1、2、3或者空格,结构元素矩形、椭圆、十字循环改变
 96         if( (char)c == 49 )//键盘按键1,使用椭圆结构元素
 97             g_nElementShape = MORPH_ELLIPSE;
 98         else if( (char)c == 50 )//键盘按键2,使用矩形结构元素
 99             g_nElementShape = MORPH_RECT;
100         else if( (char)c == 51 )//键盘按键3,使用十字结构元素
101             g_nElementShape = MORPH_CROSS;
102         else if( (char)c == \' \' )
103             g_nElementShape = (g_nElementShape + 1) % 3; 
104 
105     }
106 
107     return 0;
108 }
109 
110 
111 //******************************【on_OpenClose()部分】*****************************
112 //    描述:【开运算/闭运算】窗口的回调函数
113 //*****************************************************************************
114 static void on_OpenClose( int, void* )
115 {
116     //【0】偏移量的定义
117     int offset = g_nOpenCloseNum - g_nMaxIterationNum;    //偏移量
118     int Absolute_offset = offset > 0 ? offset : -offset;    //偏移量绝对值
119 
120     //【1】自定义核
121     Mat element = getStructuringElement( g_nElementShape,
122                                             Size(Absolute_offset*2+1, Absolute_offset*2+1),
123                                             Point(Absolute_offset,Absolute_offset));
124 
125     //【2】进行操作
126     if(offset < 0)
127         morphologyEx( g_srcImage, g_dstImage, CV_MOP_OPEN, element );
128     else
129         morphologyEx( g_srcImage, g_dstImage, CV_MOP_CLOSE, element );
130 
131     //【3】显示效果图
132     imshow("【<1>开运算/闭运算】", g_dstImage);
133 }
134 
135 
136 
137 //******************************【on_ErodeDilate()部分】*****************************
138 //    描述:【腐蚀/膨胀】窗口的回调函数
139 //*****************************************************************************
140 static void on_ErodeDilate( int, void* )
141 {
142     //【0】偏移量的定义
143     int offset = g_nErodeDilateNum - g_nMaxIterationNum;    //偏移量
144     int Absolute_offset = offset > 0 ? offset : -offset;    //偏移量绝对值
145 
146     //【1】自定义核
147     Mat element = getStructuringElement( g_nElementShape,
148                                             Size(Absolute_offset*2+1, Absolute_offset*2+1),
149                                             Point(Absolute_offset,Absolute_offset));
150 
151     //【2】进行操作
152     if(offset < 0)
153         erode( g_srcImage, g_dstImage, element );
154     else
155         dilate( g_srcImage, g_dstImage, element );
156 
157     //【3】显示效果图
158     imshow("【<2>腐蚀/膨胀】", g_dstImage);
159 }
160 
161 
162 
163 //******************************【on_TopBlackHat()部分】*****************************
164 //    描述:【顶帽运算/黑帽运算】窗口的回调函数
165 //*****************************************************************************
166 static void on_TopBlackHat( int, void* )
167 {
168     //【0】偏移量的定义
169     int offset = g_nTopBlackHatNum - g_nMaxIterationNum;    //偏移量
170     int Absolute_offset = offset > 0 ? offset : -offset;    //偏移量绝对值
171 
172     //【1】自定义核
173     Mat element = getStructuringElement( g_nElementShape,
174                                             Size(Absolute_offset*2+1, Absolute_offset*2+1),
175                                             Point(Absolute_offset,Absolute_offset));
176 
177     //【2】进行操作
178     if(offset < 0)
179         morphologyEx( g_srcImage, g_dstImage, MORPH_TOPHAT, element );
180     else
181         morphologyEx( g_srcImage, g_dstImage, MORPH_BLACKHAT, element );
182 
183     //【3】显示效果图
184     imshow("【<3>顶帽/黑帽】", g_dstImage);
185 }
186 
187 
188 //******************************【ShowHelpText()部分】*****************************
189 //    描述:输出一些帮助信息
190 //*****************************************************************************
191 static void ShowHelpText()
192 {
193     //输出一些帮助信息
194     printf("\n\n\n\t请调整滚动条观察图像效果!!\n\n");
195     printf("\n\n\t按键操作说明:\n\n"
196         "\t\t键盘按键【ESC】或者【Q】- 退出程序\n"  
197         "\t\t键盘按键【1】- 使用椭圆(Elliptic)结构元素\n"  
198         "\t\t键盘按键【2】- 使用矩形(Rectangle )结构元素\n"  
199         "\t\t键盘按键【3】- 使用十字型(Cross-shaped)结构元素\n"  
200         "\t\t键盘按键【空格SPACE】- 在矩形、椭圆、十字形结构元素中循环\n"  
201         "\n\n\t\t\t\t\t\t\t\t by浅墨"  
202         );  
203 }

 

分类:

技术点:

相关文章: