Main Content

标记控制的分水岭分割

此示例说明如何使用分水岭分割来分离图像中相互接触的对象。分水岭变换通过将图像视为一个曲面,其中亮像素表示较高处,暗像素表示较低处,从而找出图像中的“汇水盆地”和“分水岭脊线”。

如果您能够标识或“标记”前景对象和背景位置,使用分水岭变换的分割效果会更好。标记控制的分水岭分割遵循以下基本过程:

  1. 计算分割函数。这得到是一个图像,其中暗区域是您尝试分割的对象。

  2. 计算前景标记。这些是每个对象中连通的像素斑点。

  3. 计算背景标记。这些像素不是任何对象的一部分。

  4. 修正分割函数,使其仅在前景和背景标记位置具有最小值。

  5. 计算修正分割函数的分水岭变换。

步骤 1:读入彩色图像并将其转换为灰度

rgb = imread("pears.png");
I = im2gray(rgb);
imshow(I)

text(732,501,"Image courtesy of Corel(R)",...
     "FontSize",7,"HorizontalAlignment","right")

Figure contains an axes object. The hidden axes object contains 2 objects of type image, text.

步骤 2:使用梯度幅值作为分割函数

计算梯度幅值。对象边界处的梯度较高,对象内部的梯度较低(大多数情况下)。

gmag = imgradient(I);
imshow(gmag,[])
title("Gradient Magnitude")

Figure contains an axes object. The hidden axes object with title Gradient Magnitude contains an object of type image.

您能通过直接对梯度幅值使用分水岭变换来分割图像吗?

L = watershed(gmag);
Lrgb = label2rgb(L);
imshow(Lrgb)
title("Watershed Transform of Gradient Magnitude")

Figure contains an axes object. The hidden axes object with title Watershed Transform of Gradient Magnitude contains an object of type image.

不能。如果没有额外的预处理,例如以下标记计算,直接使用分水岭变换通常会导致“过度分割”。

步骤 3:标记前景对象

此处可以应用多种过程来找到前景标记,这些标记必须是每个前景对象内部的连通像素斑点。在此示例中,您使用称为“开运算重构”和“闭运算重构”的形态学方法来“清理”图像。这些运算将在每个对象内创建最大值平面,使用 imregionalmax 可以找出这些最大值。

开运算是先腐蚀后膨胀,而开运算重构是先腐蚀后进行形态学重构。让我们对两者进行比较。首先,使用 imopen 进行开运算。

se = strel("disk",20);
Io = imopen(I,se);
imshow(Io)
title("Opening")

Figure contains an axes object. The hidden axes object with title Opening contains an object of type image.

接下来,使用 imerodeimreconstruct 进行开运算重构。

Ie = imerode(I,se);
Iobr = imreconstruct(Ie,I);
imshow(Iobr)
title("Opening-by-Reconstruction")

Figure contains an axes object. The hidden axes object with title Opening-by-Reconstruction contains an object of type image.

在开运算后闭运算可以去除暗点和针状标记。对常规形态学闭运算和闭运算重构进行比较。首先尝试 imclose

Ioc = imclose(Io,se);
imshow(Ioc)
title("Opening-Closing")

Figure contains an axes object. The hidden axes object with title Opening-Closing contains an object of type image.

现在使用 imdilate,然后使用 imreconstruct。请注意,您必须对 imreconstruct 的输入和输出进行补充。

Iobrd = imdilate(Iobr,se);
Iobrcbr = imreconstruct(imcomplement(Iobrd),imcomplement(Iobr));
Iobrcbr = imcomplement(Iobrcbr);
imshow(Iobrcbr)
title("Opening-Closing by Reconstruction")

Figure contains an axes object. The hidden axes object with title Opening-Closing by Reconstruction contains an object of type image.

通过比较 IobrcbrIoc 可以看到,在去除小瑕疵而不影响对象整体形状方面,基于重构的开运算和闭运算比标准的开运算和闭运算更高效。计算 Iobrcbr 的局部最大值,以获得良好的前景标记。

fgm = imregionalmax(Iobrcbr);
imshow(fgm)
title("Regional Maxima of Opening-Closing by Reconstruction")

Figure contains an axes object. The hidden axes object with title Regional Maxima of Opening-Closing by Reconstruction contains an object of type image.

为了帮助解释结果,可将前景标记图像叠加在原始图像上。

