#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/objdetect/objdetect.hpp" #include "opencv2/highgui/highgui.hpp" #include #include #include #include #include void filter_rects(const std::vector& candidates, std::vector& objects); int main(int argc, char** argv) { const std::string keys = "{help h usage ? | | print this message and exit }" "{cascade c | | path to cascade xml, if empty HOG detector will be executed }" "{frame f | | wildchart pattern to frame source}" "{min_scale |0.4 | minimum scale to detect }" "{max_scale |5.0 | maxamum scale to detect }" "{total_scales |55 | prefered number of scales between min and max }" "{write_file wf |0 | write to .txt. Disabled by default.}" "{write_image wi |0 | write to image. Disabled by default.}" "{show_image si |1 | show image. Enabled by default.}" "{threshold thr |-1 | detection threshold. Detections with score less then threshold will be ignored.}" ; cv::CommandLineParser parser(argc, argv, keys); parser.about("Soft cascade training application."); if (parser.has("help")) { parser.printMessage(); return 0; } if (!parser.check()) { parser.printErrors(); return 1; } int wf = parser.get("write_file"); if (wf) std::cout << "resulte will be stored to .txt file with the same name as image." << std::endl; int wi = parser.get("write_image"); if (wi) std::cout << "resulte will be stored to image with the same name as input plus dt." << std::endl; int si = parser.get("show_image"); float minScale = parser.get("min_scale"); float maxScale = parser.get("max_scale"); int scales = parser.get("total_scales"); int thr = parser.get("threshold"); cv::HOGDescriptor hog; cv::softcascade::Detector cascade; bool useHOG = false; std::string cascadePath = parser.get("cascade"); if (cascadePath.empty()) { useHOG = true; hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector()); std::cout << "going to use HOG detector." << std::endl; } else { cv::FileStorage fs(cascadePath, cv::FileStorage::READ); if( !fs.isOpened()) { std::cout << "Soft Cascade file " << cascadePath << " can't be opened." << std::endl << std::flush; return 1; } cascade = cv::softcascade::Detector(minScale, maxScale, scales, cv::softcascade::Detector::DOLLAR); if (!cascade.load(fs.getFirstTopLevelNode())) { std::cout << "Soft Cascade can't be parsed." << std::endl << std::flush; return 1; } } std::string src = parser.get("frame"); std::vector frames; cv::glob(parser.get("frame"), frames); std::cout << "collected " << src << " " << frames.size() << " frames." << std::endl; for (int i = 0; i < (int)frames.size(); ++i) { std::string& frame_sourse = frames[i]; cv::Mat frame = cv::imread(frame_sourse); if(frame.empty()) { std::cout << "Frame source " << frame_sourse << " can't be opened." << std::endl << std::flush; continue; } std::ofstream myfile; if (wf) myfile.open((frame_sourse.replace(frame_sourse.end() - 3, frame_sourse.end(), "txt")).c_str(), std::ios::out); //// if (useHOG) { std::vector found, found_filtered; // run the detector with default parameters. to get a higher hit-rate // (and more false alarms, respectively), decrease the hitThreshold and // groupThreshold (set groupThreshold to 0 to turn off the grouping completely). hog.detectMultiScale(frame, found, 0, cv::Size(8,8), cv::Size(32,32), 1.05, 2); filter_rects(found, found_filtered); std::cout << "collected: " << (int)found_filtered.size() << " detections." << std::endl; for (size_t ff = 0; ff < found_filtered.size(); ++ff) { cv::Rect r = found_filtered[ff]; cv::rectangle(frame, r.tl(), r.br(), cv::Scalar(0,255,0), 3); if (wf) myfile << r.x << "," << r.y << "," << r.width << "," << r.height << "," << 0.f << "\n"; } } else { std::vector objects; cascade.detect(frame, cv::noArray(), objects); std::cout << "collected: " << (int)objects.size() << " detections." << std::endl; for (int obj = 0; obj < (int)objects.size(); ++obj) { cv::softcascade::Detection d = objects[obj]; if(d.confidence > thr) { float b = d.confidence * 1.5f; std::stringstream conf(std::stringstream::in | std::stringstream::out); conf << d.confidence; cv::rectangle(frame, cv::Rect(d.bb.x, d.bb.y, d.bb.width, d.bb.height), cv::Scalar(b, 0, 255 - b, 255), 2); cv::putText(frame, conf.str() , cv::Point(d.bb.x + 10, d.bb.y - 5),1, 1.1, cv::Scalar(25, 133, 255, 0), 1, CV_AA); if (wf) myfile << d.bb.x << "," << d.bb.y << "," << d.bb.width << "," << d.bb.height << "," << d.confidence << "\n"; } } } if (wi) cv::imwrite(frame_sourse + ".dt.png", frame); if (wf) myfile.close(); if (si) { cv::imshow("pedestrian detector", frame); cv::waitKey(10); } } if (si) cv::waitKey(0); return 0; } void filter_rects(const std::vector& candidates, std::vector& objects) { size_t i, j; for (i = 0; i < candidates.size(); ++i) { cv::Rect r = candidates[i]; for (j = 0; j < candidates.size(); ++j) if (j != i && (r & candidates[j]) == r) break; if (j == candidates.size()) objects.push_back(r); } }