参考:https://blog.csdn.net/Dujing2019/article/details/90050755
参考:https://blog.csdn.net/weixin_41907390/article/details/89431368
形态学,即数学形态学,主要应用是从图像中提取对于表达和描绘区域形状有意义的图像分量,使后续的识别工作能抓住目标对象最为本质(最具区分能力)的形状特征,如边界、骨架和连通区域等;同时细化、像素化和修建毛刺等技术也常常应用于图像的预处理和后处理中,是图像增强技术的有力补充。
基本思想是用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析识别的目的。
形态学图像处理的应用可以简化图像数据, 保持它们基本的形状特性,并除去不相干的结构

一、预备知识

数学形态学的语言是集合论
在数字图像处理的形态学运算中,常把一幅图像或者图像中一个我们感兴趣的区域称为集合,用大写字母A、B、C、D等表示;元素常指一个单个像素。像素在图像中的位置坐标用z = (z1,z2)来表示。z∈Z2,其中Z2为二元整数序偶对的集合。
集合的反射和平移
集合B的反射用B ̂ 表示。

若B是描述图像中物体的像素的集合(二维点),则B ̂ 是B中(x,y)坐标被(-x,-y)替代的点的集合。
集合B按照点z = (z1,z2)的平移,表示为(B)z,定义如下:

若B是描述图像中物体的像素集合(二维点),则(B)z是B中(x,y)坐标被(x + z1,y + z2)替代的点的集合。
下面用图示来更直观的描述集合的反射和平移。

反射和平移用来表达基于结构元(SE)的操作:研究一幅图像中感兴趣特性所用的小集合或子图像。结构元就类似于空间滤波时的卷积核(模板)。
SE中的值可以是0或1。常见的结构元结构有圆形、矩形、十字形。
当不在意SE中某些点时,该位置用‘x’标记。
结构元的原点:原点的选取与具体问题有关,当SE对称且未显示原点时,则假定原点位于对称中心处。
对图像操作时,要求结构元是矩形阵列。非矩形阵列的结构元,可通过添加最小适合数量的背景元素形成一个矩形阵列来实现。

二、二值形态学基本运算

2.1 腐蚀和膨胀

对大多数图像,一般相对于背景,物体的颜色(灰度)更深,二值化后物体会成为黑色,背景会变成白色。
但matlab在二值图像形态学处理中,默认情况下白色是前景(物体),用1表示,黑色的为背景,用0表示。对应的,结构元中的元素1也被当作白色处理。
腐蚀和膨胀都是针对图像的高亮区域。
腐蚀和膨胀是形态学的基础。

2.1.1 腐蚀与实现

腐蚀是使图像中的高亮区域“细化”或“收缩”。
对Z2中的集合A和B,使用B对A进行腐蚀,定义如下

语言描述:其中B为结构元,让B在整个Z2平面上移动,如果当B的原点平移值z点事B能完全包含与A中,则所有这样的z点构成的集合即为B对A的腐蚀图像。换句话说,就是让B的原点访问A中的每个点,寻找原点经过的位置中能使B完全被A包含的点的集合。
【将结构元素的原点覆盖在每一个二值图像的1上,只要二值图像上有0和结构元素的1重叠,那么与原点重叠的值为0】



像素格内的“o”表示原点,"X"表示该位置的值我们不关心。

小结
图像本身、结构元的形状和原点位置的选取都会影响腐蚀操作的结果。
腐蚀能够消融物体的边界,而具体的腐蚀结果与图像本身和结构元的形状有关:如果物体整体上大于结构元,腐蚀的结构是使物体变“瘦”一圈,这一圈到底有多大是由结构元决定的:如果物体本身小于结构元,则在腐蚀后的图像中物体将完全消失;如物体仅有部分区域小于结构元(如细小的连通),则腐蚀后物体会在细连通处断裂,分离为两部分。因此在实际应用中,可以利用腐蚀运算去除物体之间的粘连,消除图像中的小颗粒噪声。

实现
和腐蚀相关的两个常用函数: imerode 和 strel
imerode:完成图像腐蚀。调用形式如下:

I2 = imerode(I,SE)
% I:为原始图像,可以是二值或灰度图像(对应于灰度腐蚀)
% SE:是由strel函数返回的自定义或预设的结构元对象。
% I2:为腐蚀后的输出图像。

strel:为各种常见形态学运算生成结构元SE。当生成供二值形态学使用的结构元素时,调用形式如下:

SE = strel(shape,parameters)
% shape:指定了结构元的形状
% parameters:输入shape有关的参数。

参考:strel 形态学结构元

几个代表性的情况:

SE = strel('arbitrary',NHOOD)  % 返回一个有特定邻域NHOOD指定的结构元。其中,NHOOD为一个只包含"0"和"1" 的矩阵,规定了结构元素的形状。结构元的中心位于NHOOD矩阵的中心位置,即floor((size(NHOOD)+1)/2)。SE = strel('disk',R)  % 返回一个半径为R的圆形结构元SE = strel('pari',OFFSET) % 返回一个只包含2个“1”的结构元。其中1个“1”位于原点,另一个“1”相对于原点的位置有OFFSET向量指定。OFFSET是一个长度为2的向量,OFFSET(1)是x方向的偏移量,OFFSET(2)是y方向的偏移量。SE = strel('rectangle',MN)  % 返回一个高、宽均由向量MN指定的矩形结构元。MN是一个长度为2的向量,MN(1)是结构元的高度,MN(2)是结构元的宽度。

