Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/samples/gpu/cascadeclassifier_nvidia_api.cpp
16337 views
1
#if defined _MSC_VER && _MSC_VER >= 1400
2
#pragma warning( disable : 4201 4408 4127 4100)
3
#endif
4
5
#include <iostream>
6
#include <iomanip>
7
#include <cstdio>
8
#include "opencv2/core/cuda.hpp"
9
#include "opencv2/cudalegacy.hpp"
10
#include "opencv2/highgui.hpp"
11
#include "opencv2/imgproc.hpp"
12
#include "opencv2/objdetect.hpp"
13
#include "opencv2/objdetect/objdetect_c.h"
14
15
using namespace std;
16
using namespace cv;
17
18
19
#if !defined(HAVE_CUDA) || defined(__arm__)
20
21
int main( int, const char** )
22
{
23
#if !defined(HAVE_CUDA)
24
std::cout << "CUDA support is required (CMake key 'WITH_CUDA' must be true)." << std::endl;
25
#endif
26
27
#if defined(__arm__)
28
std::cout << "Unsupported for ARM CUDA library." << std::endl;
29
#endif
30
31
return 0;
32
}
33
34
#else
35
36
37
const Size2i preferredVideoFrameSize(640, 480);
38
const cv::String wndTitle = "NVIDIA Computer Vision :: Haar Classifiers Cascade";
39
40
41
static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
42
{
43
int fontFace = FONT_HERSHEY_DUPLEX;
44
double fontScale = 0.8;
45
int fontThickness = 2;
46
Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);
47
48
Point org;
49
org.x = 1;
50
org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;
51
putText(img, ss, org, fontFace, fontScale, Scalar(0,0,0), 5*fontThickness/2, 16);
52
putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);
53
}
54
55
56
static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
57
{
58
Scalar fontColorRed(0,0,255);
59
Scalar fontColorNV(0,185,118);
60
61
ostringstream ss;
62
ss << "FPS = " << setprecision(1) << fixed << fps;
63
matPrint(canvas, 0, fontColorRed, ss.str());
64
ss.str("");
65
ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<
66
(bGpu ? "GPU, " : "CPU, ") <<
67
(bLargestFace ? "OneFace, " : "MultiFace, ") <<
68
(bFilter ? "Filter:ON" : "Filter:OFF");
69
matPrint(canvas, 1, fontColorRed, ss.str());
70
71
if (bHelp)
72
{
73
matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");
74
matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");
75
matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");
76
matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");
77
}
78
else
79
{
80
matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
81
}
82
}
83
84
85
static NCVStatus process(Mat *srcdst,
86
Ncv32u width, Ncv32u height,
87
NcvBool bFilterRects, NcvBool bLargestFace,
88
HaarClassifierCascadeDescriptor &haar,
89
NCVVector<HaarStage64> &d_haarStages, NCVVector<HaarClassifierNode128> &d_haarNodes,
90
NCVVector<HaarFeature64> &d_haarFeatures, NCVVector<HaarStage64> &h_haarStages,
91
INCVMemAllocator &gpuAllocator,
92
INCVMemAllocator &cpuAllocator,
93
cudaDeviceProp &devProp)
94
{
95
ncvAssertReturn(!((srcdst == NULL) ^ gpuAllocator.isCounting()), NCV_NULL_PTR);
96
97
NCVStatus ncvStat;
98
99
NCV_SET_SKIP_COND(gpuAllocator.isCounting());
100
101
NCVMatrixAlloc<Ncv8u> d_src(gpuAllocator, width, height);
102
ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
103
NCVMatrixAlloc<Ncv8u> h_src(cpuAllocator, width, height);
104
ncvAssertReturn(h_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
105
NCVVectorAlloc<NcvRect32u> d_rects(gpuAllocator, 100);
106
ncvAssertReturn(d_rects.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);
107
108
NCV_SKIP_COND_BEGIN
109
110
for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++)
111
{
112
memcpy(h_src.ptr() + i * h_src.stride(), srcdst->ptr(i), srcdst->cols);
113
}
114
115
ncvStat = h_src.copySolid(d_src, 0);
116
ncvAssertReturnNcvStat(ncvStat);
117
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);
118
119
NCV_SKIP_COND_END
120
121
NcvSize32u roi;
122
roi.width = d_src.width();
123
roi.height = d_src.height();
124
125
Ncv32u numDetections;
126
ncvStat = ncvDetectObjectsMultiScale_device(
127
d_src, roi, d_rects, numDetections, haar, h_haarStages,
128
d_haarStages, d_haarNodes, d_haarFeatures,
129
haar.ClassifierSize,
130
(bFilterRects || bLargestFace) ? 4 : 0,
131
1.2f, 1,
132
(bLargestFace ? NCVPipeObjDet_FindLargestObject : 0)
133
| NCVPipeObjDet_VisualizeInPlace,
134
gpuAllocator, cpuAllocator, devProp, 0);
135
ncvAssertReturnNcvStat(ncvStat);
136
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);
137
138
NCV_SKIP_COND_BEGIN
139
140
ncvStat = d_src.copySolid(h_src, 0);
141
ncvAssertReturnNcvStat(ncvStat);
142
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);
143
144
for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++)
145
{
146
memcpy(srcdst->ptr(i), h_src.ptr() + i * h_src.stride(), srcdst->cols);
147
}
148
149
NCV_SKIP_COND_END
150
151
return NCV_SUCCESS;
152
}
153
154
155
int main(int argc, const char** argv)
156
{
157
cout << "OpenCV / NVIDIA Computer Vision" << endl;
158
cout << "Face Detection in video and live feed" << endl;
159
cout << "Syntax: exename <cascade_file> <image_or_video_or_cameraid>" << endl;
160
cout << "=========================================" << endl;
161
162
ncvAssertPrintReturn(cv::cuda::getCudaEnabledDeviceCount() != 0, "No GPU found or the library is compiled without CUDA support", -1);
163
ncvAssertPrintReturn(argc == 3, "Invalid number of arguments", -1);
164
165
cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
166
167
string cascadeName = argv[1];
168
string inputName = argv[2];
169
170
NCVStatus ncvStat;
171
NcvBool bQuit = false;
172
VideoCapture capture;
173
Size2i frameSize;
174
175
//open content source
176
Mat image = imread(inputName);
177
Mat frame;
178
if (!image.empty())
179
{
180
frameSize.width = image.cols;
181
frameSize.height = image.rows;
182
}
183
else
184
{
185
if (!capture.open(inputName))
186
{
187
int camid = -1;
188
189
istringstream ss(inputName);
190
int x = 0;
191
ss >> x;
192
193
ncvAssertPrintReturn(capture.open(camid) != 0, "Can't open source", -1);
194
}
195
196
capture >> frame;
197
ncvAssertPrintReturn(!frame.empty(), "Empty video source", -1);
198
199
frameSize.width = frame.cols;
200
frameSize.height = frame.rows;
201
}
202
203
NcvBool bUseGPU = true;
204
NcvBool bLargestObject = false;
205
NcvBool bFilterRects = true;
206
NcvBool bHelpScreen = false;
207
208
CascadeClassifier classifierOpenCV;
209
ncvAssertPrintReturn(classifierOpenCV.load(cascadeName) != 0, "Error (in OpenCV) opening classifier", -1);
210
211
int devId;
212
ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);
213
cudaDeviceProp devProp;
214
ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);
215
cout << "Using GPU: " << devId << "(" << devProp.name <<
216
"), arch=" << devProp.major << "." << devProp.minor << endl;
217
218
//==============================================================================
219
//
220
// Load the classifier from file (assuming its size is about 1 mb)
221
// using a simple allocator
222
//
223
//==============================================================================
224
225
NCVMemNativeAllocator gpuCascadeAllocator(NCVMemoryTypeDevice, static_cast<Ncv32u>(devProp.textureAlignment));
226
ncvAssertPrintReturn(gpuCascadeAllocator.isInitialized(), "Error creating cascade GPU allocator", -1);
227
NCVMemNativeAllocator cpuCascadeAllocator(NCVMemoryTypeHostPinned, static_cast<Ncv32u>(devProp.textureAlignment));
228
ncvAssertPrintReturn(cpuCascadeAllocator.isInitialized(), "Error creating cascade CPU allocator", -1);
229
230
Ncv32u haarNumStages, haarNumNodes, haarNumFeatures;
231
ncvStat = ncvHaarGetClassifierSize(cascadeName, haarNumStages, haarNumNodes, haarNumFeatures);
232
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", -1);
233
234
NCVVectorAlloc<HaarStage64> h_haarStages(cpuCascadeAllocator, haarNumStages);
235
ncvAssertPrintReturn(h_haarStages.isMemAllocated(), "Error in cascade CPU allocator", -1);
236
NCVVectorAlloc<HaarClassifierNode128> h_haarNodes(cpuCascadeAllocator, haarNumNodes);
237
ncvAssertPrintReturn(h_haarNodes.isMemAllocated(), "Error in cascade CPU allocator", -1);
238
NCVVectorAlloc<HaarFeature64> h_haarFeatures(cpuCascadeAllocator, haarNumFeatures);
239
240
ncvAssertPrintReturn(h_haarFeatures.isMemAllocated(), "Error in cascade CPU allocator", -1);
241
242
HaarClassifierCascadeDescriptor haar;
243
ncvStat = ncvHaarLoadFromFile_host(cascadeName, haar, h_haarStages, h_haarNodes, h_haarFeatures);
244
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error loading classifier", -1);
245
246
NCVVectorAlloc<HaarStage64> d_haarStages(gpuCascadeAllocator, haarNumStages);
247
ncvAssertPrintReturn(d_haarStages.isMemAllocated(), "Error in cascade GPU allocator", -1);
248
NCVVectorAlloc<HaarClassifierNode128> d_haarNodes(gpuCascadeAllocator, haarNumNodes);
249
ncvAssertPrintReturn(d_haarNodes.isMemAllocated(), "Error in cascade GPU allocator", -1);
250
NCVVectorAlloc<HaarFeature64> d_haarFeatures(gpuCascadeAllocator, haarNumFeatures);
251
ncvAssertPrintReturn(d_haarFeatures.isMemAllocated(), "Error in cascade GPU allocator", -1);
252
253
ncvStat = h_haarStages.copySolid(d_haarStages, 0);
254
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);
255
ncvStat = h_haarNodes.copySolid(d_haarNodes, 0);
256
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);
257
ncvStat = h_haarFeatures.copySolid(d_haarFeatures, 0);
258
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);
259
260
//==============================================================================
261
//
262
// Calculate memory requirements and create real allocators
263
//
264
//==============================================================================
265
266
NCVMemStackAllocator gpuCounter(static_cast<Ncv32u>(devProp.textureAlignment));
267
ncvAssertPrintReturn(gpuCounter.isInitialized(), "Error creating GPU memory counter", -1);
268
NCVMemStackAllocator cpuCounter(static_cast<Ncv32u>(devProp.textureAlignment));
269
ncvAssertPrintReturn(cpuCounter.isInitialized(), "Error creating CPU memory counter", -1);
270
271
ncvStat = process(NULL, frameSize.width, frameSize.height,
272
false, false, haar,
273
d_haarStages, d_haarNodes,
274
d_haarFeatures, h_haarStages,
275
gpuCounter, cpuCounter, devProp);
276
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1);
277
278
NCVMemStackAllocator gpuAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), static_cast<Ncv32u>(devProp.textureAlignment));
279
ncvAssertPrintReturn(gpuAllocator.isInitialized(), "Error creating GPU memory allocator", -1);
280
NCVMemStackAllocator cpuAllocator(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), static_cast<Ncv32u>(devProp.textureAlignment));
281
ncvAssertPrintReturn(cpuAllocator.isInitialized(), "Error creating CPU memory allocator", -1);
282
283
printf("Initialized for frame size [%dx%d]\n", frameSize.width, frameSize.height);
284
285
//==============================================================================
286
//
287
// Main processing loop
288
//
289
//==============================================================================
290
291
namedWindow(wndTitle, 1);
292
Mat frameDisp;
293
294
do
295
{
296
Mat gray;
297
cvtColor((image.empty() ? frame : image), gray, cv::COLOR_BGR2GRAY);
298
299
//
300
// process
301
//
302
303
NcvSize32u minSize = haar.ClassifierSize;
304
if (bLargestObject)
305
{
306
Ncv32u ratioX = preferredVideoFrameSize.width / minSize.width;
307
Ncv32u ratioY = preferredVideoFrameSize.height / minSize.height;
308
Ncv32u ratioSmallest = min(ratioX, ratioY);
309
ratioSmallest = max((Ncv32u)(ratioSmallest / 2.5f), (Ncv32u)1);
310
minSize.width *= ratioSmallest;
311
minSize.height *= ratioSmallest;
312
}
313
314
Ncv32f avgTime;
315
NcvTimer timer = ncvStartTimer();
316
317
if (bUseGPU)
318
{
319
ncvStat = process(&gray, frameSize.width, frameSize.height,
320
bFilterRects, bLargestObject, haar,
321
d_haarStages, d_haarNodes,
322
d_haarFeatures, h_haarStages,
323
gpuAllocator, cpuAllocator, devProp);
324
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1);
325
}
326
else
327
{
328
vector<Rect> rectsOpenCV;
329
330
classifierOpenCV.detectMultiScale(
331
gray,
332
rectsOpenCV,
333
1.2f,
334
bFilterRects ? 4 : 0,
335
(bLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)
336
| CV_HAAR_SCALE_IMAGE,
337
Size(minSize.width, minSize.height));
338
339
for (size_t rt = 0; rt < rectsOpenCV.size(); ++rt)
340
rectangle(gray, rectsOpenCV[rt], Scalar(255));
341
}
342
343
avgTime = (Ncv32f)ncvEndQueryTimerMs(timer);
344
345
cvtColor(gray, frameDisp, cv::COLOR_GRAY2BGR);
346
displayState(frameDisp, bHelpScreen, bUseGPU, bLargestObject, bFilterRects, 1000.0f / avgTime);
347
imshow(wndTitle, frameDisp);
348
349
//handle input
350
switch (cv::waitKey(3))
351
{
352
case ' ':
353
bUseGPU = !bUseGPU;
354
break;
355
case 'm':
356
case 'M':
357
bLargestObject = !bLargestObject;
358
break;
359
case 'f':
360
case 'F':
361
bFilterRects = !bFilterRects;
362
break;
363
case 'h':
364
case 'H':
365
bHelpScreen = !bHelpScreen;
366
break;
367
case 27:
368
bQuit = true;
369
break;
370
}
371
372
// For camera and video file, capture the next image
373
if (capture.isOpened())
374
{
375
capture >> frame;
376
if (frame.empty())
377
{
378
break;
379
}
380
}
381
} while (!bQuit);
382
383
cv::destroyWindow(wndTitle);
384
385
return 0;
386
}
387
388
#endif //!defined(HAVE_CUDA)
389
390