I2 = labeloverlay(I,fgm);
imshow(I2)
title("Regional Maxima Superimposed on Original Image")

Figure contains an axes object. The hidden axes object with title Regional Maxima Superimposed on Original Image contains an object of type image.

请注意,一些大部分被遮挡和遮蔽的对象未被标记,这意味着在最终结果中不会正确分割这些对象。此外,一些对象中的前景标记一直延伸到对象的边缘。这意味着您应清理标记斑点的边缘,然后将它们缩小一点。您可以通过先闭运算再腐蚀来实现这一点。

se2 = strel(ones(5,5));
fgm2 = imclose(fgm,se2);
fgm3 = imerode(fgm2,se2);

此过程往往会留下一些必须删除的杂散孤立像素。您可以使用 bwareaopen 来实现这一点,它可以删除像素少于特定数量的所有斑点。

fgm4 = bwareaopen(fgm3,20);
I3 = labeloverlay(I,fgm4);
imshow(I3)
title("Modified Regional Maxima Superimposed on Original Image")

Figure contains an axes object. The hidden axes object with title Modified Regional Maxima Superimposed on Original Image contains an object of type image.

步骤 4:计算背景标记

现在您需要标记背景。在清理后的图像 Iobrcbr 中,暗像素属于背景,因此您可以首先进行阈值化运算。

bw = imbinarize(Iobrcbr);
imshow(bw)
title("Thresholded Opening-Closing by Reconstruction")

Figure contains an axes object. The hidden axes object with title Thresholded Opening-Closing by Reconstruction contains an object of type image.

背景像素为黑色,但理想情况下,我们不希望背景标记太靠近我们尝试分割的对象的边缘。我们将通过计算 bw 前景的“影响区骨架”(即 SKIZ)来“精简”背景。通过计算 bw 的距离变换的分水岭变换,然后寻找结果的分水岭脊线 (DL == 0),可以实现这一目标。

D = bwdist(bw);
DL = watershed(D);
bgm = DL == 0;
imshow(bgm)
title("Watershed Ridge Lines")

Figure contains an axes object. The hidden axes object with title Watershed Ridge Lines contains an object of type image.

步骤 5:计算分割函数的分水岭变换

函数 imimposemin 可用于修正图像,使其仅在特定所需位置具有局部最小值。在此处,您可以使用 imimposemin 来修正梯度幅值图像,使其局部最小值只出现在前景和背景标记像素上。

gmag2 = imimposemin(gmag, bgm | fgm4);

最后,计算基于分水岭的分割。

L = watershed(gmag2);

步骤 6:可视化结果

一种可视化方法是在原始图像上叠加前景标记、背景标记和分割的对象边界。您可以根据需要使用膨胀来使某些方面(如对象边界)更明显可见。对象边界位于 L == 0 的位置。二值前景和背景标记缩放为不同整数值,以便对它们分配不同标签。

labels = imdilate(L==0,ones(3,3)) + 2*bgm + 3*fgm4;
I4 = labeloverlay(I,labels);
imshow(I4)
title("Markers and Object Boundaries Superimposed on Original Image")

Figure contains an axes object. The hidden axes object with title Markers and Object Boundaries Superimposed on Original Image contains an object of type image.

此可视化图像说明前景和背景标记的位置如何影响结果。在一些位置,部分被遮挡的较暗对象与其较亮的相邻对象已合并,因为被遮挡的对象没有前景标记。

另一种有用的可视化方法是将标签矩阵显示为彩色图像。标签矩阵,如 watershedbwlabel 生成的矩阵,可通过使用 label2rgb 转换为真彩色图像,以实现可视化目的。

Lrgb = label2rgb(L,"jet","w","shuffle");
imshow(Lrgb)
title("Colored Watershed Label Matrix")

Figure contains an axes object. The hidden axes object with title Colored Watershed Label Matrix contains an object of type image.

您可以使用透明方式将此伪颜色标签矩阵叠加到原始强度图像上。

figure
imshow(I)
hold on
himage = imshow(Lrgb);
himage.AlphaData = 0.3;
title("Colored Labels Superimposed Transparently on Original Image")

Figure contains an axes object. The hidden axes object with title Colored Labels Superimposed Transparently on Original Image contains 2 objects of type image.

另请参阅

| | | | | | | | | | | |