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