314 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			314 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // WARNING: this sample is under construction! Use it on your own risk.
 | |
| #if defined _MSC_VER && _MSC_VER >= 1400
 | |
| #pragma warning(disable : 4100)
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #include <iostream>
 | |
| #include <iomanip>
 | |
| #include "opencv2/contrib/contrib.hpp"
 | |
| #include "opencv2/objdetect/objdetect.hpp"
 | |
| #include "opencv2/highgui/highgui.hpp"
 | |
| #include "opencv2/imgproc/imgproc.hpp"
 | |
| #include "opencv2/gpu/gpu.hpp"
 | |
| 
 | |
| using namespace std;
 | |
| using namespace cv;
 | |
| using namespace cv::gpu;
 | |
| 
 | |
| 
 | |
| static void help()
 | |
| {
 | |
|     cout << "Usage: ./cascadeclassifier_gpu \n\t--cascade <cascade_file>\n\t(<image>|--video <video>|--camera <camera_id>)\n"
 | |
|             "Using OpenCV version " << CV_VERSION << endl << endl;
 | |
| }
 | |
| 
 | |
| 
 | |
| template<class T>
 | |
| void convertAndResize(const T& src, T& gray, T& resized, double scale)
 | |
| {
 | |
|     if (src.channels() == 3)
 | |
|     {
 | |
|         cvtColor( src, gray, CV_BGR2GRAY );
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         gray = src;
 | |
|     }
 | |
| 
 | |
|     Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
 | |
| 
 | |
|     if (scale != 1)
 | |
|     {
 | |
|         resize(gray, resized, sz);
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         resized = gray;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
 | |
| {
 | |
|     int fontFace = FONT_HERSHEY_DUPLEX;
 | |
|     double fontScale = 0.8;
 | |
|     int fontThickness = 2;
 | |
|     Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);
 | |
| 
 | |
|     Point org;
 | |
|     org.x = 1;
 | |
|     org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;
 | |
|     putText(img, ss, org, fontFace, fontScale, CV_RGB(0,0,0), 5*fontThickness/2, 16);
 | |
|     putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);
 | |
| }
 | |
| 
 | |
| 
 | |
| static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
 | |
