在 Matlab 中从 bwtraceboundary 创建掩码

Create mask from bwtraceboundary in Matlab

我正在尝试创建一个遮罩(或类似结果)以擦除未附加到被边界包围的对象的二进制图像片段。我看到这个线程 (http://www.mathworks.com/matlabcentral/answers/120579-converting-boundary-to-mask) 从 bwboundaries 执行此操作,但我无法对其进行适当的更改。我的目标是使用这段代码来隔离这张地形图连接的部分,并去掉多余的部分。我需要保留边界区域内的结构,因为我当时打算使用 bwboundaries 为主要对象的 "interior" 结构创建额外的边界线。

以下是我的代码,首先通过搜索黑色区域左下角的像素开始跟踪来创建单个边界线。它只是寻找图像中不是全白的第一列并选择最后一个黑色像素。第二部分是创建内部边界线。请注意,我正在尝试这两个步骤的过程,但如果有一种方法可以只用一个步骤来完成,我也想听听那个解决方案。最终我只想要主要的、大的黑色区域及其内部的孔的边界,同时摆脱周围多余的部分。

 figName='Images/BookTrace_1';

BW = imread([figName,'.png']);
    BW=im2bw(BW);
    imshow(BW,[]);

    for j=1:size(BW,2)
        if sum(BW(:,j))~=sum(BW(:,1))
            corner=BW(:,j);
            c=j-1;
            break
        end
    end
    r=find(corner==0);
    r=r(end);

    outline = bwtraceboundary(BW,[r c],'W',8,Inf,'counterclockwise');
    hold on;
    plot(outline(:,2),outline(:,1),'g','LineWidth',2);


[B,L] = bwboundaries(BW);
hold on
for k = 1:length(B)
    boundary = B{k};
    plot(boundary(:,2), boundary(:,1), 'g', 'LineWidth', 2)
end

非常感谢任何建议或提示。如果有问题,请告诉我,我会更新post。谢谢!

编辑:为澄清起见,我的最终目标如下图所示。我需要追踪附加到主要对象的所有外部和内部边界,同时消除所有未附加到它的备用小块。

很简单。我实际上不会使用上面的代码,而是使用图像处理工具箱。有一个 built-in 函数可以删除任何接触图像边界的白色像素。使用 imclearborder 函数。

该函数将 return 一个新的二值图像,其中任何接触图像边界的像素都将被删除。鉴于您的代码,它非常简单:

out = imclearborder(BW);

以上面的图像为例,我将对其进行阈值处理,以便删除绿线......或者更确切地说与其他白色像素合并,我将调用上面的函数:

BW = imread('http://i.stack.imgur.com/jhLOw.png'); %// Read from Whosebug
BW = im2bw(BW); %// Convert to binary
out = imclearborder(BW); %// Remove pixels along border
imshow(out); %// Show image

我们得到:


如果您想要相反的效果,即您想要保留边界并移除内部的所有其他内容,只需复制原始图像并使用上面的输出将这些像素位置设为空即可创建一个新图像。

out2 = BW; %// Make copy
out2(out) = 0; %// Set pixels not belonging to boundary to 0
imshow(out2); %// Show image

我们因此得到:

编辑

鉴于以上期望的输出,我相信我现在知道你想要什么了。您希望为每组像素填充孔并沿着所需结果的边界进行跟踪。我们将其分为两类这一事实将很有用。对于那些在内部的对象,使用 imfill function and specify the holes option to fill in any of the black holes so that they're white. For the objects that exterior, this will need a bit of work. What I would do is invert the image so that pixels that are black become white and vice-versa, then use the bwareaopen 函数清除任何面积低于一定数量的像素。这将移除那些沿着外部区域边界的孤立的小黑色区域。完成后,re-invert 图片。这样做的效果是小孔将被消除。我为该区域选择了 500 像素的阈值...似乎效果很好。

因此,以上述变量为参考,这样做:

%// Fill holes for both regions separately
out_fill = imfill(out, 'holes');
out2_fill = ~bwareaopen(~out2, 500);

%// Merge together
final_out = out_fill | out2_fill; 

这是我们得到的:

如果您想要像示例中那样漂亮的绿色边框来说明这一点,您可以这样做:

perim = bwperim(final_out);
red = final_out;
green = final_out;
blue = final_out;
red(perim) = 0;
blue(perim) = 0;
out_colour = 255*uint8(cat(3, red, green, blue));
imshow(out_colour);

上面的代码找到了物体的周长,然后我们创建一个新图像,其中沿周长的红色和蓝色通道设置为 0,同时将绿色通道设置为 255。

我们得到这个:

您可以忽略图像周围的绿色像素边框。这只是我沿着图像中的对象查找周长的方式的副作用。事实上,你提供给我的图像有一个白色像素边框环绕着整个区域,所以我不确定这是否是故意的,或者这是否是整个宏伟计划的一部分。


为了合并成一个工作示例以便您可以复制并粘贴到 MATLAB 中,以下是一个代码块中的所有代码:

%// Pre-processing
BW = imread('http://i.stack.imgur.com/jhLOw.png'); %// Read from Whosebug
BW = im2bw(BW); %// Convert to binary

out = imclearborder(BW); %// Remove pixels along border

%// Obtain pixels that are along border
out2 = BW; %// Make copy
out2(out) = 0; %// Set pixels not belonging to boundary to 0

%// Fill holes for both regions separately
out_fill = imfill(out, 'holes');
out2_fill = ~bwareaopen(~out2, 500);

%// Merge together
final_out = out_fill | out2_fill; 

%// Show final output
figure;
imshow(final_out);

%// Bonus - Show perimeter of output in green
perim = bwperim(final_out);
red = final_out;
green = final_out;
blue = final_out;
red(perim) = 0;
blue(perim) = 0;
out_colour = 255*uint8(cat(3, red, green, blue));
figure;
imshow(out_colour);