0
votes

I have a large set of images (~2000) that show a grayscale picture of cropped circles. Each image is one circle with clear background. the images are homogeneous and so is the background. The images are almost not noisy. Image size is about 700x700 pixels.

some of the images are cropped, in the sense that a part of them is outside the image boundaries. the circles are about 1/2 size of the image.

enter image description here

I have Matlab, but no image processing toolbox.

I have prior information about the radius of the images. I would appreciate receiving it from the algorithm for validation purposes, but I can use it a-priori.

How do I get the center and radius of the circles?

Thanks!

1
If you don't have the image processing tools, find how to do it as if you had it, and code the functions yourselfAnder Biguri
"Almost not noisy"! Remind me not to buy a camera sensor from you! ;-)Mark Setchell
also "these used underwear were a few times measured".Gabe
I think Cris's approach is much more rigorous, but I get pretty reasonable results by de-noising with a median filter and then doing a two colour quantisation followed by an edge detection. That gets me a bunch of white points on a black background. Then I can take 3 white points at random and find the centre knowing 3 points on the circumference. If you take the 3 points and solve a few times, you can then take the median x,y values as the centre. It takes around 3 lines in Terminal using ImageMagick which is free and on Linux, macOS and Windows.Mark Setchell
@MarkSetchell: That might actually be a better solution. Take the points I found in my answer, but ignore the gradient, and simply fit a circle to the points. I should have thought of that... :)Cris Luengo

1 Answers

2
votes

This is a typical application for the Hough transform, but since you have only one circle, we can do a little bit better.

The code below computes the gradient of the image. You have a lot of noise, but your circle is also very large. I'm using a large sigma for the Gaussian regularization that the gradient operator uses (I like to use convolution with the derivative of the Gaussian to compute derivatives). Next, I find the pixels with the largest gradient magnitude, and set up a system of equations for these points. We note that, for each point i,

origin_x + radius * gradient_x(i) = coordinate_x(i)

origin_y + radius * gradient_y(i) = coordinate_y(i)

(sorry, we don't get to do proper equations on SO). coordinate is the coordinate of the point, and gradient is the normalized gradient at that point, and the _x and _y indicate the corresponding component of the vector. radius can be negative, depending on the direction of the gradient. We can solve this system of linear equations with MATLAB's \ operator.

% Load image (take only first channel, they're all the same)
img = imread('https://i.stack.imgur.com/wAwdh.jpg');
img = dip_image(img(:,:,1));
% Compute gradient
grad = gradient(img,10);
% Find N pixels with largest gradient magnitude
N = 5000;
mask = norm(grad);
mask = setborder(mask,0,50); % Don't use data close to the edge of the image
tmp = sort(double(mask(:)));
mask = mask > tmp(end-N);
index = find(mask);
value = grad(index);
value = value / norm(value);
coords = ind2sub(mask,index); % value(i) at coords(i,:)
% Solve set of linear equations
p = [ones(N,1),zeros(N,1),double(value{1})';zeros(N,1),ones(N,1),double(value{2})'] \ coords(:);
origin = p(1:2)'
radius = p(3)
rmse = sqrt(mean((origin + radius * squeeze(double(value))' - coords).^2))
% Plot some of the lines
img
hold on
for ii=1:25:N
   plot(coords(ii,1)-[0,radius*double(value{1}(ii-1))],coords(ii,2)-[0,radius*double(value{2}(ii-1))],'r-')
end

Output:

origin =
   -2.5667  177.5305

radius =
  322.5899

rmse =
   13.8160   13.0136

result of plot

As you can see, the noise causes a lot of trouble estimating the gradient. But because there is no bias in the estimate at each pixel, the least squares estimate should lead to an accurate value.

The code above uses DIPimage 3, which is an open-source image analysis toolbox for MATLAB (Apache License). You'll have to compile it yourself, because we don't have a pre-compiled release package yet. You can instead download DIPimage 2.9, which has the same functionality, though I might have used some new syntax in the code above, I'm not sure. DIPimage 2.9 is not open source, and is free for use only in non-commercial applications.