| {
 | |
|     Scalar fontColorRed = CV_RGB(255,0,0);
 | |
|     Scalar fontColorNV  = CV_RGB(118,185,0);
 | |
| 
 | |
|     ostringstream ss;
 | |
|     ss << "FPS = " << setprecision(1) << fixed << fps;
 | |
|     matPrint(canvas, 0, fontColorRed, ss.str());
 | |
|     ss.str("");
 | |
|     ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<
 | |
|         (bGpu ? "GPU, " : "CPU, ") <<
 | |
|         (bLargestFace ? "OneFace, " : "MultiFace, ") <<
 | |
|         (bFilter ? "Filter:ON" : "Filter:OFF");
 | |
|     matPrint(canvas, 1, fontColorRed, ss.str());
 | |
| 
 | |
|     // by Anatoly. MacOS fix. ostringstream(const string&) is a private
 | |
|     // matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));
 | |
|     if (bHelp)
 | |
|     {
 | |
|         matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");
 | |
|         matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");
 | |
|         matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");
 | |
|         matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");
 | |
|         matPrint(canvas, 6, fontColorNV, "1/Q - increase/decrease scale");
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| int main(int argc, const char *argv[])
 | |
| {
 | |
|     if (argc == 1)
 | |
|     {
 | |
|         help();
 | |
|         return -1;
 | |
|     }
 | |
| 
 | |
|     if (getCudaEnabledDeviceCount() == 0)
 | |
|     {
 | |
|         return cerr << "No GPU found or the library is compiled without GPU support" << endl, -1;
 | |
|     }
 | |
| 
 | |
|     cv::gpu::printShortCudaDeviceInfo(cv::gpu::getDevice());
 | |
| 
 | |
|     string cascadeName;
 | |
|     string inputName;
 | |
|     bool isInputImage = false;
 | |
|     bool isInputVideo = false;
 | |
|     bool isInputCamera = false;
 | |
| 
 | |
|     for (int i = 1; i < argc; ++i)
 | |
|     {
 | |
|         if (string(argv[i]) == "--cascade")
 | |
|             cascadeName = argv[++i];
 | |
|         else if (string(argv[i]) == "--video")
 | |
|         {
 | |
|             inputName = argv[++i];
 | |
|             isInputVideo = true;
 | |
|         }
 | |
|         else if (string(argv[i]) == "--camera")
 | |
|         {
 | |
|             inputName = argv[++i];
 | |
|             isInputCamera = true;
 | |
|         }
 | |
|         else if (string(argv[i]) == "--help")
 | |
|         {
 | |
|             help();
 | |
|             return -1;
 | |
|         }
 | |
|         else if (!isInputImage)
 | |
|         {
 | |
|             inputName = argv[i];
 | |
|             isInputImage = true;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             cout << "Unknown key: " << argv[i] << endl;
 | |
|             return -1;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     CascadeClassifier_GPU cascade_gpu;
 | |
|     if (!cascade_gpu.load(cascadeName))
 | |
|     {
 | |
|         return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
 | |
|     }
 | |
| 
 | |
|     CascadeClassifier cascade_cpu;
 | |
|     if (!cascade_cpu.load(cascadeName))
 | |
|     {
 | |
|         return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
 | |
|     }
 | |
| 
 | |
|     VideoCapture capture;
 | |
|     Mat image;
 | |
| 
 | |
|     if (isInputImage)
 | |
|     {
 | |
|         image = imread(inputName);
 | |
|         CV_Assert(!image.empty());
 | |
|     }
 | |
|     else if (isInputVideo)
 | |
|     {
 | |
|         capture.open(inputName);
 | |
|         CV_Assert(capture.isOpened());
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         capture.open(atoi(inputName.c_str()));
 | |
|         CV_Assert(capture.isOpened());
 | |
|     }
 | |
| 
 | |
|     namedWindow("result", 1);
 | |
| 
 | |
|     Mat frame, frame_cpu, gray_cpu, resized_cpu, faces_downloaded, frameDisp;
 | |
|     vector<Rect> facesBuf_cpu;
 | |
| 
 | |
|     GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu;
 | |
| 
 | |
|     /* parameters */
 | |
|     bool useGPU = true;
 | |
|     double scaleFactor = 1.0;
 | |
|     bool findLargestObject = false;
 | |
|     bool filterRects = true;
 | |
|     bool helpScreen = false;
 | |
| 
 | |
|     int detections_num;
 | |
|     for (;;)
 | |
|     {
 | |
|         if (isInputCamera || isInputVideo)
 | |
|         {
 | |
|             capture >> frame;
 | |
|             if (frame.empty())
 | |
|             {
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         (image.empty() ? frame : image).copyTo(frame_cpu);
 | |
|         frame_gpu.upload(image.empty() ? frame : image);
 | |
| 
 | |
|         convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor);
 | |
|         convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor);
 | |
| 
 | |
|         TickMeter tm;
 | |
|         tm.start();
 | |
| 
 | |
|         if (useGPU)
 | |
|         {
 | |
|             //cascade_gpu.visualizeInPlace = true;
 | |
|             cascade_gpu.findLargestObject = findLargestObject;
 | |
| 
 | |
|             detections_num = cascade_gpu.detectMultiScale(resized_gpu, facesBuf_gpu, 1.2,
 | |
|                                                           (filterRects || findLargestObject) ? 4 : 0);
 | |
|             facesBuf_gpu.colRange(0, detections_num).download(faces_downloaded);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             Size minSize = cascade_gpu.getClassifierSize();
 | |
|             cascade_cpu.detectMultiScale(resized_cpu, facesBuf_cpu, 1.2,
 | |
|                                          (filterRects || findLargestObject) ? 4 : 0,
 | |
|                                          (findLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)
 | |
|                                             | CV_HAAR_SCALE_IMAGE,
 | |
|                                          minSize);
 | |
|             detections_num = (int)facesBuf_cpu.size();
 | |
|         }
 | |
| 
 | |
|         if (!useGPU && detections_num)
 | |
|         {
 | |
|             for (int i = 0; i < detections_num; ++i)
 | |
|             {
 | |
|                 rectangle(resized_cpu, facesBuf_cpu[i], Scalar(255));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (useGPU)
 | |
|         {
 | |
|             resized_gpu.download(resized_cpu);
 | |
| 
 | |
|              for (int i = 0; i < detections_num; ++i)
 | |
|              {
 | |
|                 rectangle(resized_cpu, faces_downloaded.ptr<cv::Rect>()[i], Scalar(255));
 | |
|              }
 | |
|         }
 | |
| 
 | |
|         tm.stop();
 | |
|         double detectionTime = tm.getTimeMilli();
 | |
|         double fps = 1000 / detectionTime;
 | |
| 
 | |
|         //print detections to console
 | |
|         cout << setfill(' ') << setprecision(2);
 | |
|         cout << setw(6) << fixed << fps << " FPS, " << detections_num << " det";
 | |
|         if ((filterRects || findLargestObject) && detections_num > 0)
 | |
|         {
 | |
|             Rect *faceRects = useGPU ? faces_downloaded.ptr<Rect>() : &facesBuf_cpu[0];
 | |
|             for (int i = 0; i < min(detections_num, 2); ++i)
 | |
|             {
 | |
|                 cout << ", [" << setw(4) << faceRects[i].x
 | |
|                      << ", " << setw(4) << faceRects[i].y
 | |
|                      << ", " << setw(4) << faceRects[i].width
 | |
|                      << ", " << setw(4) << faceRects[i].height << "]";
 | |
|             }
 | |
|         }
 | |
|         cout << endl;
 | |
| 
 | |
|         cvtColor(resized_cpu, frameDisp, CV_GRAY2BGR);
 | |
|         displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps);
 | |
|         imshow("result", frameDisp);
 | |
| 
 | |
|         char key = (char)waitKey(5);
 | |
|         if (key == 27)
 | |
|         {
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         switch (key)
 | |
|         {
 | |
|         case ' ':
 | |
|             useGPU = !useGPU;
 | |
|             break;
 | |
|         case 'm':
 | |
|         case 'M':
 | |
|             findLargestObject = !findLargestObject;
 | |
|             break;
 | |
|         case 'f':
 | |
|         case 'F':
 | |
|             filterRects = !filterRects;
 | |
|             break;
 | |
|         case '1':
 | |
|             scaleFactor *= 1.05;
 | |
|             break;
 | |
|         case 'q':
 | |
|         case 'Q':
 | |
|             scaleFactor /= 1.05;
 | |
|             break;
 | |
|         case 'h':
 | |
|         case 'H':
 | |
|             helpScreen = !helpScreen;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | 
