OpenCV学习笔记之七——图像形态学处理(一)

首先感谢@浅墨_毛星云本篇博文是小武通过学习@浅墨_毛星云的博客以及书籍《opencv3.0编程入门》整理的笔记及疑问心得,小武水平有限,欢迎交流。

@浅墨_毛星云博文:https://blog.csdn.net/poem_qianmo/article/category/1923021


一、形态学概述

数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度等。

最基本的形态学操作有二种,他们是:膨胀与腐蚀(Dilation与Erosion)。

膨胀与腐蚀能实现多种多样的功能,主要如下:

  • 消除噪声
  • 分割(isolate)出独立的图像元素,在图像中连接(join)相邻的元素。
  • 寻找图像中的明显的极大值区域或极小值区域


1、膨胀——dilate函数

函数原型:

C++: void dilate(  
                  InputArray src,  
                  OutputArray dst,  
                  InputArray kernel,  
                  Point anchor=Point(-1,-1),  
                  int iterations=1,  
                  int borderType=BORDER_CONSTANT,  
                  const Scalar& borderValue=morphologyDefaultBorderValue()   
);  

参数详解:

  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • 第三个参数,InputArray类型的kernel,膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核。

我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。

其中,getStructuringElement函数的第一个参数表示内核的形状,我们可以选择如下三种形状之一:

    • 矩形: MORPH_RECT
    • 交叉形: MORPH_CROSS
    • 椭圆形: MORPH_ELLIPSE

而getStructuringElement函数的第二和第三个参数分别是内核的尺寸以及锚点的位置。

我们一般在调用erode以及dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。且需要注意,十字形的element形状唯一依赖于锚点的位置。而在其他情况下,锚点只是影响了形态学运算结果的偏移。

2、腐蚀——erode函数

函数原型:

C++: void erode(  
    InputArray src,  
    OutputArray dst,  
    InputArray kernel,  
    Point anchor=Point(-1,-1),  
    int iterations=1,  
    int borderType=BORDER_CONSTANT,  
    const Scalar& borderValue=morphologyDefaultBorderValue()  
 );  
参数解释:
  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。
  • 第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
  • 第三个参数,InputArray类型的kernel,腐蚀操作的内核。若为NULL时,表示的是使用参考点位于中心3x3的核。我们一般使用函数 getStructuringElement配合这个参数的使用。getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。
  • 第四个参数,Point类型的anchor,锚的位置,其有默认值(-1,-1),表示锚位于单位(element)的中心,我们一般不用管它。
  • 第五个参数,int类型的iterations,迭代使用erode()函数的次数,默认值为1。
  • 第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。
  • 第七个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档中的createMorphologyFilter()函数得到更详细的解释。

代码实现:

//添加头文件
#include<opencv2/core/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv2/imgproc.hpp>
#include<iostream>

using namespace std;
using namespace cv;

//参数预定义
int Way_num=0;
int struct_size=1;

Mat  Img_in , Img_out;

//函数声明
void callback_Way_num(int ,void*);
void callback_struct_size(int ,void*);
void process();

//主函数
int main ()
{
	 Img_in=imread("lenna.jpg");
	
	 imshow("【原图】",Img_in);

	 namedWindow("【效果图】");
	 createTrackbar("腐蚀/膨胀","【效果图】",&Way_num, 1 , callback_Way_num);
	 callback_Way_num(Way_num,0);

	  createTrackbar("内核尺寸","【效果图】",&struct_size, 37 , callback_struct_size);
	  callback_struct_size(struct_size,0);
	
	 waitKey(0);
	 return 0;

}

//进行自定义的腐蚀和膨胀操作  
void process()
{
Mat element=getStructuringElement(MORPH_RECT,Size(struct_size*2+1,struct_size*2+1),Point(struct_size,struct_size));

//Way_num=0,进行腐蚀操作
if (Way_num==0)
	erode(Img_in,Img_out,element);
else
	//否则,进行膨胀
	dilate(Img_in,Img_out,element);

imshow("【效果图】",Img_out);
}

//腐蚀和膨胀之间切换开关的回调函数 
void callback_Way_num(int ,void*)
{
	process();
}

//腐蚀和膨胀操作内核改变时的回调函数
void callback_struct_size(int ,void*)
{
	process();
}


效果:





猜你喜欢

转载自blog.csdn.net/weixin_40647819/article/details/80009792