示例:不同结构元素的腐蚀效果

img = imread('binary_img.png');se1 = strel([0 1 0;1 1 1;0 1 0]);  % 3*3的十字结构元
image1 = imerode(img,se1);se2 = strel('disk',10);  % 半径为3的圆形结构元
image2 = imerode(img,se2);se3 = strel('square',3);  % 3*3的正方形结构元
image3 = imerode(img,se3);se4 = strel('square',11);  % 5*5的正方形结构元
image4 = imerode(img,se4);se5 = strel('square',50);  % 7*7的正方形结构元
image5 = imerode(img,se5);figure;
subplot(2,3,1); imshow(img); title('原图');
subplot(2,3,2); imshow(image1); title('经3*3的十字结构元腐蚀');
subplot(2,3,3); imshow(image2); title('经半径为10的圆形结构元腐蚀');
subplot(2,3,4); imshow(image3); title('经3*3的正方形结构元腐蚀');
subplot(2,3,5); imshow(image4); title('经11*11的正方形结构元腐蚀');
subplot(2,3,6); imshow(image5); title('经50*50的正方形结构元腐蚀');

结果

imerode也可以直接处理彩色图像。

2.1.2 膨胀与实现

膨胀会“增化”或“粗化”图像的高亮区域。

计算B对A的膨胀,要先计算B的反射。
【实际就是将结构元素的原点与二值图像中的1重叠,将二值图像中重叠部分不是1的值变为1,完成膨胀】

图像本身、结构元的形状和原点位置的选取都会影响腐蚀操作的结果。
膨胀运算具有扩大图像和填充图像中比结构元小的成分的作用,因此在实际应用中可以利用膨胀运算连接相邻物体和填充图像中的小孔和狭窄的缝隙



实现
imdilate函数用于完成图像膨胀。调用形式如下:

I2 = imdilate(I,SE)
% SE:由strel函数返回的自定义或预设的结构元对象。也可以直接自定义SE。
I2 = imdilate(i,ones(3,3))  % 不使用strel,而直接自定义SE

示例:连接文字裂缝

img = imread('broken-text.tif');
imshow(img);
se1 = strel('square',2);
img1 = imdilate(img,se1);se2 = strel([0 1 0;1 1 1;0 1 0]);
img2 = imdilate(img,se2);figure;
subplot(1,3,1); imshow(img); title('原图');
subplot(1,3,2); imshow(img1); title('经2*2的正方形结构元膨胀');
subplot(1,3,3); imshow(img2); title('经3*3的十字结构元膨胀');

结果

对偶性
腐蚀和膨胀彼此关于集合求补运算和反射运算是对偶的。

当结构元关于其原点对称时,即B = B ̂ ,对偶性特别有用。我们可以用相同的结构元简单地使用B膨胀图像的背景,对该结果求补即可得到B对该幅图像的腐蚀。

2.2 腐蚀和膨胀的组合

2.2.1 开运算和闭运算

开运算:先腐蚀后膨胀;闭运算:先膨胀后腐蚀。
开运算
结构元B对集合A进行开运算,定义如下:

开运算一般会平滑物体的轮廓、断开较窄的狭颈和消除细突出物(毛刺)


实现:
可以用相同的结构元调用imerode和imdilate即可实现开运算。同时matlab直接提供了imopen函数来实现开运算。调用格式如下:

I2 = imopen(I,SE)

示例

img = imread('binary_img.png');
se = strel('square',30);
img1 = imopen(img,se);
figure;
subplot(1,2,1); imshow(img); title('原图');
subplot(1,2,2); imshow(img1); title('经30*30正方形结构元开运算');

结果

闭运算
结构元B对集合A进行闭运算。定义如下

闭运算也会平滑轮廓的一部分,但通常会弥合较窄的间断和细长的沟壑,消除较小的孔洞,填补轮廓线中的断裂。


实现
可以用相同的结构元调用imdilate和imerode即可实现闭运算。同时matlab中也直接提供了imclose函数。调用格式如下:

I2 = imclose(I,SE)

示例1:开运算和闭运算的对比

f = imread('shapes.tif');
se = strel('square', 20);
fo = imopen(f, se);
fc = imclose(f, se);
foc = imclose(fo, se);
subplot(2,2,1), imshow(f), title('(原图');
subplot(2,2,2), imshow(fo), title('开运算');
subplot(2,2,3), imshow(fc), title('闭运算');
subplot(2,2,4), imshow(foc), title('开运算后的闭运算');


从开运算可以看出:物体的轮廓有一定的平滑,细小的连接消失了,突出的毛刺也没了,孤立点也消失了
从闭运算可以看出:细的缺口、内部的不规则边缘和小洞都被填充了
对图像先开运算,再闭运算处理,可以看出细的缺口、内部不规则边缘和小洞都被填充了,得到了很平滑的图像。

