2

I have an image as below :

Sample image with overlapping circles

Can anyone tell me how to detect the number of circles in it.I'm using Hough circle transform to achieve this and this is my code:

# import the necessary packages
import numpy as np
import sys
import cv2



# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(str(sys.argv[1]))
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# detect circles in the image
circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1.2, 5)

no_of_circles = 0  
# ensure at least some circles were found
if circles is not None:
# convert the (x, y) coordinates and radius of the circles to integers
    circles = np.round(circles[0, :]).astype("int")
    no_of_circles = len(circles)

# loop over the (x, y) coordinates and radius of the circles
    for (x, y, r) in circles:
# draw the circle in the output image, then draw a rectangle
# corresponding to the center of the circle
        cv2.circle(output, (x, y), r, (0, 255, 0), 4)
        cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)

# show the output image

    cv2.imshow("output", np.hstack([image, output]))

print 'no of circles',no_of_circles

I'm getting wrong answers for this code.Can anyone tell me where I went wrong?

5 Answers5

1

i tried a tricky way to detect all circles.

i found HoughCircles parameters manually

HoughCircles( src_gray, circles, HOUGH_GRADIENT, 1, 50, 40, 46, 0, 0 );

the tricky part is

flip( src, flipped, 1 );
hconcat( src,flipped, flipped );
hconcat( flipped, src, src );

flip( src, flipped, 0 );
vconcat( src,flipped, flipped );
vconcat( flipped, src, src );

flip( src, src, -1 );

will create a model like below before detection.

enter image description here

the result is like this

enter image description here

the c++ code can be easily converted to python

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
    Mat src, src_gray, flipped, display;

    if (argc < 2)
    {
        std::cerr<<"No input image specified\n";
        return -1;
    }

    // Read the image
    src = imread( argv[1], 1 );

    if( src.empty() )
    {
        std::cerr<<"Invalid input image\n";
        return -1;
    }

    flip( src, flipped, 1 );
    hconcat( src,flipped, flipped );
    hconcat( flipped, src, src );

    flip( src, flipped, 0 );
    vconcat( src,flipped, flipped );
    vconcat( flipped, src, src );

    flip( src, src, -1 );

    // Convert it to gray
    cvtColor( src, src_gray, COLOR_BGR2GRAY );

    // Reduce the noise so we avoid false circle detection
    GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );

    // will hold the results of the detection
    std::vector<Vec3f> circles;
    // runs the actual detection
    HoughCircles( src_gray, circles, HOUGH_GRADIENT, 1, 50, 40, 46, 0, 0 );

    // clone the colour, input image for displaying purposes
    display = src.clone();
    Rect rect_src(display.cols / 3, display.rows / 3, display.cols / 3, display.rows / 3 );
    rectangle( display, rect_src, Scalar(255,0,0) );
    for( size_t i = 0; i < circles.size(); i++ )
    {
        Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
        int radius = cvRound(circles[i][2]);

        Rect r = Rect( center.x-radius, center.y-radius, radius * 2, radius * 2 );
        Rect intersection_rect = r & rect_src;
        if( intersection_rect.width * intersection_rect.height >  r.width * r.height / 3 )
        {
            // circle center
            circle( display, center, 3, Scalar(0,255,0), -1, 8, 0 );
            // circle outline
            circle( display, center, radius, Scalar(0,0,255), 3, 8, 0 );
        }

    }

    // shows the results
    imshow( "results", display(rect_src));
    // get user key
    waitKey();

    return 0;
}
sturkmen
  • 3,495
  • 4
  • 27
  • 63
  • If you're operating on an image + 8 mirrored images around it, there will be problems unless circles on the border are precisely semicircles. Better to write an algorithm that detects circular arcs. – Rethunk Dec 13 '15 at 06:32
1

This SO post describes detection of semi-circles, and may be a good start for you:

Detect semi-circle in opencv

If you get stuck in OpenCV, try coding up the solution yourself. Writing a Hough circle finder parameterized for your particular application is relatively straightforward. If you write application-specific Hough algorithms a few times, you should be able to write a reasonable solution in less time than it takes to sort through a bunch of google results, decipher someone else's code, and so on.

You definitely don't need Canny edge detection for an image like this, but it won't hurt.

Other libraries (esp. commercial ones) will allow you to set more parameters for Hough circle finding. I would've expected some overload of the HoughCircle function to allow a struct of search parameters to be passed in, including the minimum percentage of circle completeness (arc length) allowed.

Although it's good to learn both RANSAC and Hough techniques--and, over time, more exotic techniques--I wouldn't necessarily recommend using RANSAC when you have circles defined so nicely and crisply. Without offering specific evidence, I'll just claim that fiddling with RANSAC parameters may be less intuitive than fiddling with Hough parameters.

Community
  • 1
  • 1
Rethunk
  • 3,976
  • 18
  • 32
0

HoughCircles needs some parameter tuning to work properly. It could be that in your case the default values of Param1 and Param2 (set to 100) are not good.

MarcoM
  • 1,093
  • 9
  • 25
0

You can fine tune your detection with HoughCircle, by computing the ultimate eroded. It will give you the number of circles in your image.

FiReTiTi
  • 5,597
  • 12
  • 30
  • 58
  • Can you please elaborate on this ? How do I fine tune the parameters ? – Kaushik Ramachandran Dec 12 '15 at 06:27
  • The number of centers after the ultimate eroded will give you the number (let's say N) of circles you have to find into your image. Then, you can start the HoughCircle with sensitive parameters in order to capture a higher number of circles. At the end, you keep the N most likely circles. – FiReTiTi Dec 12 '15 at 06:46
0

If there are only circles and background on the input you can count the number of connected components and ignore the component associated with background. This will be the simplest and most robust solution

alexisrozhkov
  • 1,623
  • 12
  • 18
  • Connected components wouldn't work well if you had two touching circles of the same color. A Hough algorithm would identify both touching circles. – Rethunk Dec 13 '15 at 05:29
  • I have explicitly asked if the touching circles are always of different color and the OP haven't answered, that's why I suggested a simpler solution. If there really are same colored overlapping circles you can check every connected component for number of convexity defects. – alexisrozhkov Dec 13 '15 at 11:24
  • I see your point, and would agree with the desire for simplicity, but assuming that at least some requirements haven't been stated (as is common), I think it's preferable to offer a solution that finds circles as circles. – Rethunk Dec 13 '15 at 13:54
  • 1
    Can't argue with that :) – alexisrozhkov Dec 13 '15 at 14:04