Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/samples/gpu/cascadeclassifier.cpp
16337 views
1
// WARNING: this sample is under construction! Use it on your own risk.
2
#if defined _MSC_VER && _MSC_VER >= 1400
3
#pragma warning(disable : 4100)
4
#endif
5
6
7
#include <iostream>
8
#include <iomanip>
9
#include "opencv2/objdetect.hpp"
10
#include "opencv2/highgui.hpp"
11
#include "opencv2/imgproc.hpp"
12
#include "opencv2/cudaobjdetect.hpp"
13
#include "opencv2/cudaimgproc.hpp"
14
#include "opencv2/cudawarping.hpp"
15
16
using namespace std;
17
using namespace cv;
18
using namespace cv::cuda;
19
20
21
static void help()
22
{
23
cout << "Usage: ./cascadeclassifier \n\t--cascade <cascade_file>\n\t(<image>|--video <video>|--camera <camera_id>)\n"
24
"Using OpenCV version " << CV_VERSION << endl << endl;
25
}
26
27
28
static void convertAndResize(const Mat& src, Mat& gray, Mat& resized, double scale)
29
{
30
if (src.channels() == 3)
31
{
32
cv::cvtColor( src, gray, COLOR_BGR2GRAY );
33
}
34
else
35
{
36
gray = src;
37
}
38
39
Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
40
41
if (scale != 1)
42
{
43
cv::resize(gray, resized, sz);
44
}
45
else
46
{
47
resized = gray;
48
}
49
}
50
51
static void convertAndResize(const GpuMat& src, GpuMat& gray, GpuMat& resized, double scale)
52
{
53
if (src.channels() == 3)
54
{
55
cv::cuda::cvtColor( src, gray, COLOR_BGR2GRAY );
56
}
57
else
58
{
59
gray = src;
60
}
61
62
Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
63
64
if (scale != 1)
65
{
66
cv::cuda::resize(gray, resized, sz);
67
}
68
else
69
{
70
resized = gray;
71
}
72
}
73
74
75
static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
76
{
77
int fontFace = FONT_HERSHEY_DUPLEX;
78
double fontScale = 0.8;
79
int fontThickness = 2;
80
Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);
81
82
Point org;
83
org.x = 1;
84
org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;
85
putText(img, ss, org, fontFace, fontScale, Scalar(0,0,0), 5*fontThickness/2, 16);
86
putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);
87
}
88
89
90
static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
91
{
92
Scalar fontColorRed = Scalar(255,0,0);
93
Scalar fontColorNV = Scalar(118,185,0);
94
95
ostringstream ss;
96
ss << "FPS = " << setprecision(1) << fixed << fps;
97
matPrint(canvas, 0, fontColorRed, ss.str());
98
ss.str("");
99
ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<
100
(bGpu ? "GPU, " : "CPU, ") <<
101
(bLargestFace ? "OneFace, " : "MultiFace, ") <<
102
(bFilter ? "Filter:ON" : "Filter:OFF");
103
matPrint(canvas, 1, fontColorRed, ss.str());
104
105
// by Anatoly. MacOS fix. ostringstream(const string&) is a private
106
// matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));
107
if (bHelp)
108
{
109
matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");
110
matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");
111
matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");
112
matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");
113
matPrint(canvas, 6, fontColorNV, "1/Q - increase/decrease scale");
114
}
115
else
116
{
117
matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
118
}
119
}
120
121
122
int main(int argc, const char *argv[])
123
{
124
if (argc == 1)
125
{
126
help();
127
return -1;
128
}
129
130
if (getCudaEnabledDeviceCount() == 0)
131
{
132
return cerr << "No GPU found or the library is compiled without CUDA support" << endl, -1;
133
}
134
135
cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
136
137
string cascadeName;
138
string inputName;
139
bool isInputImage = false;
140
bool isInputVideo = false;
141
bool isInputCamera = false;
142
143
for (int i = 1; i < argc; ++i)
144
{
145
if (string(argv[i]) == "--cascade")
146
cascadeName = argv[++i];
147
else if (string(argv[i]) == "--video")
148
{
149
inputName = argv[++i];
150
isInputVideo = true;
151
}
152
else if (string(argv[i]) == "--camera")
153
{
154
inputName = argv[++i];
155
isInputCamera = true;
156
}
157
else if (string(argv[i]) == "--help")
158
{
159
help();
160
return -1;
161
}
162
else if (!isInputImage)
163
{
164
inputName = argv[i];
165
isInputImage = true;
166
}
167
else
168
{
169
cout << "Unknown key: " << argv[i] << endl;
170
return -1;
171
}
172
}
173
174
Ptr<cuda::CascadeClassifier> cascade_gpu = cuda::CascadeClassifier::create(cascadeName);
175
176
cv::CascadeClassifier cascade_cpu;
177
if (!cascade_cpu.load(cascadeName))
178
{
179
return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
180
}
181
182
VideoCapture capture;
183
Mat image;
184
185
if (isInputImage)
186
{
187
image = imread(inputName);
188
CV_Assert(!image.empty());
189
}
190
else if (isInputVideo)
191
{
192
capture.open(inputName);
193
CV_Assert(capture.isOpened());
194
}
195
else
196
{
197
capture.open(atoi(inputName.c_str()));
198
CV_Assert(capture.isOpened());
199
}
200
201
namedWindow("result", 1);
202
203
Mat frame, frame_cpu, gray_cpu, resized_cpu, frameDisp;
204
vector<Rect> faces;
205
206
GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu;
207
208
/* parameters */
209
bool useGPU = true;
210
double scaleFactor = 1.0;
211
bool findLargestObject = false;
212
bool filterRects = true;
213
bool helpScreen = false;
214
215
for (;;)
216
{
217
if (isInputCamera || isInputVideo)
218
{
219
capture >> frame;
220
if (frame.empty())
221
{
222
break;
223
}
224
}
225
226
(image.empty() ? frame : image).copyTo(frame_cpu);
227
frame_gpu.upload(image.empty() ? frame : image);
228
229
convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor);
230
convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor);
231
232
TickMeter tm;
233
tm.start();
234
235
if (useGPU)
236
{
237
cascade_gpu->setFindLargestObject(findLargestObject);
238
cascade_gpu->setScaleFactor(1.2);
239
cascade_gpu->setMinNeighbors((filterRects || findLargestObject) ? 4 : 0);
240
241
cascade_gpu->detectMultiScale(resized_gpu, facesBuf_gpu);
242
cascade_gpu->convert(facesBuf_gpu, faces);
243
}
244
else
245
{
246
Size minSize = cascade_gpu->getClassifierSize();
247
cascade_cpu.detectMultiScale(resized_cpu, faces, 1.2,
248
(filterRects || findLargestObject) ? 4 : 0,
249
(findLargestObject ? CASCADE_FIND_BIGGEST_OBJECT : 0)
250
| CASCADE_SCALE_IMAGE,
251
minSize);
252
}
253
254
for (size_t i = 0; i < faces.size(); ++i)
255
{
256
rectangle(resized_cpu, faces[i], Scalar(255));
257
}
258
259
tm.stop();
260
double detectionTime = tm.getTimeMilli();
261
double fps = 1000 / detectionTime;
262
263
//print detections to console
264
cout << setfill(' ') << setprecision(2);
265
cout << setw(6) << fixed << fps << " FPS, " << faces.size() << " det";
266
if ((filterRects || findLargestObject) && !faces.empty())
267
{
268
for (size_t i = 0; i < faces.size(); ++i)
269
{
270
cout << ", [" << setw(4) << faces[i].x
271
<< ", " << setw(4) << faces[i].y
272
<< ", " << setw(4) << faces[i].width
273
<< ", " << setw(4) << faces[i].height << "]";
274
}
275
}
276
cout << endl;
277
278
cv::cvtColor(resized_cpu, frameDisp, COLOR_GRAY2BGR);
279
displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps);
280
imshow("result", frameDisp);
281
282
char key = (char)waitKey(5);
283
if (key == 27)
284
{
285
break;
286
}
287
288
switch (key)
289
{
290
case ' ':
291
useGPU = !useGPU;
292
break;
293
case 'm':
294
case 'M':
295
findLargestObject = !findLargestObject;
296
break;
297
case 'f':
298
case 'F':
299
filterRects = !filterRects;
300
break;
301
case '1':
302
scaleFactor *= 1.05;
303
break;
304
case 'q':
305
case 'Q':
306
scaleFactor /= 1.05;
307
break;
308
case 'h':
309
case 'H':
310
helpScreen = !helpScreen;
311
break;
312
}
313
}
314
315
return 0;
316
}
317
318