示例2:使用开运算和闭运算消除噪声,同时使图像的失真尽可能减少

img = imread('noisy-fingerprint.tif');
se = strel('square',3);
img1 = imopen(img,se);
img2 = imclose(img1,se);
figure;
subplot(1,3,1); imshow(img); title('原图');
subplot(1,3,2); imshow(img1); title('开运算');
subplot(1,3,3); imshow(img2); title('闭运算');

结果

首先对带有噪声的指纹图像进行开运算,消除指纹外面的杂点,但开运算又造成了指纹中间的很多缺口,进一步用同样的结构元执行闭运算,将缺口进行填充。

开运算和闭运算关于集合求补和反射也是对偶的。

开运算满足的性质:

闭运算满足的性质:

2.2.2 击中或击不中变换

形态学击中或击不中变换是形状检测的基本工具。常用于图像中某种特定形状的精确定位。
看书看的云里雾里,很开心找到了通俗易懂的解释。
链接:通俗理解
简单来说击中-击不中运算常用于二值图像,它用于基于结构元素(即结构元)的配置,从图像中寻找具有某种像素排列特征的目标,如单个像素、颗粒中交叉或纵向的特征、直角边缘或其他用户自定义的特征等。计算时,只有当结构元素与其覆盖的图像区域完全相同时,中心像素的值才会被置为1,否则为0。下图给出了一个例子。

其实说白了就是在给定的A中,寻找一模一样的B(结构元),找到后返回其原点。

下面再简单的概括一下书上的内容。
击中与击不中变换可表示为:

其中,B1∩B2 = ∅,B = B1∪B2。实际上B1代表B中我们感兴趣的物体(要检测的形状)对应的集合,而B2为B中背景部分对应的集合。
其实B1和B2分别代表两个结构元。输出图像由所有在B1中匹配的像素(击中)和未在B2中匹配的像素(击不中)组成。
由对偶关系可得

实现:
matlab中提供了bwhitmiss函数来实现,调用方式如下:

Ihm = bwhitmiss(I,SE1,SE2)   %  其中I为输入图像,SE1和SE2分别为上述介绍的B1和B2两个结构元,Ihm为击中击不中变换后的图像。
Ihm = bwhitmiss(I,interval)  % interval是将上述的SE1和SE2合并在一块,interval中包含1、-1、0三种元素,其中1表示SE1(击中),-1表示SE2(击不中),0表示忽略不管。

注:bwhitmiss只能处理二值图像
示例:

img = imread('test1.png');
img=rgb2gray(img);
thresh = graythresh(img);     %自动确定二值化阈值;
img =  imbinarize(img,thresh);       %对图像自动二值化即可。
B1 = strel([0 0 0; 0 1 1; 0 1 0]);
B2 = strel([1 1 1; 1 0 0; 1 0 0]);
g = bwhitmiss(img,B1,B2);
% interval = [-1 -1 -1;-1 1 1;-1 1 0];
% g = bwhitmiss(img,interval);
figure();
subplot(1,2,1); imshow(img); title('原图');
subplot(1,2,2); imshow(g); title('击中不击中变换后的图像');

其中8和9两行代码与5~7行代码有异曲同工之处,也正好通过例子说明一下bwhitmiss函数的两种调用方法。
结果

三、基本的形态学算法

3.1 边界提取

轮廓是对物体形状的有力描述,对于图像分析和识别十分有用。
边界提取
集合A的边界用β(A),可以通过先用B(结构元)对A腐蚀,然后用A减去腐蚀的结果获得。


示例

img = imread('head_portrait.png');
se = strel('square',3);
img1 = imerode(img,se);
boundary_img = img - img1;
figure;
subplot(1,3,1); imshow(img); title('原图');
subplot(1,3,2); imshow(img1); title('腐蚀图像')
subplot(1,3,3); imshow(boundary_img); title('边界图像');

结果

腐蚀图像后,原图像的高亮区域会缩小一圈,然后用原图像减去腐蚀图像,就可以得到一个轮廓边界。随着结构元尺寸的增大,腐蚀后图像就会缩小的越厉害,得到的边界就会越粗。

3.2 孔洞(区域)填充

孔洞定义为前景像素相连接的边界所包围的背景区域。孔洞填充可视为边界提取的反过程,它是在边界已知的情况下得到边界包围的整个区域。
已知某一8连通边界和边界内部的某个点,要求从该点开始填充整个边界包围的区域,这一过程也称为“种子”填充,填充的开始点被称为“种子”。
对于4连通的边界,其围成的内部区域是8连通的,而8连通的边界围成的内部区域却是4连通的。

算法描述:
初始化:X0 = 种子点 (即连通边界内部的某个点,除了该位置置1外,其余位置均为0,大小与A的大小相同,A为包含连通边界及边界内部的集合)
循环:

终止条件:若Xk = Xk-1,则算法在第k步结束。
然后集合Xk包含所有被填充的孔洞。Xk和A的并集包含所有填充的孔洞及这些孔洞的边界。

后面会介绍一种基于形态学重建的全自动的孔洞填充方法。

3.3 连通分量提取

