MATLAB中的灰度图像圆检测

3
我有以下图片。我的目标是检测第二张图片中的圆。我使用了[centers,radii] = imfindcircles(IM,[100 300]);,但没有找到任何内容。
是否有其他方法可以检测圆?我该怎么做?
原始图像: enter image description here 圆形:我用画图工具画的。 enter image description here

如果你对它进行阈值处理会发生什么? - kkuilla
显然,您需要调整 imfindcircles 的参数。尝试将 'ObjectPolarity' 设置为 'bright',将 'EdgeThreshold' 设置为非常低的值,并调整 'Sensitivity' - Shai
2个回答

6

这里提供一种替代imfindcircles的解决方案。基本上,对图像进行阈值处理,使用圆盘形结构元素膨胀,然后在找到边缘后,应用Hough变换来检测圆形,可以使用此处提供的circle_hough算法。

以下是代码:

clear
clc
close all

A = imread('CircleIm.jpg');

%// Some pre-processing. Treshold image and dilate it.
B = im2bw(A,.85);

se = strel('disk',2);

C = imdilate(B,se);

D = bwareaopen(C,10000);

%// Here imfill is not necessary but you might find it useful in other situations.
E = imfill(D,'holes');

%// Detect edges
F = edge(E);

%// circle_hough from the File Exchange.

%// This code is based on Andrey's answer here:
%https://dsp.stackexchange.com/questions/5930/find-circle-in-noisy-data.

%// Generate range of radii.
 radii = 200:10:250;

h = circle_hough(F, radii,'same');
[~,maxIndex] = max(h(:));
[i,j,k] = ind2sub(size(h), maxIndex);
radius = radii(k);
center.x = j;
center.y = i;

%// Generate circle to overlay
N = 200;

theta=linspace(0,2*pi,N);
rho=ones(1,N)*radius;

%Cartesian coordinates
[X,Y] = pol2cart(theta,rho); 

figure;

subplot(2,2,1)
imshow(B);
title('Thresholded image  (B)','FontSize',16)

subplot(2,2,2)
imshow(E);
title('Filled image (E)','FontSize',16)

subplot(2,2,3)
imshow(F);hold on

plot(center.x-X,center.y-Y,'r-','linewidth',2);

title('Edge image + circle (F)','FontSize',16)

subplot(2,2,4)
imshow(A);hold on
plot(center.x-X,center.y-Y,'r-','linewidth',2);
title('Original image + circle (A)','FontSize',16)

以下是给出的结果:

输入图像

您也可以尝试调整传递给threshold或dilate的参数,以查看它对结果的影响。

希望能对您有所帮助!


2
这里有另一种解决这个问题的方法,与 imfindcircles 和之前的答案不同,它不是基于霍夫变换的。主要步骤如下:
  1. 对图像进行分割(使用 Otsu 方法估计阈值)
  2. 查找连通组件并保留其中只有 2% 的组件,从面积较大的组件开始保留
  3. 使用小半径圆(或圆盘)对图像进行膨胀
  4. 再次查找连通组件,并将具有最大面积的组件确定为圆形
霍夫变换有时会很慢,这取决于输入数据大小和分辨率。比较两种方法(使用/不使用霍夫变换)的执行时间可能很有用。
该方法还可以检测其他形状(非圆形)的对象。
function[circle] = ipl_find_circle(I)

% NOTE: I is assumed to be a grayscale image

% Step 1: Segment image using Otsu´s method
t = graythresh(I); 
BW = im2bw(I, t); 

% Step 2: Leave just "big" components on binary image
[L, num] = bwlabel(BW); 
stats = regionprops(L, 'Area', 'PixelIdxList');
area_vector = [stats(:).Area];
area_vector = sort(area_vector);
threshold_pos = floor(num * 0.98);
threshold = area_vector(threshold_pos);

for i=1:num
    if(stats(i).Area < threshold)
        BW(stats(i).PixelIdxList) = false;
    end
end

% Step 3: Dilate image with a circle of small radius
str = strel('disk', 5); 
BW = imdilate(BW, str); 

% Step 4: Take component with biggest area as the circle
L = bwlabel(BW); 
stats = regionprops(L, 'Area', 'BoundingBox', 'Centroid', 'EquivDiameter');
area_vector = [stats(:).Area];
[max_value, max_idx] = max(area_vector);
soi = stats(max_idx);

% Set output variable
circle = imcrop(I, soi.BoundingBox);

% Display results
radius = soi.EquivDiameter/2;
N = 1000;
theta = linspace(0, 2*pi, N);
rho = ones(1, N) * radius;
[X,Y] = pol2cart(theta, rho);
X = soi.Centroid(1) - X;
Y = soi.Centroid(2) - Y;

figure; 
subplot(1,2,1);
imshow(I);
hold on;
plot(X, Y, '-r', 'LineWidth', 2);
title('Original graycale image + circle', 'FontSize', 12)

subplot(1,2,2);
imshow(circle);
title('Circle region', 'FontSize', 12);

end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接