使用纹理滤波器的纹理分割
此示例说明如何根据纹理识别和分割区域。
读取图像
读取并显示一个挎包上的纹理图案的灰度图像。
I = imread('bag.png'); imshow(I) title('Original Image')
创建纹理图像
使用 entropyfilt
创建纹理图像。函数 entropyfilt
返回一个数组,其中每个输出像素包含输入图像 I
中对应像素周围 9×9 邻域的熵值。熵是随机性的统计测度。
您还可以使用 stdfilt
和 rangefilt
来获得类似的分割结果。为了与局部熵的纹理图像进行比较,创建分别显示局部标准差和局部范围的纹理图像 S
和 R
。
E = entropyfilt(I); S = stdfilt(I,ones(9)); R = rangefilt(I,ones(9));
使用 rescale
重新缩放纹理图像 E
和 S
,使像素值在数据类型为 double
的图像的预期范围 [0, 1] 内。
Eim = rescale(E); Sim = rescale(S);
以蒙太奇方式显示三个纹理图像。
montage({Eim,Sim,R},'Size',[1 3],'BackgroundColor','w',"BorderSize",20) title('Texture Images Showing Local Entropy, Local Standard Deviation, and Local Range')
为底部纹理创建掩膜
此示例继续处理熵纹理图像 Eim
。您可以对其他两种类型的具有其他形态学函数的纹理图像重复类似的过程,以获得类似的分割结果。
对重新缩放后的图像 Eim
设置阈值以分割纹理。选择 0.8 的阈值,因为它大致是纹理之间边界上像素的强度值。
BW1 = imbinarize(Eim,0.8);
imshow(BW1)
title('Thresholded Texture Image')
二值图像 BW1
中的分割对象是白色。如果您比较 BW1
和 I
,会注意到顶部纹理过度分割(多个白色对象),底部纹理几乎整体分割。使用 bwareaopen
删除顶部纹理中的对象。
BWao = bwareaopen(BW1,2000);
imshow(BWao)
title('Area-Opened Texture Image')
使用 imclose
对边缘进行平滑处理,并使 BWao
中对象的任何开放孔洞闭合。指定 entropyfilt
使用的相同 9×9 邻域。
nhood = ones(9);
closeBWao = imclose(BWao,nhood);
imshow(closeBWao)
title('Closed Texture Image')
使用 imfill
填充 closeBWao
中对象的孔洞。底部纹理的掩膜并不完美,因为掩膜没有延伸到图像的底部。但是,您可以使用该掩膜来分割纹理。
mask = imfill(closeBWao,'holes'); imshow(mask); title('Mask of Bottom Texture')
使用掩膜分割纹理
将纹理分成两个不同图像。
textureTop = I; textureTop(mask) = 0; textureBottom = I; textureBottom(~mask) = 0; montage({textureTop,textureBottom},'Size',[1 2],'BackgroundColor','w',"BorderSize",20) title('Segmented Top Texture (Left) and Segmented Bottom Texture (Right)')
显示分割结果
创建一个标签矩阵,其中标签 1 的掩膜是 false
,标签 2 的掩膜是 true
。在原始图像上叠加标签矩阵。
L = mask+1;
imshow(labeloverlay(I,L))
title('Labeled Segmentation Regions')
以青色显示两个纹理之间边界的轮廓。
boundary = bwperim(mask); imshow(labeloverlay(I,boundary,"Colormap",[0 1 1])) title('Boundary Between Textures')
另请参阅
entropyfilt
| bwareaopen
| imclose
| imbinarize
| imfill
| bwperim
| rangefilt