如何select MATLAB中的最大轮廓
How to select the largest contour in MATLAB
在我的进度工作中,我必须检测寄生虫。我用 HSV 找到了寄生虫,后来把它做成灰度图像。现在我也做了边缘检测。我需要一些代码告诉 MATLAB 找到最大的轮廓(寄生虫)并将其余区域设为黑色像素。
您可以 select "largest" 等高线通过填充每个等高线围绕的孔洞,找出哪个形状给您最大的面积,然后使用最大面积的位置并复制它到最终图像。正如 Benoit_11 建议的那样,使用 regionprops
- 特别是 Area
和 PixelList
标志。像这样:
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);
第一行代码直接从 Whosebug 读取您的图像。由于某些原因该图像也是RGB图像,因此我通过im2bw
. There is also a white border that surrounds the image. You most likely had this image open in a figure
and saved the image from the figure. I got rid of this by using imclearborder
将其转换为二进制以去除白色边框。
接下来,我们需要填充轮廓包围的区域,所以使用 imfill
和 holes
标志。接下来,使用 regionprops
来分析图像中不同的填充对象 - 特别是 Area
以及填充图像中每个对象属于哪些像素。一旦我们获得这些属性,找到给你最大面积的填充轮廓,然后访问正确的 regionprops
元素,提取属于对象的像素位置,然后使用这些并将像素复制到输出图像并显示结果。
我们得到:
或者,您可以使用 Perimeter
标志(如 Benoit_11 所建议的那样),并简单地找到与最大轮廓相对应的最大周长。这仍然应该给你你想要的。因此,只需将代码的第三行和第四行中的 Area
标志替换为 Perimeter
,您应该仍会得到相同的结果。
这可能是一种方法 -
%// 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')
基于 bsxfun
的函数 biggest_blob
是此处发布的其他答案使用 regionprops
执行的替代方法。根据我的经验,我发现这种基于 bsxfun
的技术比 regionprops
更快。 Here are few benchmarks 在我之前的一个回答中比较这两种技术的运行时性能。
关联函数-
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;
调试图像 -
由于我的答案几乎都写出来了,所以无论如何我都会给你,但这个想法类似于@rayryeng 的答案。
基本上我在调用 regionprops
期间使用 Perimeter
和 PixelIdxList
标志,因此一旦图像边界被使用 imclearborder
.
删除
代码如下:
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)
并且输出:
如你所见,有很多方法可以达到相同的结果哈哈。
在我的进度工作中,我必须检测寄生虫。我用 HSV 找到了寄生虫,后来把它做成灰度图像。现在我也做了边缘检测。我需要一些代码告诉 MATLAB 找到最大的轮廓(寄生虫)并将其余区域设为黑色像素。
您可以 select "largest" 等高线通过填充每个等高线围绕的孔洞,找出哪个形状给您最大的面积,然后使用最大面积的位置并复制它到最终图像。正如 Benoit_11 建议的那样,使用 regionprops
- 特别是 Area
和 PixelList
标志。像这样:
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);
第一行代码直接从 Whosebug 读取您的图像。由于某些原因该图像也是RGB图像,因此我通过im2bw
. There is also a white border that surrounds the image. You most likely had this image open in a figure
and saved the image from the figure. I got rid of this by using imclearborder
将其转换为二进制以去除白色边框。
接下来,我们需要填充轮廓包围的区域,所以使用 imfill
和 holes
标志。接下来,使用 regionprops
来分析图像中不同的填充对象 - 特别是 Area
以及填充图像中每个对象属于哪些像素。一旦我们获得这些属性,找到给你最大面积的填充轮廓,然后访问正确的 regionprops
元素,提取属于对象的像素位置,然后使用这些并将像素复制到输出图像并显示结果。
我们得到:
或者,您可以使用 Perimeter
标志(如 Benoit_11 所建议的那样),并简单地找到与最大轮廓相对应的最大周长。这仍然应该给你你想要的。因此,只需将代码的第三行和第四行中的 Area
标志替换为 Perimeter
,您应该仍会得到相同的结果。
这可能是一种方法 -
%// 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')
基于 bsxfun
的函数 biggest_blob
是此处发布的其他答案使用 regionprops
执行的替代方法。根据我的经验,我发现这种基于 bsxfun
的技术比 regionprops
更快。 Here are few benchmarks 在我之前的一个回答中比较这两种技术的运行时性能。
关联函数-
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;
调试图像 -
由于我的答案几乎都写出来了,所以无论如何我都会给你,但这个想法类似于@rayryeng 的答案。
基本上我在调用 regionprops
期间使用 Perimeter
和 PixelIdxList
标志,因此一旦图像边界被使用 imclearborder
.
代码如下:
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)
并且输出:
如你所见,有很多方法可以达到相同的结果哈哈。