标记控制的流域细分
此示例显示了如何使用分水岭分段将图像中的接触对象分开。分水岭变换通过将其视为光像素高,深色像素很低的表面通过将其视为图像中的“流域”和“流域山脊线”。
Segmentation using the watershed transform works better if you can identify, or "mark," foreground objects and background locations. Marker-controlled watershed segmentation follows this basic procedure:
计算分割函数。这是一个图像,其黑暗区域是您要细分的对象。
计算前景标记。这些是每个对象中的像素的斑点。
计算背景标记。这些像素不是任何对象的一部分。
修改分割函数,使其仅在前景和背景标记位置具有最小值。
计算修饰分割函数的流域变换。
步骤1:阅读颜色图像并将其转换为灰度
rgb = imread('Pears.png');i = rgb2gray(rgb);imshow(i)文本(732,501,“图片由Corel(R)提供”,,,,...'字体大小',7,'水平对齐',,,,'right')
步骤2:使用梯度幅度作为分割函数
Compute the gradient magnitude. The gradient is high at the borders of the objects and low (mostly) inside the objects.
gmag = imgradient(i);imshow(gmag,[])标题(“梯度幅度”)
您可以通过直接在梯度大小上使用流域转换来分割图像吗?
L =流域(GMAG);lrgb = label2rgb(l);imshow(lrgb)标题('Watershed Transform of Gradient Magnitude')
否。在下面使用分水岭变换的情况下,没有其他预处理(例如下面的标记计算)通常会导致“过度分割”。
步骤3:标记前景对象
可以在此处应用各种过程以找到前景标记,必须将其连接到每个前景对象内部的像素的斑点。在此示例中,您将使用称为“按重建开放”和“逐个构造”的形态技术来“清洁”图像。这些操作将在每个对象内部创建平坦的最大值,可以使用Imrigionalmax
。
开口是一种侵蚀,随后是扩张,而逐个结构是侵蚀,然后是形态重建。让我们比较两者。首先,使用iMopen
。
se = strel('磁盘',20);io = iMopen(i,se);imshow(io)标题(“开放”)
接下来使用imerode
andimreconstruct
。
ie = imerode(i,se);ioBr = imreconstruct(即,i);imshow(iobr)标题(“按重建开放”)
开口后,闭合可以消除黑斑和茎标记。比较常规的形态闭合与逐个结构的结束。第一次尝试快到了
:
ioc = imclose(io,se);imshow(ioc)标题(“开放关闭”)
现在使用不断增加
其次是imreconstruct
。Notice you must complement the image inputs and output ofimreconstruct
。
iobrd = imdilate(iobr,se);iobrcbr = imreconstruct(imComplement(ioBRD),imComplement(ioBR));iobrcbr = imcomplement(iobrcbr);imshow(iobrcbr)标题('Opening-Closing by Reconstruction')
As you can see by comparingiobrcbr
和Ioc
,基于重建的开放和关闭比删除小瑕疵的标准开放和关闭更有效,而不会影响物体的整体形状。计算区域最大iobrcbr
获得良好的前景标记。
fgm = imrigionalmax(iobrcbr);imshow(FGM)标题(“重建开放关闭的区域最大值”)
为了帮助解释结果,将前景标记图像叠加在原始图像上。
i2 = labeloverlay(i,fgm);imshow(i2)标题('Regional Maxima Superimposed on Original Image')
请注意,某些大多数封闭和阴影的对象没有标记,这意味着这些对象在最终结果中不会正确分割。同样,某些对象中的前景标记直至对象的边缘。这意味着您应该清洁标记斑点的边缘,然后将它们缩小一点。您可以通过结束,然后进行侵蚀来做到这一点。
se2 = strel(一个(5,5));fgm2 = imclose(fgm,se2);fgm3 = imerode(fgm2,se2);
此过程倾向于留下一些必须删除的流浪隔离像素。您可以使用Bwareaopen
,它消除了少于一定数量的像素的所有斑点。
fgm4 = bwareaopen(fgm3,20); I3 = labeloverlay(I,fgm4); imshow(I3) title(“修改的区域最大值叠加在原始图像上”)
步骤4:计算背景标记
Now you need to mark the background. In the cleaned-up image,iobrcbr
,深色像素属于背景,因此您可以从阈值操作开始。
bw = imbinarize(iobrcbr);imshow(bw)标题(“重建阈值开放式闭合”)
背景像素为黑色,但理想情况下,我们不希望背景标记太近我们试图分割的对象的边缘。我们将通过计算“影响区域的骨架”或Skiz的前景来“稀薄”背景BW
。This can be done by computing the watershed transform of the distance transform ofBW
,然后寻找流域山脊线(dl == 0
结果。
D = bwdist (bw);DL =分水岭(D);bgm = DL = = 0;imshow(bgm) title(“分水岭线”)
步骤5:计算分割函数的流域变换。
The functionimimposemin
可以用于修改图像,以便它仅在某些所需位置具有区域最小值。在这里您可以使用imimposemin
为了修改梯度幅度图像,以使其唯一的区域最小值出现在前景和背景标记像素上。
gmag2 = imimposemin(gmag, bgm | fgm4);
最后,计算基于流域的细分。
L = watershed(gmag2);
步骤6:可视化结果
一种可视化技术是将原始图像上的前景标记,背景标记和分段对象边界叠加。您可以根据需要使用扩张来进行某些方面,例如对象边界,更明显。对象边界位于l == 0
。将二进制前景标记和背景标记缩放到不同的整数值,以便分配不同的标签。
标签= imdilate(l == 0,一个(3,3)) + 2*bgm + 3*fgm4;i4 = labeloverlay(i,labels);imshow(i4)标题(“标记和物体边界叠加在原始图像上”)
这种可视化说明了前景和背景标记的位置如何影响结果。在几个位置,由于封闭的物体没有前景标记,因此将部分遮挡的深色物体与更明亮的邻居对象合并。
Another useful visualization technique is to display the label matrix as a color image. Label matrices, such as those produced by分水岭
andBwlabel
,,,,can be converted to truecolor images for visualization purposes by usinglabel2rgb
。
lrgb = label2rgb(l,'喷射',,,,'W',,,,“洗牌”);imshow(lrgb)标题(“彩色流域标签矩阵”)
您可以使用透明度将此伪色标签矩阵叠加在原始强度图像之上。
图Imshow(i)保持onhimage = imshow(lrgb);himage.alphadata = 0.3;标题(“彩色标签在原始图像上透明地叠加”)
也可以看看
分水岭
|iMopen
|imreconstruct
|快到了
|不断增加
|Imrigionalmax
|imerode
|Bwareaopen
|BWDIST
|label2rgb
|imcomplement
|Labeloverlay
|imgradient