在Matlab中创建bwtraceboundary的掩码

时间:2015-06-15 03:22:13

标签: image matlab image-processing mask boundary

我试图创建一个蒙版(或类似的结果),以便擦除未附加到边界所包围的对象的二进制图像的片段。我在bwboundaries中看到了这个帖子(http://www.mathworks.com/matlabcentral/answers/120579-converting-boundary-to-mask),但是我在修改它时遇到了麻烦。我的目标是使用此代码来隔离连接的此地形图的一部分,并删除多余的部分。我需要保留有界区域内的结构,因为我将使用bwboundaries创建主要对象"内部"的其他边界线。结构体。

enter image description here

以下是我的代码,首先通过搜索黑色区域的左下角像素来开始跟踪来创建单个边界线。它只是查找图像的第一列,它不是完全白色并选择最后一个黑色像素。然后第二部分创建内部边界线。请注意,我正在尝试这两个步骤,但如果只有一个方法可以做到这一点,我也希望听到这个解决方案。最终我只想要主要的,大的黑色区域和它内部的洞的边界,同时摆脱悬挂的额外的碎片。

 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

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

编辑:为了澄清,我的最终目标如下图所示。我需要跟踪附加到主要对象的所有外边界和内边界,同时消除任何未附加到其上的备用小块。 enter image description here

1 个答案:

答案 0 :(得分:5)

这非常简单。我实际上不会使用上面的代码,而是使用图像处理工具箱。这是一个内置功能,可以删除任何触摸图像边框的白色像素。使用imclearborder功能。

该函数将返回一个新的二进制图像,其中任何触及图像边框的像素都将被删除。鉴于您的代码,它非常简单:

out = imclearborder(BW);

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

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

我们得到:

enter image description here

如果你想要相反的效果,你想要保留边界并删除其他内容,只需通过复制原始图像创建一个新图像,然后使用上面的输出将这些像素位置置零。

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

我们得到:

enter image description here

修改

鉴于以上所需的输出,我相信我现在知道你想要什么。您希望为每组像素填充孔并沿着所需结果的边界进行跟踪。我们将这个分为两类的事实将是有用的。对于内部对象,请使用imfill功能并指定holes选项以填充任何黑洞,以便它们变为白色。对于外部物体,这需要一些工作。我要做的是反转图像,使黑色像素变为白色,反之亦然,然后使用bwareaopen功能清除区域低于一定量的任何像素。这将移除沿着外部区域的边界的那些小的孤立的黑色区域。完成后,重新反转图像。这样做的效果是可以消除小孔。我为该区域选择了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; 

这就是我们得到的:

enter image description here

如果你想要一个漂亮的绿色边框来举例说明这一点,你可以这样做:

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.

我们得到了这个:

enter image description here

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

要整合到一个工作示例中,以便您可以复制并粘贴到MATLAB中,这里是一个代码块中的所有代码:

%// Pre-processing
BW = imread('http://i.stack.imgur.com/jhLOw.png'); %// Read from StackOverflow
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);