opencv学习--图像形态学处理

      主要形态学操作有 膨胀、腐蚀 、开运算,闭运算,形态学梯度,顶帽,黑帽。对其原理及opencv的实现进行总结。

      参考博客及资料如下:图像处理--形态学https://blog.csdn.net/yangleo1987/article/details/53168423                                     http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.html

   

      形态学,即数学形态学(mathematical Morphology),是图像处理中应用最为广泛的技术之一,主要用于从图像中提取对表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质〈最具区分能力-most discriminative)的形状特征,如边界和连通区域等。同时像细化、像素化和修剪毛刺等技术也常应用于图像的预处理和后处理中,成为图像增强技术的有力补充。

       膨胀与腐蚀是图像形态学中最基本的操作,也是其他形态学操作的基础。

      膨胀与腐蚀能够实现以下作用:

   (1)消除噪声

   (2)分割出独立的图像元素,在图像中连接相邻的元素

   (3)寻找图像中的明显的极大值区域或者极小值区域

   (4)求出图像的梯度

       腐蚀和膨胀都是对图像的白色部分(高亮部分)而言。膨胀是图像中的高亮部分进行膨胀,类似于领域扩张,效果图拥有比原图更大的高亮区域;腐蚀是原图的高亮部分被腐蚀,类似于领域被蚕食,效果图拥有比原图更小的高亮区域。

       从数学的角度来说,膨胀和腐蚀操作就是将图像与核进行卷积,核可以是任意形状和大小的。

1. 腐蚀(erode)

       腐蚀就是求局部最小值的操作。核B与图像卷积,即计算核B覆盖的区域的像素点的最小值,并把这个最小值赋值给参考点指定的像素。这样就会使图像中高亮区域逐渐减少。

2.膨胀(dilate)

       膨胀就是求局部最大值的操作。核B与图像卷积,即计算核B覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中高亮区域逐渐增长。

     膨胀和腐蚀的opencv实现如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "highgui.h"
#include 
#include 

using namespace cv;

/// 全局变量
Mat src, erosion_dst, dilation_dst;

int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;

/** Function Headers */
void Erosion( int, void* );
void Dilation( int, void* );

/** @function main */
int main( int argc, char** argv )
{
  /// Load 图像
  src = imread( argv[1] );

  if( !src.data )
  { return -1; }

  /// 创建显示窗口
  namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );
  namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );
  cvMoveWindow( "Dilation Demo", src.cols, 0 );

  /// 创建腐蚀 Trackbar
  createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo",
                  &erosion_elem, max_elem,
                  Erosion );

  createTrackbar( "Kernel size:\n 2n +1", "Erosion Demo",
                  &erosion_size, max_kernel_size,
                  Erosion );

  /// 创建膨胀 Trackbar
  createTrackbar( "Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo",
                  &dilation_elem, max_elem,
                  Dilation );

  createTrackbar( "Kernel size:\n 2n +1", "Dilation Demo",
                  &dilation_size, max_kernel_size,
                  Dilation );

  /// Default start
  Erosion( 0, 0 );
  Dilation( 0, 0 );

  waitKey(0);
  return 0;
}

/**  @function Erosion  */
void Erosion( int, void* )
{
  int erosion_type;
  if( erosion_elem == 0 ){ erosion_type = MORPH_RECT; }
  else if( erosion_elem == 1 ){ erosion_type = MORPH_CROSS; }
  else if( erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }

  Mat element = getStructuringElement( erosion_type,
                                       Size( 2*erosion_size + 1, 2*erosion_size+1 ),
                                       Point( erosion_size, erosion_size ) );

  /// 腐蚀操作
  erode( src, erosion_dst, element );
  imshow( "Erosion Demo", erosion_dst );
}

/** @function Dilation */
void Dilation( int, void* )
{
  int dilation_type;
  if( dilation_elem == 0 ){ dilation_type = MORPH_RECT; }
  else if( dilation_elem == 1 ){ dilation_type = MORPH_CROSS; }
  else if( dilation_elem == 2) { dilation_type = MORPH_ELLIPSE; }

  Mat element = getStructuringElement( dilation_type,
                                       Size( 2*dilation_size + 1, 2*dilation_size+1 ),
                                       Point( dilation_size, dilation_size ) );
  ///膨胀操作
  dilate( src, dilation_dst, element );
  imshow( "Dilation Demo", dilation_dst );
}

运用膨胀和腐蚀这两个基本操作,可实现较高级的形态学变换,如 开运算,闭运算,形态学梯度,顶帽,黑帽。

3.开运算

      开运算其实就是先腐蚀再膨胀。

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

4.闭运算

       闭运算其实就是先膨胀再腐蚀。闭运算能够排除小型黑洞(黑色区域)。

5形态学梯度

       形态学梯度就是膨胀图与腐蚀图之差。

       对二值图像进行这一操作,可以将团块的边缘突出出来,我们可以用形态梯度来保留物体的边缘轮廓。

6.顶帽

        顶帽就是原图与开运算图之差。

        因为开运算带来的结果是放大了裂痕或者局部低亮度的区域。因此,从原图中减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作与选择的核的大小有关。

        顶帽运算往往用来分离比邻近点亮一些的斑块,在一幅图像具有大幅的背景,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。

7 黑帽

        黑帽就是原图与闭运算图之差。

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

        黑帽运算用来分离比临近点暗一点的斑块,效果图有着非常完美的轮廓。

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
#include 

using namespace cv;

/// 全局变量
Mat src, dst;

int morph_elem = 0;
int morph_size = 0;
int morph_operator = 0;
int const max_operator = 4;
int const max_elem = 2;
int const max_kernel_size = 21;

char* window_name = "Morphology Transformations Demo";

/** 回调函数申明 */
void Morphology_Operations( int, void* );

/** @函数 main */
int main( int argc, char** argv )
{
  /// 装载图像
  src = imread( argv[1] );

  if( !src.data )
  { return -1; }

 /// 创建显示窗口
 namedWindow( window_name, CV_WINDOW_AUTOSIZE );

 /// 创建选择具体操作的 trackbar
 createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );

 /// 创建选择内核形状的 trackbar
 createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
                 &morph_elem, max_elem,
                 Morphology_Operations );

 /// 创建选择内核大小的 trackbar
 createTrackbar( "Kernel size:\n 2n +1", window_name,
                 &morph_size, max_kernel_size,
                 Morphology_Operations );

 /// 启动使用默认值
 Morphology_Operations( 0, 0 );

 waitKey(0);
 return 0;
 }

 /**
  * @函数 Morphology_Operations
  */
void Morphology_Operations( int, void* )
{
  // 由于 MORPH_X的取值范围是: 2,3,4,5 和 6
  int operation = morph_operator + 2;

  Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );

  /// 运行指定形态学操作
  morphologyEx( src, dst, operation, element );
  imshow( window_name, dst );
  }

 

你可能感兴趣的:(opencv学习,opencv,形态学,膨胀,腐蚀)