1 /**
2  * @file HoughCircle_Demo.cpp
3  * @brief Demo code for Hough Transform
4  * @author OpenCV team
5  */
6 
7 #include "opencv2/imgcodecs.hpp"
8 #include "opencv2/highgui/highgui.hpp"
9 #include "opencv2/imgproc/imgproc.hpp"
10 #include <iostream>
11 
12 using namespace std;
13 using namespace cv;
14 
15 namespace
16 {
17     // windows and trackbars name
18     const std::string windowName = "Hough Circle Detection Demo";
19     const std::string cannyThresholdTrackbarName = "Canny threshold";
20     const std::string accumulatorThresholdTrackbarName = "Accumulator Threshold";
21     const std::string usage = "Usage : tutorial_HoughCircle_Demo <path_to_input_image>\n";
22 
23     // initial and max values of the parameters of interests.
24     const int cannyThresholdInitialValue = 200;
25     const int accumulatorThresholdInitialValue = 50;
26     const int maxAccumulatorThreshold = 200;
27     const int maxCannyThreshold = 255;
28 
HoughDetection(const Mat & src_gray,const Mat & src_display,int cannyThreshold,int accumulatorThreshold)29     void HoughDetection(const Mat& src_gray, const Mat& src_display, int cannyThreshold, int accumulatorThreshold)
30     {
31         // will hold the results of the detection
32         std::vector<Vec3f> circles;
33         // runs the actual detection
34         HoughCircles( src_gray, circles, HOUGH_GRADIENT, 1, src_gray.rows/8, cannyThreshold, accumulatorThreshold, 0, 0 );
35 
36         // clone the colour, input image for displaying purposes
37         Mat display = src_display.clone();
38         for( size_t i = 0; i < circles.size(); i++ )
39         {
40             Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
41             int radius = cvRound(circles[i][2]);
42             // circle center
43             circle( display, center, 3, Scalar(0,255,0), -1, 8, 0 );
44             // circle outline
45             circle( display, center, radius, Scalar(0,0,255), 3, 8, 0 );
46         }
47 
48         // shows the results
49         imshow( windowName, display);
50     }
51 }
52 
53 
main(int argc,char ** argv)54 int main(int argc, char** argv)
55 {
56     Mat src, src_gray;
57 
58     if (argc < 2)
59     {
60         std::cerr<<"No input image specified\n";
61         std::cout<<usage;
62         return -1;
63     }
64 
65     // Read the image
66     src = imread( argv[1], 1 );
67 
68     if( src.empty() )
69     {
70         std::cerr<<"Invalid input image\n";
71         std::cout<<usage;
72         return -1;
73     }
74 
75     // Convert it to gray
76     cvtColor( src, src_gray, COLOR_BGR2GRAY );
77 
78     // Reduce the noise so we avoid false circle detection
79     GaussianBlur( src_gray, src_gray, Size(9, 9), 2, 2 );
80 
81     //declare and initialize both parameters that are subjects to change
82     int cannyThreshold = cannyThresholdInitialValue;
83     int accumulatorThreshold = accumulatorThresholdInitialValue;
84 
85     // create the main window, and attach the trackbars
86     namedWindow( windowName, WINDOW_AUTOSIZE );
87     createTrackbar(cannyThresholdTrackbarName, windowName, &cannyThreshold,maxCannyThreshold);
88     createTrackbar(accumulatorThresholdTrackbarName, windowName, &accumulatorThreshold, maxAccumulatorThreshold);
89 
90     // infinite loop to display
91     // and refresh the content of the output image
92     // until the user presses q or Q
93     int key = 0;
94     while(key != 'q' && key != 'Q')
95     {
96         // those paramaters cannot be =0
97         // so we must check here
98         cannyThreshold = std::max(cannyThreshold, 1);
99         accumulatorThreshold = std::max(accumulatorThreshold, 1);
100 
101         //runs the detection, and update the display
102         HoughDetection(src_gray, src, cannyThreshold, accumulatorThreshold);
103 
104         // get user key
105         key = waitKey(10);
106     }
107 
108     return 0;
109 }
110