1 #include <vector>
2 #include <iostream>
3 #include <string>
4 
5 #include "opencv2/core.hpp"
6 #include "opencv2/core/utility.hpp"
7 #include "opencv2/imgproc.hpp"
8 #include "opencv2/cudaimgproc.hpp"
9 #include "opencv2/highgui.hpp"
10 
11 using namespace std;
12 using namespace cv;
13 
loadImage(const string & name)14 static Mat loadImage(const string& name)
15 {
16     Mat image = imread(name, IMREAD_GRAYSCALE);
17     if (image.empty())
18     {
19         cerr << "Can't load image - " << name << endl;
20         exit(-1);
21     }
22     return image;
23 }
24 
main(int argc,const char * argv[])25 int main(int argc, const char* argv[])
26 {
27     CommandLineParser cmd(argc, argv,
28         "{ image i        | ../data/pic1.png  | input image }"
29         "{ template t     | templ.png | template image }"
30         "{ full           |           | estimate scale and rotation }"
31         "{ gpu            |           | use gpu version }"
32         "{ minDist        | 100       | minimum distance between the centers of the detected objects }"
33         "{ levels         | 360       | R-Table levels }"
34         "{ votesThreshold | 30        | the accumulator threshold for the template centers at the detection stage. The smaller it is, the more false positions may be detected }"
35         "{ angleThresh    | 10000     | angle votes threshold }"
36         "{ scaleThresh    | 1000      | scale votes threshold }"
37         "{ posThresh      | 100       | position votes threshold }"
38         "{ dp             | 2         | inverse ratio of the accumulator resolution to the image resolution }"
39         "{ minScale       | 0.5       | minimal scale to detect }"
40         "{ maxScale       | 2         | maximal scale to detect }"
41         "{ scaleStep      | 0.05      | scale step }"
42         "{ minAngle       | 0         | minimal rotation angle to detect in degrees }"
43         "{ maxAngle       | 360       | maximal rotation angle to detect in degrees }"
44         "{ angleStep      | 1         | angle step in degrees }"
45         "{ maxBufSize     | 1000      | maximal size of inner buffers }"
46         "{ help h ?       |           | print help message }"
47     );
48 
49     cmd.about("This program demonstrates arbitrary object finding with the Generalized Hough transform.");
50 
51     if (cmd.has("help"))
52     {
53         cmd.printMessage();
54         return 0;
55     }
56 
57     const string templName = cmd.get<string>("template");
58     const string imageName = cmd.get<string>("image");
59     const bool full = cmd.has("full");
60     const bool useGpu = cmd.has("gpu");
61     const double minDist = cmd.get<double>("minDist");
62     const int levels = cmd.get<int>("levels");
63     const int votesThreshold = cmd.get<int>("votesThreshold");
64     const int angleThresh = cmd.get<int>("angleThresh");
65     const int scaleThresh = cmd.get<int>("scaleThresh");
66     const int posThresh = cmd.get<int>("posThresh");
67     const double dp = cmd.get<double>("dp");
68     const double minScale = cmd.get<double>("minScale");
69     const double maxScale = cmd.get<double>("maxScale");
70     const double scaleStep = cmd.get<double>("scaleStep");
71     const double minAngle = cmd.get<double>("minAngle");
72     const double maxAngle = cmd.get<double>("maxAngle");
73     const double angleStep = cmd.get<double>("angleStep");
74     const int maxBufSize = cmd.get<int>("maxBufSize");
75 
76     if (!cmd.check())
77     {
78         cmd.printErrors();
79         return -1;
80     }
81 
82     Mat templ = loadImage(templName);
83     Mat image = loadImage(imageName);
84 
85     Ptr<GeneralizedHough> alg;
86 
87     if (!full)
88     {
89         Ptr<GeneralizedHoughBallard> ballard = useGpu ? cuda::createGeneralizedHoughBallard() : createGeneralizedHoughBallard();
90 
91         ballard->setMinDist(minDist);
92         ballard->setLevels(levels);
93         ballard->setDp(dp);
94         ballard->setMaxBufferSize(maxBufSize);
95         ballard->setVotesThreshold(votesThreshold);
96 
97         alg = ballard;
98     }
99     else
100     {
101         Ptr<GeneralizedHoughGuil> guil = useGpu ? cuda::createGeneralizedHoughGuil() : createGeneralizedHoughGuil();
102 
103         guil->setMinDist(minDist);
104         guil->setLevels(levels);
105         guil->setDp(dp);
106         guil->setMaxBufferSize(maxBufSize);
107 
108         guil->setMinAngle(minAngle);
109         guil->setMaxAngle(maxAngle);
110         guil->setAngleStep(angleStep);
111         guil->setAngleThresh(angleThresh);
112 
113         guil->setMinScale(minScale);
114         guil->setMaxScale(maxScale);
115         guil->setScaleStep(scaleStep);
116         guil->setScaleThresh(scaleThresh);
117 
118         guil->setPosThresh(posThresh);
119 
120         alg = guil;
121     }
122 
123     vector<Vec4f> position;
124     TickMeter tm;
125 
126     if (useGpu)
127     {
128         cuda::GpuMat d_templ(templ);
129         cuda::GpuMat d_image(image);
130         cuda::GpuMat d_position;
131 
132         alg->setTemplate(d_templ);
133 
134         tm.start();
135 
136         alg->detect(d_image, d_position);
137         d_position.download(position);
138 
139         tm.stop();
140     }
141     else
142     {
143         alg->setTemplate(templ);
144 
145         tm.start();
146 
147         alg->detect(image, position);
148 
149         tm.stop();
150     }
151 
152     cout << "Found : " << position.size() << " objects" << endl;
153     cout << "Detection time : " << tm.getTimeMilli() << " ms" << endl;
154 
155     Mat out;
156     cv::cvtColor(image, out, COLOR_GRAY2BGR);
157 
158     for (size_t i = 0; i < position.size(); ++i)
159     {
160         Point2f pos(position[i][0], position[i][1]);
161         float scale = position[i][2];
162         float angle = position[i][3];
163 
164         RotatedRect rect;
165         rect.center = pos;
166         rect.size = Size2f(templ.cols * scale, templ.rows * scale);
167         rect.angle = angle;
168 
169         Point2f pts[4];
170         rect.points(pts);
171 
172         line(out, pts[0], pts[1], Scalar(0, 0, 255), 3);
173         line(out, pts[1], pts[2], Scalar(0, 0, 255), 3);
174         line(out, pts[2], pts[3], Scalar(0, 0, 255), 3);
175         line(out, pts[3], pts[0], Scalar(0, 0, 255), 3);
176     }
177 
178     imshow("out", out);
179     waitKey();
180 
181     return 0;
182 }
183