1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler// WARNING: this sample is under construction! Use it on your own risk.
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#if defined _MSC_VER && _MSC_VER >= 1400
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#pragma warning(disable : 4100)
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#endif
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <iostream>
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include <iomanip>
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/objdetect/objdetect.hpp"
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/highgui/highgui.hpp"
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/imgproc/imgproc.hpp"
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/cudaobjdetect.hpp"
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/cudaimgproc.hpp"
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "opencv2/cudawarping.hpp"
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "tick_meter.hpp"
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace std;
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv;
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerusing namespace cv::cuda;
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void help()
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cout << "Usage: ./cascadeclassifier_gpu \n\t--cascade <cascade_file>\n\t(<image>|--video <video>|--camera <camera_id>)\n"
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            "Using OpenCV version " << CV_VERSION << endl << endl;
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void convertAndResize(const Mat& src, Mat& gray, Mat& resized, double scale)
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (src.channels() == 3)
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cv::cvtColor( src, gray, COLOR_BGR2GRAY );
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        gray = src;
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (scale != 1)
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cv::resize(gray, resized, sz);
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        resized = gray;
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void convertAndResize(const GpuMat& src, GpuMat& gray, GpuMat& resized, double scale)
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (src.channels() == 3)
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cv::cuda::cvtColor( src, gray, COLOR_BGR2GRAY );
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        gray = src;
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (scale != 1)
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cv::cuda::resize(gray, resized, sz);
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        resized = gray;
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int fontFace = FONT_HERSHEY_DUPLEX;
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double fontScale = 0.8;
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    int fontThickness = 2;
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Point org;
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    org.x = 1;
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    putText(img, ss, org, fontFace, fontScale, Scalar(0,0,0), 5*fontThickness/2, 16);
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstatic void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Scalar fontColorRed = Scalar(255,0,0);
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Scalar fontColorNV  = Scalar(118,185,0);
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ostringstream ss;
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ss << "FPS = " << setprecision(1) << fixed << fps;
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matPrint(canvas, 0, fontColorRed, ss.str());
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ss.str("");
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (bGpu ? "GPU, " : "CPU, ") <<
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (bLargestFace ? "OneFace, " : "MultiFace, ") <<
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (bFilter ? "Filter:ON" : "Filter:OFF");
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    matPrint(canvas, 1, fontColorRed, ss.str());
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // by Anatoly. MacOS fix. ostringstream(const string&) is a private
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    // matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (bHelp)
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matPrint(canvas, 6, fontColorNV, "1/Q - increase/decrease scale");
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerint main(int argc, const char *argv[])
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (argc == 1)
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        help();
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return -1;
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (getCudaEnabledDeviceCount() == 0)
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return cerr << "No GPU found or the library is compiled without CUDA support" << endl, -1;
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    string cascadeName;
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    string inputName;
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool isInputImage = false;
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool isInputVideo = false;
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool isInputCamera = false;
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (int i = 1; i < argc; ++i)
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (string(argv[i]) == "--cascade")
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascadeName = argv[++i];
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else if (string(argv[i]) == "--video")
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            inputName = argv[++i];
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            isInputVideo = true;
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else if (string(argv[i]) == "--camera")
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            inputName = argv[++i];
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            isInputCamera = true;
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else if (string(argv[i]) == "--help")
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            help();
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return -1;
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else if (!isInputImage)
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            inputName = argv[i];
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            isInputImage = true;
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cout << "Unknown key: " << argv[i] << endl;
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            return -1;
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Ptr<cuda::CascadeClassifier> cascade_gpu = cuda::CascadeClassifier::create(cascadeName);
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cv::CascadeClassifier cascade_cpu;
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (!cascade_cpu.load(cascadeName))
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    VideoCapture capture;
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat image;
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (isInputImage)
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        image = imread(inputName);
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert(!image.empty());
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else if (isInputVideo)
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture.open(inputName);
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert(capture.isOpened());
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    else
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        capture.open(atoi(inputName.c_str()));
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        CV_Assert(capture.isOpened());
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    namedWindow("result", 1);
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    Mat frame, frame_cpu, gray_cpu, resized_cpu, frameDisp;
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    vector<Rect> faces;
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu;
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* parameters */
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool useGPU = true;
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    double scaleFactor = 1.0;
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool findLargestObject = false;
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool filterRects = true;
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    bool helpScreen = false;
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (;;)
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    {
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (isInputCamera || isInputVideo)
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            capture >> frame;
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            if (frame.empty())
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                break;
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        (image.empty() ? frame : image).copyTo(frame_cpu);
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        frame_gpu.upload(image.empty() ? frame : image);
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor);
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor);
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        TickMeter tm;
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        tm.start();
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (useGPU)
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascade_gpu->setFindLargestObject(findLargestObject);
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascade_gpu->setScaleFactor(1.2);
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascade_gpu->setMinNeighbors((filterRects || findLargestObject) ? 4 : 0);
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascade_gpu->detectMultiScale(resized_gpu, facesBuf_gpu);
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascade_gpu->convert(facesBuf_gpu, faces);
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        else
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            Size minSize = cascade_gpu->getClassifierSize();
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            cascade_cpu.detectMultiScale(resized_cpu, faces, 1.2,
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                         (filterRects || findLargestObject) ? 4 : 0,
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                         (findLargestObject ? CASCADE_FIND_BIGGEST_OBJECT : 0)
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                            | CASCADE_SCALE_IMAGE,
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                         minSize);
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        for (size_t i = 0; i < faces.size(); ++i)
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            rectangle(resized_cpu, faces[i], Scalar(255));
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        tm.stop();
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        double detectionTime = tm.getTimeMilli();
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        double fps = 1000 / detectionTime;
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        //print detections to console
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cout << setfill(' ') << setprecision(2);
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cout << setw(6) << fixed << fps << " FPS, " << faces.size() << " det";
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if ((filterRects || findLargestObject) && !faces.empty())
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            for (size_t i = 0; i < faces.size(); ++i)
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            {
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                cout << ", [" << setw(4) << faces[i].x
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                     << ", " << setw(4) << faces[i].y
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                     << ", " << setw(4) << faces[i].width
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                     << ", " << setw(4) << faces[i].height << "]";
276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            }
277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cout << endl;
279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cv::cvtColor(resized_cpu, frameDisp, COLOR_GRAY2BGR);
281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps);
282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        imshow("result", frameDisp);
283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        char key = (char)waitKey(5);
285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        if (key == 27)
286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
287793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        switch (key)
291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        {
292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case ' ':
293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            useGPU = !useGPU;
294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'm':
296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'M':
297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            findLargestObject = !findLargestObject;
298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'f':
300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'F':
301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            filterRects = !filterRects;
302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case '1':
304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            scaleFactor *= 1.05;
305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'q':
307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'Q':
308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            scaleFactor /= 1.05;
309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'h':
311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        case 'H':
312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            helpScreen = !helpScreen;
313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler            break;
314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        }
315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    return 0;
318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
319