今天,我们一起来学习图像形态学操作中两种最基本的形态学操作,即腐蚀与膨胀。

一、理论

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

腐蚀与膨胀主要实现以下功能:

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

1、腐蚀

腐蚀对图像求局部最小值;腐蚀操作就是将图像(或图像的一部分区域,我们称之为A)与卷积核(我们称之为B)进行卷积。

核可以是任何的形状和大小,它拥有一个单独定义出来的参考点,我们称其为锚点。多数情况下,核是一个小的中间带有参考点和实心正方形或者圆盘,其实,我们可以把核视为模板或者掩码。

1)腐蚀的数学表达式




opencv 求最大连通区域 opencv求图像局部最值_锚点

腐蚀的数学表达式



2)腐蚀效果演示




opencv 求最大连通区域 opencv求图像局部最值_#include_02

腐蚀效果演示



3)腐蚀的作用:

  • 对象大小减小一个像素(3x3)
  • 平滑对象边缘
  • 弱化或者分割图像之间的半岛型连接

2、膨胀

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

核可以是任何的形状和大小,它拥有一个单独定义出来的参考点,我们称其为锚点。多数情况下,核是一个小的中间带有参考点和实心正方形或者圆盘,其实,我们可以把核视为模板或者掩码。

1)膨胀的数学表达式




opencv 求最大连通区域 opencv求图像局部最值_默认值_03

膨胀的数学表达式




opencv 求最大连通区域 opencv求图像局部最值_#include_04

膨胀效果演示



膨胀的作用:

  • 对象大小增加一个像素(3x3)
  • 平滑对象边缘
  • 减少或者填充对象之间的距离

小结:

可以看做膨胀是将白色区域扩大,腐蚀是将黑色区域扩大。

二、OpenCV腐蚀与膨胀API函数详解

1、腐蚀

1)函数原型:

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

2)函数功能:

用指定的卷积核腐蚀图像,使用像素邻域内的局部极小运算符来腐蚀一张图片,从src输入,由dst输出,支持就地(in-place)操作。

3)参数详解:

  • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一;
  • 第二个参数,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(),一般我们不用去管他。

第三个参数一般用getStructuringElement()函数获取卷积核的大小;getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。

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

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

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

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

4)实例:

#include #include #include #include using namespace std;using namespace cv;int main(){ //载入原图  Mat image = imread("lena.png"); if (image.empty()) { printf("image error!"); return -1; } //创建窗口  namedWindow("【原图】腐蚀操作"); namedWindow("【效果图】腐蚀操作"); //显示原图 imshow("【原图】腐蚀操作