3

Question

  • What formula would allow me to predict the center of this circle?
  • In addition, what attributes of this image must be detected in order to predict the center? I figured understanding the math first will help me determine what parts of the image are relevant, then I can worry about trying to detect those features.

Background

I need to programmatically find the center of a circle while I'm only able to see the outer edge of the circle. I am using matlab for my prototype of this.

This was a class project. We finished the project using matlabs imfindcircles(), but it is to slow. It takes about 2-3 seconds to process a single image. I want to improve my programs speed and hopefully learn some math in the process. The initial assignment was to create a rifle that blind people could use.

Below is a test image I am trying to process:

Ignore the black around the outer edge. I have my camera behind a scope, that is why you can only see a small magnified circle in the middle. The black half circles are actually a target, so there are multiple rings nested inside each other.

Image to process

Also, I initially posted this question on stackoverflow as a programming issue. Feel free to read it for more information about the code behind my imfindcircles() solution and my attempted alternative. However, there are quite a few votes to close it. I'm guessing that is because it is really more of a math problem than a programming problem.

My Solution

I have written a short tutorial about how I solved the problem and posted all my code to github. See the tutorial and code. The tutorial was written in the projects README.md file so it should appear when you view the github page and scroll down a bit. I used the math @vadim123 suggested.

zechdc
  • 133
  • 1
    Note that a circumcircle surrounding a triangle is unique... Maybe picking three points on the circle's edge which define a triangle would help? – abiessu Nov 20 '13 at 16:32

5 Answers5

5

The hard part is finding three points on the circle using the messy data you're given. Assuming you have done this, $A,B,C$, in that order, then:

  1. Let $L_1$ be the line that passes through the midpoint of segment $AB$, and is perpendicular to $AB$.

  2. Let $L_2$ be the line that passes through the midpoint of segment $BC$, and is perpendicular to $BC$.

Then the intersection of $L_1$ and $L_2$ is the center of the circle.

If $A,B,C$ are far away that will make the error smaller. Hence I advocate doing this process several times for different choices of $A,B,C$, to get several "centers" and averaging.

vadim123
  • 82,796
2

My suggestion

  1. Find edge points (i.e. where a small neighbourhood contains dark and light pixels; or that differ maximally from a Gauss-blurred version of the image; or whatever you prefer)

  2. Repeatedly pick random triplets from these edge points and calulate the circumcenter of the triangle formed by them

  3. Look for clusters among these circumcenters.

It may be a good idea to weigh the circumcenters, e.g. give less weight to cases where two of the vertices are close

1

If the portion shown is large enough try http://www.murderousmaths.co.uk/books/ccent.htm

Mick
  • 17,141
1

This is an excellent chance to use the least squared estimation technique you learned in your linear algebra course.

Estimates derived from a small number of points will be unreliable -- especially when you start drawing lines between two or three points. You want to use as many boundary points as possible to get an accurate and robust estimate. A good, quick, and easy method is to 1) blur the image to smooth out the boundary of the disk, 2) threshold the smoothed image to determine which pixels belong to the disk, 3) detect the disk's boundary, 4) perform a least squared error estimate of the circle's parameters.

The equation for your circle is

$$ r^2 = (m_i-m_0)^2 + (n_i-n_0)^2, $$

where $r$ is the radius of the circle, $m_0$ the center row, $n_0$ the center column, $m_i$ the rows of the detected boundary, and $n_i$ the columns of the boundary. We want to separate the unknowns ($r$, $m_0$, and $n_0$) and the knowns ($m_i$ and $n_i$) as much as we can. We also want to express the problem as dot product of two vectors:

$$ \left[ \begin{array}{ccc} 1 & -2m_i & -2n_i \end{array} \right] \left[ \begin{array}{c} m_0^2 + n_0^2 -r^2 \\ m_0 \\ n_0 \end{array} \right] = -m_i^2 - n_i^2 $$

Since we have values for $m_i$ and $n_i$ for each detected boundary point, the above becomes an over-determined matrix problem: $\mathbf{Ax}=\mathbf{b}$. We create $\mathbf{A}$ where the $i^{\mathrm{th}}$ row is equal to $[1 -2m_i -2n_i]$, and likewise $\mathbf{b}$ where the $i^\mathrm{th}$ row is $-m_i^2 - n_i^2$. The LSE solution will give us a three-element vector with the estimates for $m_0^2+n_0^2-r^2$, $m_0$, and $n_0$.

In MATLAB my solution looked like this:

x = sum( double( imread( 'circle.jpg' ) ), 3 );
d = imdilate( x, strel('ball',10,10) ) > 100;
b = bwboundaries( d );
bndry = b{1}; % This is easier to read.
Np = size( bndry, 1 );
A = [ ones(Np,1) -2*bndry(:,1) -2*bndry(:,2) ];

% The LSE gives a three element vector. The first
% entry is m_0^2 + n_0^2 - r^2, the second is m_0,
% and the third is n_0.
est = A \ [ -bndry(:,1).^2 - bndry(:,2).^2 ];
radius = sqrt( est(2)^2 + est(3)^2 - est(1) );

The above gives the following estimates:

>> est

est =

      542277.276599492
      373.657555135236
      647.454919217534

>> radius

radius =

      128.610125297867

You can plot the results with:

t = ( 0 : 0.01 : 2*pi )';
circest = repmat( [ est(2) est(3) ], length(t), 1 ) ...
  + radius * [ sin(t) cos(t) ];
imagesc( x )
hold on
plot( circest(:,2), circest(:,1), 'r' );
plot( est(3), est(2), 'rx' );
0

We know that the hypotenuse of a right triangle serves as a diameter for the circumcircle of the right triangle. That is, if we have a circle $O$ with some diameter $\overline{AB}$, then the endpoints $A$ and $B$ could be vertices of a triangle and $C$ could be a point such that $ \triangle ABC $ is right. We know how to construct right triangles, don't we? So, we can construct this diameter and then find the midpoint?

This is all assuming I understand your question ...