形态学,即数学形态学(Mathematical Morphology),在图像处理中有广泛的应用,主要应用是从图像中提取对于表达和描绘区域形状有意义的图像分量,使后续的识别工作能够抓住目标对象最为本质(最具区分能力——most discrimination)的形状特征,像是边界、连通区域等。
基本概念
在数字图像处理的形态学运算中,常常把一幅图像或者图像中1个感兴趣的区域称作集合;而元素通常是指1个单个的像素,用该像素在图像中的整型位置坐标z=(z1,z2)表示。其他的一些基本概念就是集合的交并补集。值得一提的是差集,A与B的差集由所有属于A但不属于B的元素构成,至于包含就是AB的子集关系。
结构元素:设有两幅图像A、S。若A是被处理的对象,而S是用来处理A的,则称S为结构元素,通常是一些比较小的图像,二者的关系有点类似于滤波中图像与模板之间的关系。
二值图像中的基本形态学运算
tip:所有的形态学运算都是针对图像中的前景物体进行的(通常更习惯于将物体用黑色(灰度值为0)表示,背景用白色(灰度值为255)表示,比如Visual C++的一般就遵循这种规定;但是Matlab在二值图像形态学处理中,默认白色为前景,而黑色为背景)。
腐蚀
对Z²上元素的集合A和S,使用S对A进行腐蚀,可以表示为
简单说来,就是让原本位于图像原点的结构元素S在整个Z²平面上进行移动,当S的原点平移至某一点(假定为z)时,S可以完全包含在A中,则所有这样的点z构成的集合,即为S对A的腐蚀图像。
假设左边为待处理的原始图A,右边为结构元素S,以S的左下角为原点,进行腐蚀运算后的结果应该为,
tip:这种运算的运算结果不仅与结构元素的形状有关,还与结构元素的原点位置密切相关。
Matlab中与腐蚀相关的两个常用函数为imerode()和strel(),具体应用如下,
>> I=imread('erode_dilate.bmp');
>> figure1=imshow(I);
>> se=strel('square',3)
se =
strel is a square shaped structuring element with properties:
Neighborhood: [3x3 logical]
Dimensionality: 2
>> Ib=imerode(I,se); %腐蚀
>> figure2=imshow(Ib);
>>
>> se=strel('square',5); %将结构元素换成5*5的正方形
>> Ic=imerode(I,se); %腐蚀
>> figure3=imshow(Ic);
>> se=strel([0 1 0;1 1 1;0 1 0]); %将结构元素换成3*3的十字结构元素
>> Id=imerode(I,se); %腐蚀
>> figure4=imshow(Id);
>> se=strel('square',6); %将结构元素换成6*6的正方形
>> Ie=imerode(I,se); %腐蚀
>> figure5=imshow(Ie);
>> se=strel('square',7); %将结构元素换成7*7的正方形
>> If=imerode(I,se); %腐蚀
>> figure6=imshow(If);
显示结果如下,
由此我们可以看出腐蚀的作用,也就是能够消融物体边界,当然具体效果要根据图像本身和结构元素的形状来判断,如果物体整体上小于结构元素,则被腐蚀后将会完全消失;如果仅有部分区域小于结构元素(如细小的连通),则连通处会被断开。
膨胀
对于Z²上元素的集合A和S,使用S对A进行膨胀,可以表示为
也就是说,让原本位于图像原点的结构元素S在Z²上移动,当自身原点平移至z点,S相对于其自身原点的反射映像S'和A有公共的交集,也就是说至少有一个像素是重叠的,这样的z点构成的集合也就是S对A的膨胀图像。
如图所示,左侧为待处理图像A,右侧为结构元素S,膨胀后图像为
值得注意的是,膨胀和腐蚀中的不同点是膨胀中要求有公共交集的不是S本身,而是S的反射集,在使用非对称结构元素的时候需要格外注意。
Matlab中有Imdilate()函数用于完成图像膨胀,常用调用形式如下,
I2=imdilate(I,SE);
参数形式和之前腐蚀基本一样,返回值为膨胀后的图像,具体应用如下,
>> I=imread('starcraft.bmp');
>> se=strel('square',3);
>> Ie1=imerode(I,se); %3*3正方形结构元素的腐蚀
>> se=strel([0 1 0;1 1 1; 0 1 0]);
>> Ie2=imerode(Ie1,se); %3*3十字架结构元素的腐蚀
>> se=strel('square',3);
>> Id1=imdilate(Ie2,se); %3*3正方形结构元素的膨胀
>> Id2=imdilate(Id1,se); %3*3正方形结构元素的膨胀
>> se=strel([0 1 0;1 1 1; 0 1 0]);
>> Id3=imdilate(Id2,se); %3*3十字架结构元素的膨胀
效果如下,
开运算与闭运算
开闭运算都是由膨胀和腐蚀复合而成,开运算是先腐蚀后膨胀,闭运算是先膨胀后腐蚀。
开运算
开运算可以表示为,
一般来说,开运算使图像的轮廓变得光滑,断开下载的连接和消除细毛刺。
>> I=imread('img02.bmp');
>> Ie=imerode(I,se);
>> imshow(Ie);
>> Ie2=imdilate(Ie,se);
>> imshow(Ie2);
>> subplot(1,3,1),imshow(I),title('原图像');
>> subplot(1,3,2),imshow(Ie),title('先腐蚀');
>> subplot(1,3,3),imshow(Ie2),title('后膨胀');
效果如下,
为了更直观的看出开运算的效果,我们将结构元素稍微设置大一点,
>> se=strel('square',6);
>> Ie4=imopen(I,se);
>> imshow(Ie4)
再直观一点,
>> I=imread('erode_dilate.bmp');
>> Io=imopen(I,ones(6,6));%采用6*6的正方形结构元素进行开运算
>> subplot(1,2,1),imshow(I);
>> subplot(1,2,2),imshow(Io);
tip:原始图像分为两个主要的区域(圆形和矩形),中间用一个宽度为5的条形连通带,上面是一个3*3的十字,底部三个正方形边长分别为3、5、6。
对比前面的腐蚀,我们可以看到,开运算在过滤噪声的同时并没有对物体的形状、轮廓产生明显的影响,这是一大优势,但是若是只关心物体的位置和个数的时候,腐蚀的计算速度更具有优势。
闭运算
使用结构元素S对A进行闭运算,可以记作,
闭运算同样使得轮廓变得光滑,但是与开运算相反,它通常能够弥合狭窄的间断,填充小的孔洞。
tip:开闭运算也是对偶的,对于某图像多次应用开运算或者闭运算,和只进行一次运算的效果相同。
如图所示,分别是原始图、闭运算后、开运算后,