数字图像处理-二值形态学图像处理
文章目录
1.边缘提取
1.采用以下步骤提取原图像A的边缘,绘制出结果图像C和D。
-
原图像为A,结构元为B
-
A在B作用下进行腐蚀,得到图像C
-
用原图像A减去C,得到边缘图像D
本题考验的是我们的对腐蚀图像处理方法的掌握程度,腐蚀的含义是在B完全包括在A时,B的原点位置的集合。因此(1)问通过对腐蚀的含义进行模板运算得到结果,而(2)问相当于是(1)的延申,可以理解为A交B。
腐蚀公式如下:
A在B腐蚀后的结果C:
原图A减去腐蚀得到的C得到D:
从该过程中,充分的了解到膨胀,腐蚀,开,闭运算的方式和作用,膨胀可以桥接断裂的图像,腐蚀可以去除图像中边界点使得图像向内部收缩。开闭运算是在腐蚀和膨胀运算的结合,只是顺序不同,开运算先腐蚀再膨胀得使得边界突出更加平滑去除孤立区域,闭运算先膨胀后腐蚀,使得内部间隙被填充,通过开闭运算可修补断裂的指纹。
2 孔洞填充
采用以下步骤填充原图像A的孔洞
-
①原图像为A,结构元为B;
-
求带孔洞图像A的补集,记为Ac
-
在孔洞内选择一个点,并将该点作为初始化的X0。
-
利用条件膨胀,即下面形态学运算得到Xk(k=1,2,…)。
Xk=(Xk-1⨁B)∩Ac
-
判断Xk=Xk-1是否成立,如果成立转下一步,否则,转步骤(4)。
-
利用步骤(5)中得到的Xk和A求并集,得到最后的目标结果。按上述步骤绘制出图像A被逐步填充的过程图。
效果图:
3.使用bwmorph函数填充下图中的孔洞。
本题考验的是我们的对孔洞填充的实际运用,孔洞填充可通过结构元的膨胀来实现,通过将选定的点不断的膨胀并与原图像的补码相交后与之前的图像相比较直到我们能够达到前一次与这一次填充之后的效果相同后与原图像求并集得到最终结果。
代码:
A = imread('Fig0916(a)(region-filling-reflections).tif');
A = imbinarize(A); %二值化
figure(1);
subplot(1,2,1);imshow(A);title('二值化后的图');
%首先对A求补步骤1
A_ct = ~A; %A的补集
%得到图像的大小
[m,n] = size(A);
%新建一个矩阵
X = zeros(m,n);
%找到灰度值为1的坐标点
[k,z] = find(A==1);
%选取第一个灰度值为1的点做为模板的初始点
X(k(1),z(1)) = 1;
%膨胀结构元
se = [0,1,0;1,1,1;0,1,0]; %结构元
over = 0; %判断是否迭代结束
i = 0; %迭代次数
while(~over)
i = i + 1;
Xp = X;
%步骤4;膨胀后与补集求交集
X = bwmorph(X,'dilate') & A_ct;%imdilate(X,se) & A_ct;
if X == Xp %步骤5判断二者相等,相等迭代结束
over = 1;
end
end
fprintf('%2d',i);
A = ~X | A; %步骤6求并集
subplot(1,2,2);
imshow(A);
title('填充结果');
效果图:
本题考验的是我们的对孔洞填充的实际运用,孔洞填充可通过结构元的膨胀来实现,通过将选定的点不断的膨胀并与原图像的补码相交后与之前的图像相比较直到我们能够达到前一次与这一次填充之后的效果相同后与原图像求并集得到最终结果。
通过此时实践,确实是了解到了很多的东西,因为不知道原来其实只要不断的迭代膨胀就可以得到结果,还想着通过计算连通分量的情况确定每一个孔洞的大小并逐个填充,收获了更多的知识。
4 从重叠的两个或多个颗粒组中分离出各圆形颗粒。假设所有颗粒大小相同,请给出算法生成只包含如下颗粒的图像。
- 只包含重叠的颗粒。
2.只包含不重叠的颗粒。
代码:
clc;clear;
%读入图像
f=imread('FigP0936(bubbles_on_black_background).tif');
[a,b]=size(f);
%开运算
se=strel('disk',3');%圆盘型结构元素
f=imopen(f,se);figure();subplot(2,2,1);imshow(f);title('二值化图像');
% L为标记矩阵,n为找到连接分量的总数
[L,n]=bwlabel(f);
%仅与边界重叠的颗粒
f1=f;
flag = zeros(n) ; %记录边界值
%与左右边界重叠的颗粒将其所有的连通量都置为黑色
for k=1:a
if(L(k,1)~=0)
flag(L(k,1))=1;
I= L==L(k,1);
f1(I)=0;
I=0;
end
if(L(k,b)~=0)
flag(L(k,b))=1;
I= L==L(k,b);
f1(I)=0;
I=0;
end
end
%与上下边界
for k=1:b
if(L(1,k)~=0)
flag(L(1,k))=1;
[I]=find(L==L(1,k));
f1(I)=0;
I=0;
end
if(L(a,k)~=0)
flag(L(a,k))=1;
[I]=find(L==L(a,k));
f1(I)=0;
I=0;
end
end
f1=f-f1;subplot(2,2,2);imshow(f1);title('仅与边界重叠的');
%仅与彼此重叠的颗粒,面积在300~450间
f2=f;
for k=1:n
[r,c]=find(L==k);
if( size(r,1)>350 && size(r,1)<450 )
for i=1:size(r,1)
f2(r(i),c(i))=0;
end
end
end
f2=f-f2;f2 = f2-f1;subplot(2,2,3);imshow(f2);title('没有重叠的颗粒(去除边界)');
%重叠的颗粒
f3=f;
for k=1:n
[r,c]=find(L==k);
if( size(r,1)>450)
for i=1:size(r,1)
f3(r(i),c(i))=0;
end
end
end
f3=f-f3;f3 = f3 - f1;subplot(2,2,4);;imshow(f3);title('发生重叠的颗粒(去除边界)');
%找到最小的连通颗粒 ,不在边界处的最大颗粒
num = zeros(n)
max = 0;
for i=1:n
num(i) = size(find(L==i),1);
if flag(i) == 1
continue;
end
if (num(i)>max)
max = num(i);
end
end
a = min(num,[],1);
fprintf("最小的连通量是 %d\n",a(1));
fprintf("最大的连通量是 %d\n",max);
效果图:
本题考验的是我们的对连通分量知识的实际操作,在开始分离图像之前需要对图像先进行开运算平滑处理去除尖锐部分噪声,通过统计连通分量并计算每一个连通分量的大小得到一个只包含重叠的颗粒的大小,并将其他颗粒从原图像中减出去,需要值得注意的是,由于边界有一圈的白边会对计算分量的大小造成干扰,我在这个过程中将临近边缘的连通分量都删掉了。
题目4的结果是不临近边界的最小连通颗粒是389,而最大的颗粒是3854;通过计算可以得到一颗圆形颗粒的大小大概再350-450之间,因此只需要保留该区域大小的连通分量就实现了分离出重复或不重复或边界区域的目的。