Image 在Matlab中从bwtraceboundary创建掩码

Image 在Matlab中从bwtraceboundary创建掩码,image,matlab,image-processing,mask,boundary,Image,Matlab,Image Processing,Mask,Boundary,我正在尝试创建一个遮罩或类似的结果,以便擦除未附着到边界包围的对象的二进制图像片段。我从BWBounders看到了这个线程,但是我很难对它进行适当的更改。我的目标是使用此代码来隔离此地形图中连接的部分,并除去多余的部分。我需要保留边界区域内的结构,因为我将使用边界创建主对象内部结构的附加边界线 下面是我的代码,通过搜索黑色区域的左下角像素开始跟踪,首先创建单个边界线。它只查找图像的第一列,该列不是完全白色的,并选择最后一个黑色像素。第二部分是创建内部边界线。请注意,我正在尝试这两个步骤的过程,但

我正在尝试创建一个遮罩或类似的结果,以便擦除未附着到边界包围的对象的二进制图像片段。我从BWBounders看到了这个线程,但是我很难对它进行适当的更改。我的目标是使用此代码来隔离此地形图中连接的部分,并除去多余的部分。我需要保留边界区域内的结构,因为我将使用边界创建主对象内部结构的附加边界线

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

 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
非常感谢您的任何建议或提示。如果有问题,请告诉我,我会更新帖子。谢谢大家!

编辑:为了澄清,我的最终目标如下图所示。我需要跟踪连接到主对象的所有外部和内部边界,同时消除未连接到它的任何备用小块。
这很简单。实际上,我不会使用上面的代码,而是使用图像处理工具箱。有一个内置的功能,以删除任何白色像素,接触到图像的边界。使用该函数

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

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
我们得到:

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

out2 = BW; %// Make copy
out2(out) = 0; %// Set pixels not belonging to boundary to 0
imshow(out2); %// Show image
因此,我们得到:

编辑 鉴于上述期望输出,我相信我知道您现在想要什么。您希望填充每组像素的孔,并沿着所需结果的边界进行跟踪。事实上,我们将其分为两类将是有用的。对于那些位于内部的对象,使用函数并指定“孔”选项来填充任何黑洞,使其为白色。对于外部的对象,这将需要一些工作。我要做的是反转图像,使黑色的像素变为白色,反之亦然,然后使用该函数清除任何面积低于一定量的像素。这将删除沿外部区域边界的小孤立黑色区域。完成后,重新反转图像。这样做的效果是小孔将被消除。我为该区域选择了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 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);

这很简单。实际上,我不会使用上面的代码,而是使用图像处理工具箱。有一个内置的功能,以删除任何白色像素,接触到图像的边界。使用该函数

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

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
我们得到:

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

out2 = BW; %// Make copy
out2(out) = 0; %// Set pixels not belonging to boundary to 0
imshow(out2); %// Show image
因此,我们得到:

编辑 鉴于上述期望输出,我相信我知道您现在想要什么。您希望填充每组像素的孔,并沿着所需结果的边界进行跟踪。事实上,我们将其分为两类将是有用的。对于那些位于内部的对象,使用函数并指定“孔”选项来填充任何黑洞,使其为白色。对于外部的对象,这将需要一些工作。我要做的是反转图像,使黑色的像素变为白色,反之亦然,然后使用该函数清除任何面积低于一定量的像素。这将删除沿外部区域边界的小孤立黑色区域。完成后,重新反转图像。这样做的效果是小孔将被消除。我为该区域选择了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 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);

这是一个非常值得了解的功能!不过我很抱歉,我想我可能不清楚我需要什么。我想把绿色边界之外的所有东西都移走,但把所有东西都放在里面。所以,这两个选项只能给我一个或另一个,除非我误解了?@jmolaro对不起,我不明白。。。如果你想移除绿色边界之外的所有东西,那不是第二种选择吗?你能告诉我理想的输出是什么样子吗?@jmolaro-好的,你想删除图像中那些用绿色描绘的像素吗?我还是不太明白你想要什么。@jmolaro-对不起,不是真的。所需的输出描述说明了一件事,但图像说明了另一件事。你给我看的图像基本上跟踪了图像中所有白色对象的所有边界。这与我需要追踪所有连接到主要对象的外部和内部边界相冲突,同时消除任何未连接到它的备用小块。。。。。对我来说,这是我为你提供的第二个选择。你看到我的图像和你的图像中被擦除的片段了吗?比如,山顶上的黑色小岛?另外,在你的第二个选择中,许多白色湖泊从黑色物体中消失了。这是一个需要了解的伟大功能!不过我很抱歉,我想我可能不清楚我需要什么。我想把绿色边界之外的所有东西都移走,但把所有东西都放在里面。所以,这两个选项只能给我一个或另一个,除非我误解了?@jmolaro对不起,我不明白。。。如果你想移除绿色边界之外的所有东西,那不是第二种选择吗?你能告诉我理想的输出是什么样子吗?@jmolaro-好的,你想删除图像中那些用绿色描绘的像素吗?我还是不太明白你想要什么。@jmolaro-对不起,不是真的。所需的输出描述说明了一件事,但图像说明了另一件事。你给我看的图像基本上跟踪了图像中所有白色对象的所有边界。这与我需要追踪所有连接到主要对象的外部和内部边界相冲突,同时消除任何未连接到它的备用小块。。。。。对我来说,这是我为你提供的第二个选择。你看到我的图像和你的图像中被擦除的片段了吗?比如,山顶上的黑色小岛?另外,在第二个选项中,许多白色湖泊从黑色对象中消失。