OpenCV  3.2.0
Open Source Computer Vision
Hough Circle Transform

.2.0+dfsg_doc_tutorials_imgproc_imgtrans_hough_circle_hough_circle

Goal

In this tutorial you will learn how to:

Theory

Hough Circle Transform

  • The Hough Circle Transform works in a roughly analogous way to the Hough Line Transform explained in the previous tutorial.
  • In the line detection case, a line was defined by two parameters \((r, \theta)\). In the circle case, we need three parameters to define a circle:

    \[C : ( x_{center}, y_{center}, r )\]

    where \((x_{center}, y_{center})\) define the center position (green point) and \(r\) is the radius, which allows us to completely define a circle, as it can be seen below:

  • For sake of efficiency, OpenCV implements a detection method slightly trickier than the standard Hough Transform: The Hough gradient method, which is made up of two main stages. The first stage involves edge detection and finding the possible circle centers and the second stage finds the best radius for each candidate center. For more details, please check the book Learning OpenCV or your favorite Computer Vision bibliography

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 radio 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:

cv::Mat::rows
int rows
the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
Definition: mat.hpp:1959
imgproc.hpp
cv::IMREAD_COLOR
@ IMREAD_COLOR
If set, always convert image to the 3 channel BGR color image.
Definition: imgcodecs.hpp:67
cv::cvtColor
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
Converts an image from one color space to another.
cv::waitKey
int waitKey(int delay=0)
Waits for a pressed key.
cv::Vec3i
Vec< int, 3 > Vec3i
Definition: matx.hpp:376
highgui.hpp
cv::imread
Mat imread(const String &filename, int flags=IMREAD_COLOR)
Loads an image from a file.
cv::COLOR_BGR2GRAY
@ COLOR_BGR2GRAY
convert between RGB/BGR and grayscale, color conversions
Definition: imgproc.hpp:538
cv::HoughCircles
void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0)
Finds circles in a grayscale image using the Hough transform.
cv::Vec
Template class for short numerical vectors, a partial case of Matx.
Definition: matx.hpp:306
cv::medianBlur
void medianBlur(InputArray src, OutputArray dst, int ksize)
Blurs an image using the median filter.
imgcodecs.hpp
cv::LINE_AA
@ LINE_AA
antialiased line
Definition: core.hpp:218
cv::imshow
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
cv::Scalar
Scalar_< double > Scalar
Definition: types.hpp:606
cv::HOUGH_GRADIENT
@ HOUGH_GRADIENT
basically 21HT, described in
Definition: imgproc.hpp:473
cv::Point
Point2i Point
Definition: types.hpp:183
cv::Mat
n-dimensional dense array class
Definition: mat.hpp:741
i
for i
Definition: modelConvert.m:63
cv::CommandLineParser
Designed for command line parsing.
Definition: utility.hpp:735
cv
Definition: affine.hpp:52
cv::datasets::circle
@ circle
Definition: gr_skig.hpp:62
cv::circle
void circle(InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
Draws a circle.