1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
.. _hough_circle:
Hough Circle Transform
***********************
Goal
=====
In this tutorial you will learn how to:
* Use the OpenCV function :hough_circles:`HoughCircles <>` to detect circles in an image.
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 :math:`(r, \theta)`. In the circle case, we need three parameters to define a circle:
.. math::
C : ( x_{center}, y_{center}, r )
where :math:`(x_{center}, y_{center})` define the center position (gree point) and :math:`r` is the radius, which allows us to completely define a circle, as it can be seen below:
.. image:: images/Hough_Circle_Tutorial_Theory_0.jpg
:alt: Result of detecting circles with Hough Transform
:align: center
* For sake of efficiency, OpenCV implements a detection method slightly trickier than the standard Hough Transform: *The Hough gradient method*. For more details, please check the book *Learning OpenCV* or your favorite Computer Vision bibliography
Code
======
#. **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.
.. |TutorialHoughCirclesSimpleDownload| replace:: here
.. _TutorialHoughCirclesSimpleDownload: https://github.com/Itseez/opencv/tree/master/samples/cpp/houghcircles.cpp
.. |TutorialHoughCirclesFancyDownload| replace:: here
.. _TutorialHoughCirclesFancyDownload: https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/HoughCircle_Demo.cpp
#. The sample code that we will explain can be downloaded from |TutorialHoughCirclesSimpleDownload|_. A slightly fancier version (which shows both Hough standard and probabilistic with trackbars for changing the threshold values) can be found |TutorialHoughCirclesFancyDownload|_.
.. code-block:: cpp
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace cv;
/** @function main */
int main(int argc, char** argv)
{
Mat src, src_gray;
/// Read the image
src = imread( argv[1], 1 );
if( !src.data )
{ return -1; }
/// Convert it to gray
cvtColor( src, src_gray, CV_BGR2GRAY );
/// Reduce the noise so we avoid false circle detection
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
vector<Vec3f> circles;
/// Apply the Hough Transform to find the circles
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
/// Draw the circles detected
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]);
// circle center
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
// circle outline
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
/// Show your results
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
imshow( "Hough Circle Transform Demo", src );
waitKey(0);
return 0;
}
Explanation
============
#. Load an image
.. code-block:: cpp
src = imread( argv[1], 1 );
if( !src.data )
{ return -1; }
#. Convert it to grayscale:
.. code-block:: cpp
cvtColor( src, src_gray, CV_BGR2GRAY );
#. Apply a Gaussian blur to reduce noise and avoid false circle detection:
.. code-block:: cpp
GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
#. Proceed to apply Hough Circle Transform:
.. code-block:: cpp
vector<Vec3f> circles;
HoughCircles( src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows/8, 200, 100, 0, 0 );
with the arguments:
* *src_gray*: Input image (grayscale)
* *circles*: A vector that stores sets of 3 values: :math:`x_{c}, y_{c}, r` for each detected circle.
* *CV_HOUGH_GRADIENT*: Define the detection method. Currently this is the only one available in OpenCV
* *dp = 1*: The inverse ratio of resolution
* *min_dist = src_gray.rows/8*: 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
#. Draw the detected circles:
.. code-block:: cpp
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]);
// circle center
circle( src, center, 3, Scalar(0,255,0), -1, 8, 0 );
// circle outline
circle( src, center, radius, Scalar(0,0,255), 3, 8, 0 );
}
You can see that we will draw the circle(s) on red and the center(s) with a small green dot
#. Display the detected circle(s):
.. code-block:: cpp
namedWindow( "Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE );
imshow( "Hough Circle Transform Demo", src );
#. Wait for the user to exit the program
.. code-block:: cpp
waitKey(0);
Result
=======
The result of running the code above with a test image is shown below:
.. image:: images/Hough_Circle_Tutorial_Result.jpg
:alt: Result of detecting circles with Hough Transform
:align: center
|