Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

To quickly detect circles with very large diameter variation, you can use the radial symmetry transform (as they are radially symmetric) (Loy&Zelinsky 2002). It's not in OpenCV, but it's easy to implement.

The algorithm is the following:

  • define an accumulator image (same size as the original)
  • detect the gradients in the image (magnitude/angle).
  • For every point where the gradient magnitude is over a certain threshold, draw a line in the gradient direction in the accumulator image (in fact, as it's an accumulator, you have to increment by 1 the value of the pixels along the line).
  • Detect the local maxima in the accumulator image. They will indicate the center of the coins.

To quickly detect circles with very large diameter variation, you can use the radial symmetry transform (as they are radially symmetric) (Loy&Zelinsky 2002). It's not in OpenCV, but it's easy to implement.

The algorithm is the following:

  • define an accumulator image (same size as the original)
  • detect the gradients in the image (magnitude/angle).
  • For every point where the gradient magnitude is over a certain threshold, draw a line in the gradient direction in the accumulator image (in fact, as it's an accumulator, you have to increment by 1 the value of the pixels along the line).line). The length of the line should be equal to the maximum radius you want to detect.
  • Detect the local maxima in the accumulator image. They will indicate the center of the coins.

To quickly detect circles with very large diameter variation, you can use the radial symmetry transform (as they are radially symmetric) (Loy&Zelinsky 2002). It's not in OpenCV, but it's easy to implement.

The algorithm is the following:

  • define an accumulator image (same size as the original)
  • detect the gradients in the image (magnitude/angle).
  • For every point where the gradient magnitude is over a certain threshold, draw a line in the gradient direction in the accumulator image (in fact, as it's an accumulator, you have to increment by 1 the value of the pixels along the line). The length of the line should be equal to the maximum radius you want to detect.
  • Detect the local maxima in the accumulator image. They will indicate the center of the coins.

Here is the result of the radial symmetry transform (the accumulator space) for the image above and a detection length of 60 pixels. The center of all the coins is clearly visible, for any radius.

image description

To quickly detect circles with very large diameter variation, you can use the radial symmetry transform (as they are radially symmetric) (Loy&Zelinsky 2002). It's not in OpenCV, but it's easy to implement.

The algorithm is the following:

  • define an accumulator image (same size as the original)
  • detect the gradients in the image (magnitude/angle).
  • For every point where the gradient magnitude is over a certain threshold, draw a line in the gradient direction in the accumulator image (in fact, as it's an accumulator, you have to increment by 1 the value of the pixels along the line). The length of the line should be equal to the maximum radius you want to detect.
  • Detect the local maxima in the accumulator image. They will indicate the center of the coins.

Here is the result of the radial symmetry transform (the accumulator space) for the image above and a detection length of 60 pixels. The center of all the coins is clearly visible, for any radius.

image description

To quickly detect circles with very large diameter variation, you can use the radial symmetry transform (as they are radially symmetric) (Loy&Zelinsky 2002). This is a very robust and proven algorithm for circular object detection for any radius. It's not in part of OpenCV, but it's easy to implement.

The algorithm is the following:

  • define an accumulator image (same size as the original)
  • detect the gradients in the image (magnitude/angle).
  • For every point where the gradient magnitude is over a certain threshold, draw a line in the gradient direction in the accumulator image (in fact, as it's an accumulator, you have to increment by 1 the value of the pixels along the line). The length of the line should be equal to the maximum radius you want to detect.
  • Detect the local maxima in the accumulator image. They will indicate the center of the coins.

Here is the result of the radial symmetry transform (the accumulator space) for the image above and a detection length of 60 pixels. The center of all the coins is clearly visible, for any radius.

image description

To quickly detect circles with very large diameter variation, you can use the radial symmetry transform (as they are radially symmetric) (Loy&Zelinsky 2002). This is a very robust and proven algorithm for circular object detection for any radius. It's not part of OpenCV, but it's easy to implement.

The algorithm is the following:

  • define an accumulator image (same size as the original)
  • detect the gradients in the image (magnitude/angle).
  • For every point where the gradient magnitude is over a certain threshold, draw a line in the gradient direction in the accumulator image (in fact, as it's an accumulator, you have to increment by 1 the value of the pixels along the line). The length of the line should be equal to the maximum radius you want to detect.
  • Detect the local maxima in the accumulator image. They will indicate the center of the coins.

Here is the result of the radial symmetry transform (the accumulator space) for the image above and a detection length of 60 pixels. The center of all the coins is clearly visible, for any radius.

image description

Here is the C++ code for the proposed algorithm. It takes the X and Y gradients and the detection radius (ray). minval and maxval are low and high thresholds for the gradient.

void RadSymTransform(InputArray gradx,InputArray grady,OutputArray result,int ray,double minval=0,double maxval=255)
{
Mat gxMat=gradx.getMat();
Mat gyMat=grady.getMat();
result.create(gradx.size(), CV_16UC1);
Mat resMat=result.getMat();
resMat=Mat::zeros(resMat.size(), resMat.type());
int x,y,i,H,W;
double tx,ty,gx,gy,ampl,max;
H=gxMat.rows;W=gxMat.cols;
for(y=0;y<H;y++)
    for (x = 0; x < W; x++)
    {
        gx=gxMat.at<double>(y,x);
        gy=gyMat.at<double>(y,x);
        ampl=sqrt(gx*gx+gy*gy);
        if((ampl>minval)&&(ampl<maxval)){
            max=(abs(gx)>abs(gy)?abs(gx):abs(gy));
            gx/=max;gy/=max;
            tx=x-ray*gx;ty=y-ray*gy;
            if(tx<0||tx>W||ty<0||ty>H)continue;
            tx=x;ty=y;
            for (i = 0; i < ray; ++i)
            {
                tx-=gx;ty-=gy;
                resMat.at<ushort>((int)ty,(int)tx)++;
            }
        }
    }
}