在二值图像中提取连通分量是许多自动图像分析应用中的核心任务。提取连通分量的过程实际上也是标注连通分量的过程, 通常的做法是给原图像中的每个连通区分配一个唯一代表该区域的编号, 在输出图像中该连通区内的所有像素的像素值就赋值为该区域的编号, 我们将这样的输出图像称为标注图像。
令A是包含一个或多个连通分量的集合,并形成一个阵列X0(大小与A相同)。
算法描述:
初始化:X0 = 连通分量A中的某个点
循环:

终止条件:当Xk Xk-1时,循环结束。
Xk包含输入图像中的所有连通分量。

实现
连通分量提取借助工具函数bwlabel

[L, num] = bwlabel (f, conn)
% f :输入的二值图像
% coon:指明要提取的连通分量是4连通还是8连通,默认是8连通,
% L:标记矩阵
% num:给出找到的连通分量总数。

计算和显示连通分量的质心

f = imread('test2.tif');
imshow(f);title('(a)标注连通分量原始图像:');
[L,n]=bwlabel(f);
[r,c]=find(L==3);        %返回第3个对象所有像素的行索引和列索引
rbar=mean(r);
cbar=mean(c);
% 可以使用一个循环来计算和显示图像中全部对象的质心。为了使质心重叠在图像上时可看到该质心,将使用中心为 '*' 符号的圆标记来表示
figure,imshow(f);title('(b)标记所有对象质心后的图像:');
hold on            %保持当前图像使其不被刷新
for k=1:n[r,c]=find(L==k);rbar=mean(r);cbar=mean(c);plot(cbar,rbar,'Marker','o','MarkerEdgeColor','k',...'MarkerFaceColor','k','MarkerSize',10);  % 圆标记的设置plot(cbar,rbar,'Marker','*','MarkerFaceColor','w'); %其中的marker为标记,*的设置
end

3.4 凸壳

如果在集合A内连接任意两个点的直线段都在A的内部,则称A是凸的。任意集合S的凸壳H是包含于S的最小凸集。差集H-S称为S的凸缺。
获得集合A的凸壳的简单形态学算法如下:
令Bi,i = 1,2,3,4表示四个结构元。

其中X0i = A。
循环终止条件:Xki = Xk-1i
令Di = Xki,则A的凸壳为:

即,该方法反复使用B1对A做击中击不中变换,当不再发生进一步变化时,与A求并集,得到D1,由结构元Bi(i = 2,3,4)和A进行相同的运算可得Di(i = 2,3,4)。最后,4个D的并组成了A的凸壳。

bwmorph 二值图像的形态学运算
参考:bwmorph
调用格式:

BW2 = bwmorph(BW,operation)   %对二值图像 BW 应用特定的形态学运算。
BW2 = bwmorph(BW,operation,n)  % n用来指定重复操作的次数,n 可以是 Inf,在这种情况下会一直重复运算,直到图像不再变化。

3.5 细化

细化是在图像中将二值物体和形状减小为单个像素宽的线。
结构元B对集合A的细化可根据击中击不中变换来定义:

对称地细化A的一种更有用表达方式是以结构元序列为基础的

Bi是Bi-1旋转后的形式。则使用结构元序列将细化定义如下

即A被B1细化一次,得到的结果再被B2细化一次,直到被Bn细化一次。

img = imread('noisy-fingerprint.tif');
fe = imerode(img,ones(3,3));
fd = imdilate(fe,ones(5,5));
g1 = bwmorph(f, 'thin',1);
g2 = bwmorph(f, 'thin',2);
ginf = bwmorph(f,'thin', Inf);
figure;
subplot(2,3,1); imshow(img);title('原图');
subplot(2,3,2); imshow(fe); title('腐蚀去噪');
subplot(2,3,3); imshow(fd); title('膨胀连接断裂部分');
subplot(2,3,4); imshow(g1);title('细化一次');
subplot(2,3,5); imshow(g2);title('细化两次');
subplot(2,3,6); imshow(ginf);title('一直细化到稳定状态');


可以看出,不同的细化次数,得到的结果也是不一样的。

3.6 粗化

粗化是细化的形态学对偶

其中B是适合于粗化处理的结构元。
为了粗化A,通常的做法是:先对A求补 C = Ac,然后细化C ,然后再对结果求补

3.7 骨架

img = imread('bone.tif');
img1 = bwmorph(img,'skel',inf);
se1 = strel('square',3);
img2 = imdilate(img1,se1);
figure;
subplot(1,3,1); imshow(img); title('原图');
subplot(1,3,2); imshow(img1); title('骨架');
subplot(1,3,3); imshow(img2); title('膨胀后的骨架');


只使用bwmorph得到的骨架会产生断裂,故对产生的骨架再用3*3的正方形结构元进行了膨胀。

3.8 形态学重建

形态学重建涉及两幅图像和一个结构元。一幅图像是标记,它包含变换的起始点,另一幅图像是模板,它用来约束该变换。结构元用来定义连接性。
形态学重建的核心是测地膨胀和测地腐蚀

测地膨胀和腐蚀

