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)
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"
18 using namespace cv::cuda;
23 cout << "Usage: ./cascadeclassifier_gpu \n\t--cascade <cascade_file>\n\t(<image>|--video <video>|--camera <camera_id>)\n"
24 "Using OpenCV version " << CV_VERSION << endl << endl;
28 static void convertAndResize(const Mat& src, Mat& gray, Mat& resized, double scale)
30 if (src.channels() == 3)
32 cv::cvtColor( src, gray, COLOR_BGR2GRAY );
39 Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
43 cv::resize(gray, resized, sz);
51 static void convertAndResize(const GpuMat& src, GpuMat& gray, GpuMat& resized, double scale)
53 if (src.channels() == 3)
55 cv::cuda::cvtColor( src, gray, COLOR_BGR2GRAY );
62 Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
66 cv::cuda::resize(gray, resized, sz);
75 static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
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);
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);
90 static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
92 Scalar fontColorRed = Scalar(255,0,0);
93 Scalar fontColorNV = Scalar(118,185,0);
96 ss << "FPS = " << setprecision(1) << fixed << fps;
97 matPrint(canvas, 0, fontColorRed, 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());
105 // by Anatoly. MacOS fix. ostringstream(const string&) is a private
106 // matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));
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");
117 matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
122 int main(int argc, const char *argv[])
130 if (getCudaEnabledDeviceCount() == 0)
132 return cerr << "No GPU found or the library is compiled without CUDA support" << endl, -1;
135 cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
139 bool isInputImage = false;
140 bool isInputVideo = false;
141 bool isInputCamera = false;
143 for (int i = 1; i < argc; ++i)
145 if (string(argv[i]) == "--cascade")
146 cascadeName = argv[++i];
147 else if (string(argv[i]) == "--video")
149 inputName = argv[++i];
152 else if (string(argv[i]) == "--camera")
154 inputName = argv[++i];
155 isInputCamera = true;
157 else if (string(argv[i]) == "--help")
162 else if (!isInputImage)
169 cout << "Unknown key: " << argv[i] << endl;
174 Ptr<cuda::CascadeClassifier> cascade_gpu = cuda::CascadeClassifier::create(cascadeName);
176 cv::CascadeClassifier cascade_cpu;
177 if (!cascade_cpu.load(cascadeName))
179 return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
182 VideoCapture capture;
187 image = imread(inputName);
188 CV_Assert(!image.empty());
190 else if (isInputVideo)
192 capture.open(inputName);
193 CV_Assert(capture.isOpened());
197 capture.open(atoi(inputName.c_str()));
198 CV_Assert(capture.isOpened());
201 namedWindow("result", 1);
203 Mat frame, frame_cpu, gray_cpu, resized_cpu, frameDisp;
206 GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu;
210 double scaleFactor = 1.0;
211 bool findLargestObject = false;
212 bool filterRects = true;
213 bool helpScreen = false;
217 if (isInputCamera || isInputVideo)
226 (image.empty() ? frame : image).copyTo(frame_cpu);
227 frame_gpu.upload(image.empty() ? frame : image);
229 convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor);
230 convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor);
237 cascade_gpu->setFindLargestObject(findLargestObject);
238 cascade_gpu->setScaleFactor(1.2);
239 cascade_gpu->setMinNeighbors((filterRects || findLargestObject) ? 4 : 0);
241 cascade_gpu->detectMultiScale(resized_gpu, facesBuf_gpu);
242 cascade_gpu->convert(facesBuf_gpu, faces);
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,
254 for (size_t i = 0; i < faces.size(); ++i)
256 rectangle(resized_cpu, faces[i], Scalar(255));
260 double detectionTime = tm.getTimeMilli();
261 double fps = 1000 / detectionTime;
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())
268 for (size_t i = 0; i < faces.size(); ++i)
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 << "]";
278 cv::cvtColor(resized_cpu, frameDisp, COLOR_GRAY2BGR);
279 displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps);
280 imshow("result", frameDisp);
282 char key = (char)waitKey(5);
295 findLargestObject = !findLargestObject;
299 filterRects = !filterRects;
310 helpScreen = !helpScreen;