首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在MATLAB中选择最大轮廓

如何在MATLAB中选择最大轮廓
EN

Stack Overflow用户
提问于 2015-02-19 18:25:57
回答 3查看 3.2K关注 0票数 2

在我的工作过程中,我必须发现一种寄生虫。我用HSV找到了寄生虫,后来把它变成了灰色图像。现在我也做了边缘检测。我需要一些代码,告诉MATLAB找到最大的轮廓(寄生虫),并使其余的区域为黑色像素。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-19 18:58:55

你可以选择“最大”的轮廓,通过填充每个轮廓周围的洞,找出哪个形状给你最大的面积,然后使用最大区域的位置,然后复制到最后的图像。正如Benoit_11所建议的那样,使用regionprops --特别是AreaPixelList标志。就像这样:

代码语言:javascript
复制
im = imclearborder(im2bw(imread('http://i.stack.imgur.com/a5Yi7.jpg')));
im_fill = imfill(im, 'holes');
s = regionprops(im_fill, 'Area', 'PixelList');
[~,ind] = max([s.Area]);
pix = sub2ind(size(im), s(ind).PixelList(:,2), s(ind).PixelList(:,1));
out = zeros(size(im));
out(pix) = im(pix);
imshow(out);

第一行代码直接从StackOverflow读取图像。由于某些原因,图像也是RGB图像,因此我通过im2bw将其转换为二进制。在图像周围还有一条白色的边框。您很可能在figure中打开了这个图像,并将图像从图形中保存下来。我通过使用imclearborder删除白色边框来消除这个问题。

接下来,我们需要填充等高线环绕的区域,所以使用imfillholes标志。接下来,使用regionprops分析图像中不同的填充对象--特别是Area,以及哪些像素属于填充图像中的每个对象。一旦我们获得这些属性,找到给出最大面积的填充轮廓,然后访问正确的regionprops元素,提取出属于对象的像素位置,然后使用这些像素并将像素复制到输出图像并显示结果。

我们得到:

或者,您可以使用Perimeter标志(如Benoit_11建议的那样),只需找到与最大等高线对应的最大周长即可。这还是能给你你想要的。因此,只需在第三行和第四行代码中将Area标志替换为Perimeter,您仍然应该得到相同的结果。

票数 3
EN

Stack Overflow用户

发布于 2015-02-19 19:07:00

这可能是一种方法-

代码语言:javascript
复制
%// Read in image as binary
im = im2bw(imread('http://i.stack.imgur.com/a5Yi7.jpg'));
im = im(40:320,90:375); %// clear out the whitish border you have
figure, imshow(im), title('Original image')

%// Fill all contours to get us filled blobs and then select the biggest one
outer_blob = imfill(im,'holes');
figure, imshow(outer_blob), title('Filled Blobs')

%// Select the biggest blob that will correspond to the biggest contour
outer_blob = biggest_blob(outer_blob); 

%// Get the biggest contour from the biggest filled blob
out = outer_blob & im;
figure, imshow(out), title('Final output: Biggest Contour')

基于biggest_blob的函数bsxfun可以替代这里发布的其他答案在regionprops中所做的操作。根据我的经验,我发现这种基于bsxfun的技术比regionprops更快。Here are few benchmarks在前面的一个答案上比较了这两种技术的运行时性能。

相关功能-

代码语言:javascript
复制
function out = biggest_blob(BW)

%// Find and labels blobs in the binary image BW
[L, num] = bwlabel(BW, 8); 

%// Count of pixels in each blob, basically should give area of each blob
counts = sum(bsxfun(@eq,L(:),1:num)); 

%// Get the label(ind) cooresponding to blob with the maximum area 
%// which would be the biggest blob
[~,ind] = max(counts);

%// Get only the logical mask of the biggest blob by comparing all labels 
%// to the label(ind) of the biggest blob
out = (L==ind);

return;

调试图像-

票数 3
EN

Stack Overflow用户

发布于 2015-02-19 19:11:17

既然我的答案差不多都写好了,我还是会给你的,但是这个想法和@rayryeng的回答很相似。

基本上,我在调用Perimeter时使用regionpropsPixelIdxList标志,因此,一旦使用imclearborder删除图像边框,就可以得到构成最大轮廓的像素的线性索引。

以下是代码:

代码语言:javascript
复制
clc
clear


BW = imclearborder(im2bw(imread('http://i.stack.imgur.com/a5Yi7.jpg')));

S= regionprops(BW, 'Perimeter','PixelIdxList');

[~,idx] = max([S.Perimeter]);

Indices = S(idx).PixelIdxList;

NewIm = false(size(BW));

NewIm(Indices) = 1;

imshow(NewIm)

以及产出:

正如你所看到的,有很多方法可以达到同样的效果,哈哈。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28614074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档