a、测地膨胀
令F表示标记图像,G表示模板图像。F和G均为二值图像,且F⊆G。
DG(1)(F)表示大小为1的标记图像关于模板的测地膨胀,定义为:

F关于G的大小为n的测地膨胀定义为:

所谓的大小,即上标1和n,表示的是迭代次数。
其中DG(0)(F) = F,在递推式中,求交在每一步中都执行了。交集算子保证模板G将限制标记F的生长(膨胀)。
下图显示了一个大小为1的测地膨胀

b、测地腐蚀
标记F关于模板G的大小为1的测地腐蚀定义:

F关于G的大小为n的测地腐蚀定义:

EG(0)(F) = F,并集在每个迭代步骤中执行,并保证一幅图像的测地腐蚀仍然大于等于其模板图像。
下图所示为大小为1的测地腐蚀

用膨胀和腐蚀的形态学重建

来自标记图像F对模板图像G的膨胀形态学重建表示为:RGD(F) ,被定义为F关于G的测地膨胀。反复迭代直至达到稳定状态。

迭代k次,直至DG(k)(F) = DG(k+1)(F)。
对大小为1的测地膨胀继续进行处理,进行膨胀形态学重建,如下图:

模板图像G对标记图像F的腐蚀形态学重建表示为RGE(F) ,被定义为F关于G的测地腐蚀,反复迭代直至达到稳定状态,即

应用实例

重建开运算
先腐蚀再重建
在形态学开操作中,腐蚀会去除小的物体,且后续的膨胀会试图恢复遗留物体的形状。 然而,这种恢复的精确度取决于物体的形状和结构元之间的相似性。重建开运算准确地恢复腐蚀所保留物体的形状。图像F的大小为n的重建开运算可定义为 :

方括号中表示B对F的n次腐蚀。
imreconstruct:形态学重建

out = imreconstruct(marker,mask)
%  marker为标记图像,mask为模板图像

示例:提取一幅图中的垂直笔画的长字符(长字符的平均高度为51像素)

f = imread('book-text.tif');
fe=imerode(f,ones(51,1)); % 竖线腐蚀
fo=imopen(f,ones(51,1)); % 竖线做开运算,为了和重建开运算作对比
fobr=imreconstruct(fe,f); % fe做标记
figure;
subplot(2,2,1),imshow(f);title('原图');
subplot(2,2,2),imshow(fe);title('使用竖线结构元腐蚀后的结果');
subplot(2,2,3),imshow(fo);title('使用竖线结构元做开运算结果');
subplot(2,2,4),imshow(fobr);title('重构开运算');


孔洞填充
令I(x,y)表示一幅二值图像,假定形成了一幅标记图像F,除了在该图像的边界位置为1-I之外,在其他位置均为0,即


H是一幅等于I且所有孔洞都被填充的二值图像。
使用imfill函数的参数’holes’可以实现该操作。

g = imfill(f,'holes')

边界清除
清除图像中与边界相连的物体。用原图像作为模板,并定义标记图像

首先计算形态学重建RID(F),即简单地提取接触到边界的物体,然后用原图像相减,即得到一幅其中没有接触边界的物体的图像X。

使用imclearborder函数可以实现边界清除操作。

g = imclearborder(f,conn)

conn为像素邻接方式,其值可以是4或8(默认),表示4邻接或8邻接。
该函数会清除比周围对象更亮且与边界相连接的结构。
f为输入图像,可以是二值图像,也可以是灰度图像。

f = imread('book-text.tif');
ff=imfill(f,'holes');%对f进行孔洞填充
fc=imclearborder(f,8);%清除边界,2维8邻接
figure;
subplot(2,2,[1,2]); imshow(f); title('原图');
subplot(2,2,3),imshow(ff);title('填充孔洞后的图像');
subplot(2,2,4),imshow(fc);title('清除边界后的图像');

四、灰度级形态学

f(x,y)和b(x,y)为两个二维数字函数。f(x,y)表示一幅灰度级图像,b(x,y)表示结构元。
灰度级形态学中的结构元分为两类:非平坦或平坦的结构元。

4.1 腐蚀和膨胀

平坦结构元 b的值在其定义域内的所有坐标处均为0
当b的原点在(x,y)处时,用一个平坦结构元b在(x,y)处对图像f的腐蚀定义为:图像f中与b重合区域的最小值。

b ̂ 的原点在(x,y)处时,平坦结构元b在任何位置(x,y)处对图像f的膨胀定义为:图像f中与b ̂ 重合区域的最大值。

其中b ̂ = b(-x,-y)。
非平坦结构元
腐蚀

膨胀

腐蚀和膨胀关于函数的补集和反射是对偶的。

实现
腐蚀和膨胀可以使用imerode和imdilate进行实现。唯一的区别就是结构元的创建。
平坦结构元的创建和二值形态学中的相同;非平坦结构元的创建可使用如下方法:

SE = strel(NHOOD,HEIGHT) % 创建非平坦的结构元素
% NHOOD:指明结构元定义域的矩阵,只能由0和1组成
% HEIGHT:与NHOOD尺寸相同的矩阵,指出来对应于NHOOD中每个元素的高度。

4.2 开运算和闭运算

结构元b对图像f的开运算

