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
12using namespace std;
13using namespace cv;
14
15namespace
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
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
54int 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