Merge remote-tracking branch 'origin/2.4' into merge-2.4
[platform/upstream/opencv.git] / samples / cpp / peopledetect.cpp
1 #include <opencv2/core/utility.hpp>
2 #include <opencv2/imgproc.hpp>
3 #include <opencv2/objdetect.hpp>
4 #include <opencv2/highgui.hpp>
5 #include <opencv2/softcascade.hpp>
6
7 #include <iostream>
8 #include <vector>
9 #include <string>
10 #include <fstream>
11
12 void filter_rects(const std::vector<cv::Rect>& candidates, std::vector<cv::Rect>& objects);
13
14 int main(int argc, char** argv)
15 {
16     const std::string keys =
17     "{help h usage ?    |     | print this message and exit }"
18     "{cascade c         |     | path to cascade xml, if empty HOG detector will be executed }"
19     "{frame f           |     | wildchart pattern to frame source}"
20     "{min_scale         |0.4  | minimum scale to detect }"
21     "{max_scale         |5.0  | maxamum scale to detect }"
22     "{total_scales      |55   | prefered number of scales between min and max }"
23     "{write_file wf     |0    | write to .txt. Disabled by default.}"
24     "{write_image wi    |0    | write to image. Disabled by default.}"
25     "{show_image si     |1    | show image. Enabled by default.}"
26     "{threshold thr     |-1   | detection threshold. Detections with score less then threshold will be ignored.}"
27     ;
28
29     cv::CommandLineParser parser(argc, argv, keys);
30     parser.about("Soft cascade training application.");
31
32     if (parser.has("help"))
33     {
34         parser.printMessage();
35         return 0;
36     }
37
38     if (!parser.check())
39     {
40         parser.printErrors();
41         return 1;
42     }
43
44     int wf = parser.get<int>("write_file");
45     if (wf) std::cout << "resulte will be stored to .txt file with the same name as image." << std::endl;
46
47     int wi = parser.get<int>("write_image");
48     if (wi) std::cout << "resulte will be stored to image with the same name as input plus dt." << std::endl;
49
50     int si = parser.get<int>("show_image");
51
52     float minScale =  parser.get<float>("min_scale");
53     float maxScale =  parser.get<float>("max_scale");
54     int scales     =  parser.get<int>("total_scales");
55     int thr        =  parser.get<int>("threshold");
56
57     cv::HOGDescriptor hog;
58     cv::softcascade::Detector cascade;
59
60     bool useHOG = false;
61     std::string cascadePath = parser.get<std::string>("cascade");
62     if (cascadePath.empty())
63     {
64         useHOG = true;
65         hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());
66         std::cout << "going to use HOG detector." << std::endl;
67     }
68     else
69     {
70         cv::FileStorage fs(cascadePath, cv::FileStorage::READ);
71         if( !fs.isOpened())
72         {
73             std::cout << "Soft Cascade file " << cascadePath << " can't be opened." << std::endl << std::flush;
74             return 1;
75         }
76
77         cascade = cv::softcascade::Detector(minScale, maxScale, scales, cv::softcascade::Detector::DOLLAR);
78
79         if (!cascade.load(fs.getFirstTopLevelNode()))
80         {
81             std::cout << "Soft Cascade can't be parsed." << std::endl << std::flush;
82             return 1;
83         }
84     }
85
86     std::string src = parser.get<std::string>("frame");
87     std::vector<cv::String> frames;
88     cv::glob(parser.get<std::string>("frame"), frames);
89     std::cout << "collected " << src << " " << frames.size() << " frames." << std::endl;
90
91     for (int i = 0; i < (int)frames.size(); ++i)
92     {
93         std::string frame_sourse = frames[i];
94         cv::Mat frame = cv::imread(frame_sourse);
95
96         if(frame.empty())
97         {
98             std::cout << "Frame source " << frame_sourse << " can't be opened." << std::endl << std::flush;
99             continue;
100         }
101
102         std::ofstream myfile;
103         if (wf)
104             myfile.open((frame_sourse.replace(frame_sourse.end() - 3, frame_sourse.end(), "txt")).c_str(), std::ios::out);
105
106         ////
107         if (useHOG)
108         {
109             std::vector<cv::Rect> found, found_filtered;
110             // run the detector with default parameters. to get a higher hit-rate
111             // (and more false alarms, respectively), decrease the hitThreshold and
112             // groupThreshold (set groupThreshold to 0 to turn off the grouping completely).
113             hog.detectMultiScale(frame, found, 0, cv::Size(8,8), cv::Size(32,32), 1.05, 2);
114
115             filter_rects(found, found_filtered);
116             std::cout << "collected: " << (int)found_filtered.size() << " detections." << std::endl;
117
118             for (size_t ff = 0; ff < found_filtered.size(); ++ff)
119             {
120                 cv::Rect r = found_filtered[ff];
121                 cv::rectangle(frame, r.tl(), r.br(), cv::Scalar(0,255,0), 3);
122
123                 if (wf) myfile << r.x << "," << r.y << "," << r.width << "," << r.height << "," << 0.f << "\n";
124             }
125         }
126         else
127         {
128             std::vector<cv::softcascade::Detection> objects;
129             cascade.detect(frame,  cv::noArray(), objects);
130             std::cout << "collected: " << (int)objects.size() << " detections." << std::endl;
131
132             for (int obj = 0; obj  < (int)objects.size(); ++obj)
133             {
134                 cv::softcascade::Detection d = objects[obj];
135
136                 if(d.confidence > thr)
137                 {
138                     float b = d.confidence * 1.5f;
139
140                     std::stringstream conf(std::stringstream::in | std::stringstream::out);
141                     conf << d.confidence;
142
143                     cv::rectangle(frame, cv::Rect((int)d.x, (int)d.y, (int)d.w, (int)d.h), cv::Scalar(b, 0, 255 - b, 255), 2);
144                     cv::putText(frame, conf.str() , cv::Point((int)d.x + 10, (int)d.y - 5),1, 1.1, cv::Scalar(25, 133, 255, 0), 1, cv::LINE_AA);
145
146                     if (wf)
147                         myfile << d.x << "," <<  d.y << "," << d.w << "," <<  d.h << "," << d.confidence << "\n";
148                 }
149             }
150         }
151
152         if (wi) cv::imwrite(frame_sourse + ".dt.png", frame);
153         if (wf) myfile.close();
154
155         if (si)
156         {
157             cv::imshow("pedestrian detector", frame);
158             cv::waitKey(10);
159         }
160     }
161
162     if (si) cv::waitKey(0);
163     return 0;
164 }
165
166 void filter_rects(const std::vector<cv::Rect>& candidates, std::vector<cv::Rect>& objects)
167 {
168     size_t i, j;
169     for (i = 0; i < candidates.size(); ++i)
170     {
171         cv::Rect r = candidates[i];
172
173         for (j = 0; j < candidates.size(); ++j)
174             if (j != i && (r & candidates[j]) == r)
175                 break;
176
177         if (j == candidates.size())
178             objects.push_back(r);
179     }
180 }