OpenCV  3.3.0
Open Source Computer Vision
Hough Circle Transform

Goal

In this tutorial you will learn how to:

Theory

Hough Circle Transform

Code

  1. What does this program do?
    • Loads an image and blur it to reduce the noise
    • Applies the Hough Circle Transform to the blurred image .
    • Display the detected circle in a window.
  2. The sample code that we will explain can be downloaded from here. A slightly fancier version (which shows trackbars for changing the threshold values) can be found here.
    #include <iostream>
    using namespace cv;
    using namespace std;
    static void help()
    {
    cout << "\nThis program demonstrates circle finding with the Hough transform.\n"
    "Usage:\n"
    "./houghcircles <image_name>, Default is ../data/board.jpg\n" << endl;
    }
    int main(int argc, char** argv)
    {
    cv::CommandLineParser parser(argc, argv,
    "{help h ||}{@image|../data/board.jpg|}"
    );
    if (parser.has("help"))
    {
    help();
    return 0;
    }
    string filename = parser.get<string>("@image");
    Mat img = imread(filename, IMREAD_COLOR);
    if(img.empty())
    {
    help();
    cout << "can not open " << filename << endl;
    return -1;
    }
    Mat gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);
    medianBlur(gray, gray, 5);
    vector<Vec3f> circles;
    HoughCircles(gray, circles, HOUGH_GRADIENT, 1,
    gray.rows/16, // change this value to detect circles with different distances to each other
    100, 30, 1, 30 // change the last two parameters
    // (min_radius & max_radius) to detect larger circles
    );
    for( size_t i = 0; i < circles.size(); i++ )
    {
    Vec3i c = circles[i];
    circle( img, Point(c[0], c[1]), c[2], Scalar(0,0,255), 3, LINE_AA);
    circle( img, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, LINE_AA);
    }
    imshow("detected circles", img);
    return 0;
    }

Explanation

  1. Load an image
    string filename = parser.get<string>("@image");
    Mat img = imread(filename, IMREAD_COLOR);
    if(img.empty())
    {
    help();
    cout << "can not open " << filename << endl;
    return -1;
    }
  2. Convert it to grayscale:
    Mat gray;
    cvtColor(img, gray, COLOR_BGR2GRAY);
  3. Apply a Median blur to reduce noise and avoid false circle detection:
    medianBlur(gray, gray, 5);
  4. Proceed to apply Hough Circle Transform:
    vector<Vec3f> circles;
    HoughCircles(gray, circles, HOUGH_GRADIENT, 1,
    gray.rows/16, // change this value to detect circles with different distances to each other
    100, 30, 1, 30 // change the last two parameters
    // (min_radius & max_radius) to detect larger circles
    );
    with the arguments:
    • gray: Input image (grayscale).
    • circles: A vector that stores sets of 3 values: \(x_{c}, y_{c}, r\) for each detected circle.
    • HOUGH_GRADIENT: Define the detection method. Currently this is the only one available in OpenCV.
    • dp = 1: The inverse ratio of resolution.
    • min_dist = gray.rows/16: Minimum distance between detected centers.
    • param_1 = 200: Upper threshold for the internal Canny edge detector.
    • param_2 = 100*: Threshold for center detection.
    • min_radius = 0: Minimum radius to be detected. If unknown, put zero as default.
    • max_radius = 0: Maximum radius to be detected. If unknown, put zero as default.
  5. Draw the detected circles:
    for( size_t i = 0; i < circles.size(); i++ )
    {
    Vec3i c = circles[i];
    circle( img, Point(c[0], c[1]), c[2], Scalar(0,0,255), 3, LINE_AA);
    circle( img, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, LINE_AA);
    }
    You can see that we will draw the circle(s) on red and the center(s) with a small green dot
  6. Display the detected circle(s) and wait for the user to exit the program:
    imshow("detected circles", img);

    Result

The result of running the code above with a test image is shown below:

Hough_Circle_Tutorial_Result.jpg