OpenCV 系列 --- 形态学操作(膨胀、腐蚀)

来源:互联网 发布:淘宝怎么申请ifashion 编辑:程序博客网 时间:2024/05/19 16:04

形态学操作是基于形状的一系列图像处理操作,基本的运算包括:腐蚀、膨胀、开、闭等。在进行其他算法研发时,我基本只用膨胀与腐蚀操作,因此本文只介绍这两种操作,其他的可以相似地进行。

关键点

  1. 操作是对图像中的高亮区域进行的,比如膨胀,就是将图像中的高亮区域扩大。
  2. 它们可以达到的目的
    • 去除噪声
    • 分离出独立的元素或者连接独立的元素
    • 可以求图像梯度或者图像中的小洞

测试用图

为了更加清晰地显示出操作前后的差距,采用如下图所示的二值图
这里写图片描述
一定要注意,形态学操作不光可以用在二值图,也可以用在灰度图,甚至可以用在彩色图。

基本原理

  1. 膨胀
    膨胀就是利用一个核(叫做结构元素)与图像进行卷积。随着核的移动,每次都取核覆盖区域的最大像素值,因此最终完成的效果是将高亮区域扩大。
  2. 腐蚀
    同样地,腐蚀也是卷积操作。随着核的移动,每次都取核覆盖区域的最小像素值,因此最终完成的效果是将高亮区域缩小。

代码示例

以下代码是OpenCV文档中给出的一段代码,比较能说明问题,我加了一些注释

#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include "highgui.h"#include <stdlib.h>#include <stdio.h>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(){  /// Load an image  src = imread("coins.png");  if( !src.data )  {       return -1;   }  /// Create windows  namedWindow( "Erosion Demo", CV_WINDOW_AUTOSIZE );  namedWindow( "Dilation Demo", CV_WINDOW_AUTOSIZE );//Element:\n 0: Rect \n 1: Cross \n 2: Ellipse  /// 腐蚀操作滚动条  createTrackbar( "Element:", "Erosion Demo",&erosion_elem, max_elem,Erosion );  createTrackbar( "Kernel", "Erosion Demo",&erosion_size, max_kernel_size,Erosion );  /// 膨胀操作滚动条  createTrackbar( "Element:", "Dilation Demo",&dilation_elem, max_elem,Dilation );  createTrackbar( "Kernel", "Dilation Demo",&dilation_size, max_kernel_size,Dilation );  // 开始  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 );}

结果

  1. 采用7*7矩形结构元素
    这里写图片描述
    左图是腐蚀、右图为膨胀。可以看出,腐蚀缩小了白色(高亮)区域,而膨胀扩大了白色区域。
  2. 采用十字结构元素,大小为7,结果如下
    这里写图片描述
    左图是腐蚀、右图为膨胀。可以看出,腐蚀缩小了白色(高亮)区域,而膨胀扩大了白色区域。
  3. 采用椭圆结构元素,大小为15,结果如下
    这里写图片描述

可以看出,当白色区域为圆形时,采用椭圆形的结构元素生成的结果较为规则,圆形结构保持较为完整。

0 0
原创粉丝点击