霍夫变换 - 找到霍夫变换圆的中心

时间:2015-02-13 22:03:42

标签: matlab computer-vision matlab-figure

我一直在阅读霍夫圆圈以及如何用它来检测圆形物体的中心和半径。虽然我理解变换是如何工作的,但我仍然无法理解如何获得圆心。下面的代码片段纯粹是为MATLAB中的coins.png定制的。我尝试了一个稍微复杂一点的图片,它失败了。我正在修复半径,然后获取累加器矩阵。

代码:

temp = accum;
temp(find(temp<40))=0; %Thresholding
imshow(temp,[0 max(temp(:))])
temp = imdilate(temp, ones(6,6)); %Dilating
imshow(temp,[0 max(max(temp))]);
temp = imerode(temp,ones(3,3)); %Eroding
imshow(temp,[0 max(max(temp))]);
s = regionprops(im2bw(temp),'centroid'); %Computing centroid
centroids = cat(1, s.Centroid);

Hough Transform of coins.png with radius = 28

我想在不同的图片上测试代码,并在google上找到this one。霍夫变换产生了一个有利的结果,但它比以前的情况更重叠,我的方法失败了。

Fairly decent Hough transform of the picture from Google

有人可以建议最好的方法来计算霍夫圈的质心吗?


原始图片:

enter image description here

完整代码:

%%Read and find edges using a filter
i = imread('coins4.jpg');
i = rgb2gray(i);
i = imresize(i,0.125);
i_f = edge(i, 'canny',[0.01 0.45]);
imshow(i_f)

%%

[x y] = find(i_f>0); % Finds where the edges are and stores the x and y coordinates
edge_index = size(x);
radius = 30; %Fixed radius value
theta = 0:0.01:2*pi;
accum = zeros(size(i,1), size(i,2)); %Create an accumulator matrix.

r_co = radius*cos(theta);
r_si = radius*sin(theta);

x1 = repmat(x, 1, length(r_co));
y1 = repmat(y, 1, length(r_si));
x_r_co = repmat(r_co, length(x),1);
y_r_si = repmat(r_si, length(y),1);

%% Filling the accumulator
a = x1 - x_r_co;
b = y1 - y_r_si;

for cnt = 1:numel(a)
    a_cnt = round(a(cnt));
    b_cnt = round(b(cnt));
    if(a_cnt>0 && b_cnt>0 && a_cnt<=size(accum,1) && b_cnt<=size(accum,2))
        accum(a_cnt,b_cnt) = accum(a_cnt,b_cnt) + 1;
    end
end

imshow(accum,[0 max(max(accum))]);

 %% Thresholding and get the center of the circle.
close all;
temp = accum;
temp(find(temp<40))=0;
imshow(temp,[0 max(temp(:))])
temp = imdilate(temp, ones(6,6));
imshow(temp,[0 max(max(temp))]);
temp = imerode(temp,ones(3,3));
imshow(temp,[0 max(max(temp))]);
s = regionprops(im2bw(temp),'centroid');
centroids = cat(1, s.Centroid);
imshow(i);
hold on;
plot(centroids(:,1), centroids(:,2),'*b')

2 个答案:

答案 0 :(得分:2)

如果你想坚持你现在拥有的2D图像,这是一个简单的算法,可能适用于你的第一张图像,因为所有的硬币都大小相同,并且它不会太混乱:

  1. 使用[~,max_idx] = max(accum(:)); [i,j] = ind2sub(size(accum), max_idx];
  2. 查找累加器数组的全局最大值
  3. 在这个像素周围拍摄一个小邻域(也许是一个半径为10像素的正方形)并计算其质心并得到它的指数(这基本上找到了你看到的亮环的中间)
  4. 将质心像素索引添加到圆心中心列表
  5. 将小邻域中的所有像素设置为零(以防止对同一像素中心进行双重检测)
  6. 从步骤1开始重复,直至达到原始全局最大值
  7. 的约70%左右

    如果这不起作用,我建议采用3D累加器方法,这对于可变大小的硬币来说要好得多。

    你得到的原因&#34;甜甜圈&#34;一些硬币的形状而不是中心强烈亮点的圆形是因为你假设的半径有点偏差。如果你要探索累加器的第三维(半径尺寸),你会发现这些&#34;甜甜圈&#34;逐渐变细到一个点,然后你可以将其检测为局部最大值。

    这需要更多的时间和记忆,但它会产生最准确的结果,并且不是代码大调整。你可以使用类似于我上面提到的方法检测最大值,但是在3D中并且没有步骤2中的质心技巧。

答案 1 :(得分:0)

因此,matlab中有一个函数可以完全满足您的需求,称为imfindcircles。您给出图像和一系列可能的半径,它输出计算的半径和圆的中心。其他一些参数允许调整计算(根据我的经验,使用它们是获得良好结果的必要条件)。

现在,如果你想自己找到中心和半径(不使用matlab),那么你想在累积矩阵上使用最大值查找器。 Hough变换的概念是,你在积累矩阵上找到的最大值每个都对应一个圆(通常在(radius,x_center,y_center)中进行参数化。这里的难点在于你有一个巨大的搜索空间和许多很多的最大值这不是&#34;真实的&#34;圈子,但是人工制品。我不知道如何可靠地区分真实的这些虚假圈子 - 我希望它是一个相当复杂的检查。

希望这有帮助!