imfindcircles
中的圆形霍夫变换。但是,您需要Image Processing Toolbox的8版,该版本从R2012a版本开始提供。如果您没有此工具箱,则不幸的是无法运行:(...但让我们假设您已经拥有它。但是,如果您使用的是早于R2012a版本的东西,Dev-iL在他/她的评论中链接了一些代码,这是在圆形霍夫变换可用之前创建的:http://www.mathworks.com/matlabcentral/fileexchange/9168-detect-circles-with-various-radii-in-grayscale-image-via-hough-transform/
im = imread('http://s29.postimg.org/spkab8oef/image.jpg'); %// Read in the image
im_gray = im2double(rgb2gray(im)); %// Convert to grayscale, then [0,1]
out = imclearborder(im_gray > 0.6); %// Threshold using 0.6, then clear the border
out = imfill(out, 'holes'); %// Fill in the holes
out = imopen(out, strel('square', 3));
out = imclose(out, strel('square', 3));
这是我得到的图片:
现在,应用圆形霍夫变换。一般的语法是:
[centres, radii, metric] = imfindcircles(img, [start_radius, end_radius]);
img
是包含您的形状的二进制图像,start_radius
和end_radius
是您想要查找的圆的最小和最大半径。执行循环霍夫变换以查找在此范围内(以像素为单位)的任何圆。输出如下:
centres
:返回检测到的每个圆的中心位置的(x,y)
坐标。radii
:每个圆的半径。metric
:圆的纯度度量值。较高的值意味着该形状更可能是圆形,反之亦然。我搜索了半径在30至60像素之间的圆。因此:
[centres, radii, metric] = imfindcircles(out, [30, 60]);
plot
和viscircles
的组合来展示检测到的圆以及半径。因此:imshow(out);
hold on;
plot(centres(:,1), centres(:,2), 'r*'); %// Plot centres
viscircles(centres, radii, 'EdgeColor', 'b'); %// Plot circles - Make edge blue
num_circles = numel(radii); %// Get number of circles
struct_reg = []; %// Save the shape analysis per circle / line here
%// For creating our circle in the temporary image
[X,Y] = meshgrid(1:size(out,2), 1:size(out,1));
%// Storing all of our circles in this image
circles_img = false(size(out));
for idx = 1 : num_circles %// For each circle we have...
%// Place our circle inside a temporary image
r = radii(idx);
cx = centres(idx,1); cy = centres(idx,2);
tmp = (X - cx).^2 + (Y - cy).^2 <= r^2;
% // Save in master circle image
circles_img(tmp) = true;
%// Do regionprops on this image and save
struct_reg = [struct_reg; regionprops(tmp)];
end
struct_reg
的单独数组,它将为我们图像中每个圆和线附加一个regionprops
结构体。我使用meshgrid
来确定相对于包含我们形状的图像的(X,Y)
坐标,以便我可以在每次迭代中在空白图像上绘制一个圆。为此,您只需要找到相对于每个圆心的欧几里得距离,并仅在该位置的距离小于r
时将像素设置为true
。完成此操作后,您将仅创建一个圆并过滤掉所有圆。然后,您将在此圆上使用regionprops
,将其添加到我们的circles_img
数组中,该数组仅包含圆,然后继续处理剩余的圆。circles_img
如下所示:
您会注意到绘制的圆很干净,但原始图像中的实际圆有点锯齿状。如果我们尝试使用此清晰图像删除圆,则会在边界周围留下一些残留像素,并且无法完全删除圆本身。为了说明我的意思,如果我仅使用circles_img
尝试删除圆,则您的图像如下所示:
... 不好看,对吧?imreconstruct
进行形态重建,在其中可以将此图像用作种子图像,并指定要处理的原始图像。形态重建的工作实质上是洪水填充。您指定种子像素和要处理的图像,imreconstruct
的工作是从这些种子开始,洪水填充白色,直到我们到达种子像素所在对象的边界。因此:out_circles = imreconstruct(circles_img, out);
regionprops
,并将结果附加到struct_reg
变量中。在执行此操作之前,显然要保存一份原始图像的副本:out_copy = out;
out_copy(out_circles) = false;
struct_reg = [struct_reg; regionprops(out_copy)];
为了举例说明,这是去掉圆形后的图片:
现在,我们分析了所有的形状。请注意,我使用了完整的regionprops
调用,因为我不知道你希望在分析中得到什么...所以我决定给你全部内容。
希望这有所帮助!
regionprops
才能检测到不同的对象。这可行吗? - tsornbwboundaries
,而不是regionprops
。我需要在bwboundaries
中将所有对象分开,即使是圆和线重叠的情况下也要分开。分开的对象的结构并不重要,只要圆仍然是圆,线仍然是线就可以。 - tsorn腐蚀是正确的方法。你应该使用一个更大的结构元素。
怎么样呢
1 腐蚀
2 检测您的对象
3 使用相同的结构元素对每个对象进行膨胀
imfindcircles
,它本质上是圆形霍夫变换,基本上就是链接#2。这是从R2012a
开始提供的。我认为链接#2是在MATLAB中提供此功能之前创建的。但是,我同意您的建议! - rayryeng