1// This file is part of OpenCV project.
2// It is subject to the license terms in the LICENSE file found in the top-level directory
3// of this distribution and at http://opencv.org/license.html
4
5#include <opencv2/xobjdetect.hpp>
6#include <opencv2/highgui.hpp>
7#include <opencv2/imgproc.hpp>
8#include <opencv2/videoio.hpp>
9#include <iostream>
10#include <iomanip>
11
12using namespace cv;
13using namespace std;
14
15class Detector
16{
17 enum Mode { Default, Daimler } m;
18 HOGDescriptor hog, hog_d;
19public:
20 Detector() : m(Default), hog(), hog_d(Size(48, 96), Size(16, 16), Size(8, 8), Size(8, 8), 9)
21 {
22 hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
23 hog_d.setSVMDetector(HOGDescriptor::getDaimlerPeopleDetector());
24 }
25 void toggleMode() { m = (m == Default ? Daimler : Default); }
26 string modeName() const { return (m == Default ? "Default" : "Daimler"); }
27 vector<Rect> detect(InputArray img)
28 {
29 // Run the detector with default parameters. to get a higher hit-rate
30 // (and more false alarms, respectively), decrease the hitThreshold and
31 // groupThreshold (set groupThreshold to 0 to turn off the grouping completely).
32 vector<Rect> found;
33 if (m == Default)
34 hog.detectMultiScale(img, found, 0, Size(8,8), Size(), 1.05, 2, false);
35 else if (m == Daimler)
36 hog_d.detectMultiScale(img, found, 0, Size(8,8), Size(), 1.05, 2, true);
37 return found;
38 }
39 void adjustRect(Rect & r) const
40 {
41 // The HOG detector returns slightly larger rectangles than the real objects,
42 // so we slightly shrink the rectangles to get a nicer output.
43 r.x += cvRound(r.width*0.1);
44 r.width = cvRound(r.width*0.8);
45 r.y += cvRound(r.height*0.07);
46 r.height = cvRound(r.height*0.8);
47 }
48};
49
50static const string keys = "{ help h | | print help message }"
51 "{ camera c | 0 | capture video from camera (device index starting from 0) }"
52 "{ video v | | use video as input }";
53
54int main(int argc, char** argv)
55{
56 CommandLineParser parser(argc, argv, keys);
57 parser.about("This sample demonstrates the use of the HoG descriptor.");
58 if (parser.has("help"))
59 {
60 parser.printMessage();
61 return 0;
62 }
63 int camera = parser.get<int>("camera");
64 string file = parser.get<string>("video");
65 if (!parser.check())
66 {
67 parser.printErrors();
68 return 1;
69 }
70
71 VideoCapture cap;
72 if (file.empty())
73 cap.open(camera);
74 else
75 {
76 file = samples::findFileOrKeep(file);
77 cap.open(file);
78 }
79 if (!cap.isOpened())
80 {
81 cout << "Can not open video stream: '" << (file.empty() ? "<camera>" : file) << "'" << endl;
82 return 2;
83 }
84
85 cout << "Press 'q' or <ESC> to quit." << endl;
86 cout << "Press <space> to toggle between Default and Daimler detector" << endl;
87 Detector detector;
88 Mat frame;
89 for (;;)
90 {
91 cap >> frame;
92 if (frame.empty())
93 {
94 cout << "Finished reading: empty frame" << endl;
95 break;
96 }
97 int64 t = getTickCount();
98 vector<Rect> found = detector.detect(frame);
99 t = getTickCount() - t;
100
101 // show the window
102 {
103 ostringstream buf;
104 buf << "Mode: " << detector.modeName() << " ||| "
105 << "FPS: " << fixed << setprecision(1) << (getTickFrequency() / (double)t);
106 putText(frame, buf.str(), Point(10, 30), FONT_HERSHEY_PLAIN, 2.0, Scalar(0, 0, 255), 2, LINE_AA);
107 }
108 for (vector<Rect>::iterator i = found.begin(); i != found.end(); ++i)
109 {
110 Rect &r = *i;
111 detector.adjustRect(r);
112 rectangle(frame, r.tl(), r.br(), cv::Scalar(0, 255, 0), 2);
113 }
114 imshow("People detector", frame);
115
116 // interact with user
117 const char key = (char)waitKey(1);
118 if (key == 27 || key == 'q') // ESC
119 {
120 cout << "Exit requested" << endl;
121 break;
122 }
123 else if (key == ' ')
124 {
125 detector.toggleMode();
126 }
127 }
128 return 0;
129}