先进行腐蚀操作可以除去小的亮的图像细节,但这样会使图像变暗,接下来进行膨胀操作增强图像的整体亮度。
几何解释:
将一幅图像看作是一个三维表面,其灰度值代表xy平面上的高度值,则当结构元b在f下表面活动时,b的任何部分的最高值构成了开运算的结果。

结构元b对图像f闭运算

先通过膨胀操作除去图像中的暗细节,同时增加图像的亮度,接下来对图像进行腐蚀,而不会将膨胀操作除去的部分重新引入图像中。
几何解释:
当结构元b在f的上表面活动时,结构元素的任何部分的最低值构成了闭运算的结果 。

4.3 灰度级形态学算法

形态学平滑
开运算抑制比结构元小的亮细节,闭运算抑制暗细节,所以经常将二者结合起来平滑图像和去除噪声。

用开操作和闭操作做形态学平滑

f = imread('dowels.tif');se=strel('disk',5);     % 半径为5的圆形结构元
fo=imopen(f,se);        % 原图开运算
foc=imclose(fo,se);  % 先开后闭focd=imclose(f,se);   % 原图闭运算
foce=imopen(focd,se);  % 先闭后开fasf=f;
for i=2:5  se=strel('disk',i);  fasf=imclose(imopen(fasf,se),se);
end
figure;
subplot(3,2,1); imshow(f);     title('原图');
subplot(3,2,2); imshow(f);     title('原图开运算');
subplot(3,2,3); imshow(foc);   title('先开后闭的图像');
subplot(3,2,4); imshow(focd);  title('原图的闭运算');
subplot(3,2,5); imshow(foce);  title('先闭后开的图像');
subplot(3,2,6); imshow(fasf);  title('使用开闭交替滤波后图像');


先开运算后闭运算构成噪声滤波器,用来平滑图像并去除噪声。
交替顺序滤波,交替顺序滤波的一种形式是用不断增大的一系列结构元执行开-闭滤波,刚开始用小的结构元,增加大小,直到与最开始进行开运算的结构元的大小相同为止。交替顺序滤波与单个开-闭滤波相比,处理图像更平滑一些。

形态学梯度
腐蚀和膨胀可与图像相减结合起来得到一幅图像的形态学梯度,形态学梯度由g定义:

膨胀粗化一幅图像中的区域,腐蚀则细化它们,膨胀和腐蚀之差强调区域间的边界。同质区域不受影响(只要SE相对较小),因此相减操作趋于消除同质区域。最终结果是边缘被增强而同质区域的贡献则被抑制的图像。

f = imread('aerial.tif');
se=strel('square',3);  %构造了一个平坦的3x3的结构元素
fd=imdilate(f,se);    %对原图像进行膨胀操作
fe=imerode(f,se);     %对原图像进行腐蚀操作
morph_grad=imsubtract(fd,fe); %从膨胀的图像中减去腐蚀过得图像产生一个形态学梯度。
subplot(2,2,1);imshow(f);title('原图');
subplot(2,2,2),imshow(fd);title('膨胀的图像');
subplot(2,2,3),imshow(fe);title('腐蚀的图像');
subplot(2,2,4),imshow(morph_grad);title('形态学梯度');


膨胀得到的图像比原图像更明亮,并且减弱或消除小的、暗的细节部分。比原图像模糊。
腐蚀得到的图像更暗,并且尺寸小,明亮的部分被削弱 。

顶帽变换和底帽变换
图像相减与开运算和闭运算相结合,可称为所谓的top-hat(顶帽)变换和bottom-hat(底帽)变换。
灰度级图像f的顶帽变换定义为f减去其开运算

f的底帽变换为f的闭运算减去f

顶帽变换用于暗背景上的亮物体,可以得到图像中面积小于结构元且比周围亮的区域;底帽变换用于亮背景上的暗物体,可以得到图像中面积小于结构元且比周围暗的区域。故也常称为白顶帽变换和黑底帽变换。
顶帽变换和底帽变换可以上述描述实现:即使用开运算或闭运算,然后和原图像之间求差。
也可以使用imtophat(顶帽变换)和imbothat(底帽变换)函数进行。调用格式如下

J = imtophat(I,SE)
J = imtophat(I,nhood)  % nhood是一个值为0和1的数组,用于指定结构元素的大小和形状J = imbothat(I,SE)
J = imbothat(I,nhood) % nhood是一个值为0和1的数组,用于指定结构元素的大小和形状

顶帽变换的一个重要用途是校正不均匀光照的影响。

img = imread('rice.tif');
g = img>=(255*graythresh(img));  % 对图像进行阈值化
se = strel('disk',40);
img1 = imopen(img,se);  % 开运算
f1 = imsubtract(img,img1); % 顶帽变换
g1 = f1>=(255*graythresh(f1)); % 顶帽变换后进行阈值化
figure;
subplot(2,3,1); imshow(img); title('原图');
subplot(2,3,2); imshow(g); title('阈值化后的图像');
subplot(2,3,3); imshow(img1); title('原图开运算');
subplot(2,3,4); imshow(f1); title('顶帽变换的图像');
subplot(2,3,5); imshow(g1); title('顶帽变换后进行阈值化');


原图是在非均匀光照下得到的米粒图像,直接对原图进行阈值化处理,可以看到右下角的米粒未从背景中正确的提取出来。图像使用半径为40的圆盘结构元进行开运算处理(这个结构元达到足以不会拟合任何物体,只留下一个近似的背景),然后从原图像中减去该图像,可以生成一幅具有合适且均匀的背景的米粒图像。对顶帽变换后的图像进行阈值化处理得到了最终的图像。

粒度测定
粒度测定属于判断图像中颗粒的大小分布的领域。形态学可间接用于估计颗粒的大小分布,而不需要识别并测量图像中的每个颗粒。
对于比背景亮且具有规则形状的颗粒,基本方法是使用逐渐增大的结构元对图像执行开运算。对于每一个开运算,计算该开运算中像素值的和,该和有时称为表面区域。因为开运算会降低亮特征的灰度,故表面区域会睡着结构元的增大而减小。

f = imread('rice.tif');
imshow(f); title('原图');
sumpixels=zeros(1,36);
for k=0:35  % 对图像进行半径为0到35的圆盘结构元开运算se=strel('disk',k);  fo=imopen(f,se);  sumpixels(k+1)=sum(fo(:));
end
figure;
plot(0:35,sumpixels),xlabel('半径k'),ylabel('表面区域');
title('表面区域和结构元半径之间的关系');
figure,plot(-diff(sumpixels));%diff()函数为差分或者近似倒数,即相邻2个之间的差值
xlabel('半径k'),ylabel('表面区域减小');
title('减小的表面区域和结构元半径之间的关系');



可以看到,连续开运算之间的表面区域会减小;图3 峰值表明出现了大量的有着这种半径的对象。
纹理分割

4.4 灰度级形态学重建

测地膨胀和测地腐蚀
令f和g分别代表标记图像和模板图像。假设f和g是大小相同的灰度级图像,且f <= g。则f关于g的大小为1(即只计算迭代1次)的测地膨胀为:

其中∧代表点方式的最小算子。即先计算b对f的膨胀,然后选择在每个(x,y)点处该结果和g间的最小者。
根据b为平坦结构元还是非平坦结构元,膨胀的计算公式不同,可看前面的介绍。
f关于g的大小为n的测地膨胀为:


类似的,f关于g的大小为1的测地腐蚀为:

其中∨代表点方式的最大算子。
f关于g的大小为n的测地腐蚀为:


形态学重建
灰度级标记图像f对灰度级模板图像g的膨胀形态学重建定义为:f关于g的测地膨胀反复迭代,直至达到稳定,即:

k应使

f对g的腐蚀形态学重建定义为:

k应使

图像f的大小为n的重建开运算:先对f进行n次腐蚀,再由f的膨胀重建(先腐蚀后重建):

图像f的大小为n的重建闭运算:先对f进行n次膨胀,再由f的腐蚀重建(先膨胀后重建):

由于对偶性,图像的重建闭运算可以用图像的求补得到:对一幅图像求补,然后计算其重建开运算,再对其结果求补。

示例:使用重建删除复杂图像的背景

%   突显计算器键盘上的文字
f = imread('calculator.tif');
%   抑制按键顶部的水平反射光,因为反射光比任何单个字符都宽,故用一条1*71的长水平线作为结构元,对图像进行重建开运算
f_obr=imreconstruct(imerode(f,ones(1,71)),f);  % 重建开运算,将得到按键及其反射的背景
f_o=imopen(f,ones(1,71));    % 开运算 ,为了比较f_thr=imsubtract(f,f_obr);    % 顶帽重建: 从原图像减去其重建开运算的结果
f_th=imsubtract(f,f_o);    % 标准顶帽运算,方便比较%   顶帽重键后,按键的边缘还存在垂直反射,使用1*11的结构元对顶帽重建的结果进行重建开运算,以删除按键边缘的垂直反射
g_obr=imreconstruct(imerode(f_thr,ones(1,11)),f_thr);  % 重建开运算 ,会造成有用字符也被细化
g_obrd=imdilate(g_obr,ones(1,21));  % 对g_obr进行膨胀,则膨胀后的字符与先前被抑制字符所占的区域重叠f2=imreconstruct(min(g_obrd,f_thr),f_thr);  % 将膨胀后的图像和重建顶帽图像求点方式最小值,用膨胀图像作模板进行重建figure;
subplot(3,3,1),imshow(f);  title('(a)原图像');
subplot(3,3,2),imshow(f_obr);  title('(b)对(a)重建开运算');
subplot(3,3,3),imshow(f_o);  title('(c)对(a)开操作');
subplot(3,3,4),imshow(f_thr);  title('(d)重建的顶帽变换');
subplot(3,3,5),imshow(f_th);  title('(e)标准顶帽变换');
subplot(3,3,6),imshow(g_obr);  title('(f)用水平线对(d)重建开运算');
subplot(3,3,7),imshow(g_obrd);  title('(g)使用水平线对(f)进行膨胀');
subplot(3,3,8),imshow(f2);  title('(h)最后的重建结果');

数字图像处理——第九章(形态学图像处理)相关推荐

  1. 数字图像处理第九章——形态学图像处理

    数字图像处理第九章 数字图像处理---形态学图像处理 (一)预备知识 1.1 集合理论中的基本概念 1.2 二值图像.集合及逻辑算子 (二)膨胀和腐蚀 2.1 膨胀 2.2 结构元的分解 2.3 st ...

  2. 数字图像处理——第九章 形态学图像处理

    数字图像处理--第9章 形态学图像处理 文章目录 数字图像处理--第9章 形态学图像处理 1 基础知识 1.1 形态学图像 1.2 二值图像 2 腐蚀和膨胀 2.1 腐蚀 2.2 膨胀 3 开操作与闭 ...

  3. 数字图像处理第九章 形态学图像处理

    形态学图像处理 1 预备知识 1.1 集合理论中的基本概念 1.2 二值图像.集合及逻辑算子 2 膨胀和腐蚀 2.1 膨胀 2.2 腐蚀 3 膨胀与腐蚀的结合 3.1 开操作和闭操作 3.2 击中或击 ...

  4. 数字图像处理第九章----形态学图像处理

    文章目录 1.概念 2.腐蚀与膨胀 3.开闭运算 4.顶帽与黑帽运算 5.边界提取与区域填充 6.细化 7.总结 1.概念 形态学操作:数学形态学时基于集合论的图像处理方法,最早出现在生物学的形态与结 ...

  5. 数字图像处理第九章形态学处理

    文章目录 引言 9.1预备知识 9.2腐蚀和膨胀 9.2.1腐蚀 9.2.2膨胀 9.3开操作和闭操作 9.3.1开操作 9.3.2闭操作 9.4一些基本的形态学算法 9.4.1边界提取 9.4.2孔 ...

  6. 数字图像处理——第九章 形态学处理

    文章目录 引言 9.1 一些基本的形态学集合 9.2 腐蚀和膨胀 9.3 开操作与闭操作 9.4 击中与击不中 9.5 形态学处理函数 实验部分 总结 引言 本章主要将数学形态学作为工具从图像中提取表 ...

  7. 数字图像处理知识点梳理——第九章 形态学图像处理

    文章目录 1.预备知识 2.腐蚀和膨胀 3.开操作和闭操作 4.一些基本的形态学算法 1.预备知识 数学形态学的语言是集合论. 在形态学中集合的反射和平移广泛用来表达基于结构元(SE)的操作:研究一幅 ...

  8. imopen和bwmorph_数字图像处理第九章讲义.ppt

    第九章 形态学图像处理 预备知识 膨胀与腐蚀 开操作和闭操作 击中或击不中变换 一些基本的形态学算法 灰度级形态学 第九章 形态学图像处理 第九章 形态学图像处理 预备知识 预备知识 集合论中的几个基 ...

  9. 数字图像处理第九章笔记——形态学图像处理

    目录 引言 一.预备知识 1.1 平移与反射 1.2 结构元 二. 腐蚀和膨胀 2.1 腐蚀 2.2 膨胀 2.3 对偶性 2.4 python实现腐蚀和膨胀 三.开操作和闭操作 四. 击中或击不中变 ...

最新文章

  1. Thymeleaf 基本用法总结
  2. Python 面向对象 —— super 的使用(Python 2.x vs Python 3.x)
  3. java增加内容辅助_Eclipse代码自动提示(内容辅助content assist)
  4. leetcode刷题:删除链表中的节点
  5. 【09】Jenkins:Pipeline 补充
  6. lua -- table.nums
  7. 这几个小工具也太好用了
  8. 百旺如何看是否清卡_百旺开票系统每月清卡怎么操作
  9. [python] Python二维码生成器qrcode库入门
  10. PyTorch搭建LSTM实现多变量多步长时间序列预测(二):单步滚动预测
  11. C# OPCUA 读写结构体
  12. EXCEL中怎样提取部分特定的文本?
  13. 无传感器永磁同步电机电机自适应自抗扰ADRC控制策略
  14. 加速度随机游走_VIO学习之公式推导——IMU篇
  15. 统计数字问题_统计问题
  16. 一起善行,助力乌龙泉小学生户外健康运动
  17. javah 类com.xxxx.xxxx 找不到问题解决方法
  18. opengl 下载安装+vs2010配置
  19. 运行库:Windows下MSVC CRT运行库封装fread()函数解析
  20. 手机如何登录企业邮箱,公司电子邮箱登录页面在哪里?

热门文章

  1. 计算机专业的学生简历范文,计算机专业学生的简历范文精选
  2. 如何打开一个已经保存的微信小程序
  3. 滑铁卢计算机专业世界最新排名,滑铁卢大学计算机专业世界排名介绍
  4. 意念云分发是干嘛的?
  5. 糗事百科-动态获取全部页码数并爬取图片
  6. display, visibility, overflow 三者的作用与区别
  7. 关键路径例题图表_算法学习记录-图——应用之关键路径(Critical Path)
  8. nslookup 入门命令详解
  9. 信用评分的简单小结(ROC,IV,WOE)
  10. 2019金九银十前端面经总结,java面试问题大全及答案大全word