\r
//#define WRITE_VIDEO\r
\r
-\r
-/** Contains all properties of application (including those which can be\r
-changed by user in runtime) */\r
-class Settings\r
+class Args\r
{\r
public:\r
- /** Sets default values */\r
- Settings();\r
-\r
- /** Reads settings from command args */\r
- static Settings Read(int argc, char** argv);\r
+ Args();\r
+ static Args read(int argc, char** argv);\r
\r
string src;\r
bool src_is_video;\r
+ bool src_is_camera;\r
+ int camera_id;\r
+\r
bool make_gray;\r
+\r
bool resize_src;\r
- double resize_src_scale;\r
+ int resized_width, resized_height;\r
+\r
double scale;\r
int nlevels;\r
int gr_threshold;\r
double hit_threshold;\r
+\r
int win_width;\r
- int win_stride_width;\r
- int win_stride_height;\r
+ int win_stride_width, win_stride_height;\r
+\r
bool gamma_corr;\r
};\r
\r
\r
-/** Describes aplication logic */\r
class App\r
{\r
public:\r
- /** Initializes application */\r
- App(const Settings& s);\r
-\r
- /** Runs demo using OpenCV highgui module for GUI building */\r
- void RunOpencvGui();\r
+ App(const Args& s);\r
+ void run();\r
\r
- /** Processes user keybord input */\r
- void HandleKey(char key);\r
+ void handleKey(char key);\r
\r
- void HogWorkBegin();\r
- void HogWorkEnd();\r
- double HogWorkFps() const;\r
+ void hogWorkBegin();\r
+ void hogWorkEnd();\r
+ string hogWorkFps() const;\r
\r
- void WorkBegin();\r
- void WorkEnd();\r
- double WorkFps() const;\r
+ void workBegin();\r
+ void workEnd();\r
+ string workFps() const;\r
\r
- const string GetPerformanceSummary() const;\r
+ string message() const;\r
\r
private:\r
App operator=(App&);\r
\r
- Settings settings;\r
+ Args args;\r
bool running;\r
\r
bool use_gpu;\r
{\r
try\r
{\r
+ cout << "Histogram of Oriented Gradients descriptor and detector sample.\n";\r
if (argc < 2)\r
{\r
- cout << "Usage:\nhog_gpu\n"\r
- << " -src <path_to_the_source>\n"\r
- << " [-src_is_video <true/false>] # says to interp. src as img or as video\n"\r
- << " [-make_gray <true/false>] # convert image to gray one or not\n"\r
- << " [-resize_src <true/false>] # do resize of the source image or not\n"\r
- << " [-resize_src_scale <double>] # preprocessing image scale factor\n"\r
- << " [-hit_threshold <double>] # classifying plane dist. threshold (0.0 usually)\n"\r
- << " [-scale <double>] # HOG window scale factor\n"\r
- << " [-nlevels <int>] # max number of HOG window scales\n"\r
- << " [-win_width <int>] # width of the window (48 or 64)\n"\r
- << " [-win_stride_width <int>] # distance by OX axis between neighbour wins\n"\r
- << " [-win_stride_height <int>] # distance by OY axis between neighbour wins\n"\r
- << " [-gr_threshold <int>] # merging similar rects constant\n"\r
- << " [-gamma_corr <int>] # do gamma correction or not\n";\r
+ cout << "\nUsage: hog_gpu\n"\r
+ << " --src <path> # it's image file by default\n"\r
+ << " [--src-is-video <true/false>] # says to interpretate src as video\n"\r
+ << " [--src-is-camera <true/false>] # says to interpretate src as camera\n"\r
+ << " [--make-gray <true/false>] # convert image to gray one or not\n"\r
+ << " [--resize-src <true/false>] # do resize of the source image or not\n"\r
+ << " [--src-width <int>] # resized image width\n"\r
+ << " [--src-height <int>] # resized image height\n"\r
+ << " [--hit-threshold <double>] # classifying plane distance threshold (0.0 usually)\n"\r
+ << " [--scale <double>] # HOG window scale factor\n"\r
+ << " [--nlevels <int>] # max number of HOG window scales\n"\r
+ << " [--win-width <int>] # width of the window (48 or 64)\n"\r
+ << " [--win-stride-width <int>] # distance by OX axis between neighbour wins\n"\r
+ << " [--win-stride-height <int>] # distance by OY axis between neighbour wins\n"\r
+ << " [--gr-threshold <int>] # merging similar rects constant\n"\r
+ << " [--gamma-correct <int>] # do gamma correction or not\n";\r
return 1;\r
}\r
- App app(Settings::Read(argc, argv));\r
- app.RunOpencvGui();\r
+ App app(Args::read(argc, argv));\r
+ app.run();\r
}\r
catch (const Exception& e) { return cout << "Error: " << e.what() << endl, 1; }\r
catch (const exception& e) { return cout << "Error: " << e.what() << endl, 1; }\r
}\r
\r
\r
-Settings::Settings()\r
+Args::Args()\r
{\r
src_is_video = false;\r
+ src_is_camera = false;\r
+ camera_id = 0;\r
+\r
make_gray = false;\r
- resize_src = true;\r
- resize_src_scale = 1.5;\r
+\r
+ resize_src = false;\r
+ resized_width = 640;\r
+ resized_height = 480;\r
+\r
scale = 1.05;\r
nlevels = 13;\r
gr_threshold = 8;\r
hit_threshold = 1.4;\r
+\r
win_width = 48;\r
win_stride_width = 8;\r
win_stride_height = 8;\r
+\r
gamma_corr = true;\r
}\r
\r
\r
-Settings Settings::Read(int argc, char** argv)\r
+Args Args::read(int argc, char** argv)\r
{\r
- cout << "Parsing command args" << endl;\r
-\r
- Settings settings;\r
+ Args args;\r
for (int i = 1; i < argc - 1; i += 2)\r
{\r
string key = argv[i];\r
string val = argv[i + 1];\r
- if (key == "-src") settings.src = val;\r
- else if (key == "-src_is_video") settings.src_is_video = (val == "true"); \r
- else if (key == "-make_gray") settings.make_gray = (val == "true");\r
- else if (key == "-resize_src") settings.resize_src = (val == "true");\r
- else if (key == "-resize_src_scale") settings.resize_src_scale = atof(val.c_str());\r
- else if (key == "-hit_threshold") settings.hit_threshold = atof(val.c_str());\r
- else if (key == "-scale") settings.scale = atof(val.c_str());\r
- else if (key == "-nlevels") settings.nlevels = atoi(val.c_str());\r
- else if (key == "-win_width") settings.win_width = atoi(val.c_str());\r
- else if (key == "-win_stride_width") settings.win_stride_width = atoi(val.c_str());\r
- else if (key == "-win_stride_height") settings.win_stride_height = atoi(val.c_str());\r
- else if (key == "-gr_threshold") settings.gr_threshold = atoi(val.c_str());\r
- else if (key == "-gamma_corr") settings.gamma_corr = atoi(val.c_str()) != 0;\r
- else throw runtime_error((string("Unknown key: ") + key));\r
+ if (key == "--src") args.src = val;\r
+ else if (key == "--src-is-video") args.src_is_video = (val == "true"); \r
+ else if (key == "--src-is-camera") args.src_is_camera = (val == "true"); \r
+ else if (key == "--camera-id") args.camera_id = atoi(val.c_str());\r
+ else if (key == "--make-gray") args.make_gray = (val == "true");\r
+ else if (key == "--resize-src") args.resize_src = (val == "true");\r
+ else if (key == "--src-width") args.resized_width = atoi(val.c_str());\r
+ else if (key == "--src-height") args.resized_height = atoi(val.c_str());\r
+ else if (key == "--hit-threshold") args.hit_threshold = atof(val.c_str());\r
+ else if (key == "--scale") args.scale = atof(val.c_str());\r
+ else if (key == "--nlevels") args.nlevels = atoi(val.c_str());\r
+ else if (key == "--win-width") args.win_width = atoi(val.c_str());\r
+ else if (key == "--win-stride-width") args.win_stride_width = atoi(val.c_str());\r
+ else if (key == "--win-stride-height") args.win_stride_height = atoi(val.c_str());\r
+ else if (key == "--gr-threshold") args.gr_threshold = atoi(val.c_str());\r
+ else if (key == "--gamma-correct") args.gamma_corr = atoi(val.c_str()) != 0;\r
+ else throw runtime_error((string("unknown key: ") + key));\r
}\r
-\r
- cout << "Command args are parsed\n";\r
- return settings;\r
+ return args;\r
}\r
\r
\r
-App::App(const Settings &s)\r
+App::App(const Args& s)\r
{\r
- settings = s;\r
+ args = s;\r
cout << "\nControls:\n"\r
<< "\tESC - exit\n"\r
<< "\tm - change mode GPU <-> CPU\n"\r
<< endl;\r
\r
use_gpu = true;\r
- make_gray = settings.make_gray;\r
- scale = settings.scale;\r
- gr_threshold = settings.gr_threshold;\r
- nlevels = settings.nlevels;\r
- hit_threshold = settings.hit_threshold;\r
- gamma_corr = settings.gamma_corr;\r
+ make_gray = args.make_gray;\r
+ scale = args.scale;\r
+ gr_threshold = args.gr_threshold;\r
+ nlevels = args.nlevels;\r
+ hit_threshold = args.hit_threshold;\r
+ gamma_corr = args.gamma_corr;\r
\r
- if (settings.win_width != 64 && settings.win_width != 48)\r
- settings.win_width = 64;\r
+ if (args.win_width != 64 && args.win_width != 48)\r
+ args.win_width = 64;\r
\r
cout << "Scale: " << scale << endl;\r
+ if (args.resize_src)\r
+ cout << "Source size: (" << args.resized_width << ", " << args.resized_height << ")\n";\r
cout << "Group threshold: " << gr_threshold << endl;\r
cout << "Levels number: " << nlevels << endl;\r
- cout << "Win width: " << settings.win_width << endl;\r
- cout << "Win stride: (" << settings.win_stride_width << ", " << settings.win_stride_height << ")\n";\r
+ cout << "Win width: " << args.win_width << endl;\r
+ cout << "Win stride: (" << args.win_stride_width << ", " << args.win_stride_height << ")\n";\r
cout << "Hit threshold: " << hit_threshold << endl;\r
cout << "Gamma correction: " << gamma_corr << endl;\r
cout << endl;\r
}\r
\r
\r
-void App::RunOpencvGui()\r
+void App::run()\r
{\r
running = true;\r
\r
- Size win_size(settings.win_width, settings.win_width * 2); //(64, 128) or (48, 96)\r
- Size win_stride(settings.win_stride_width, settings.win_stride_height);\r
+ Size win_size(args.win_width, args.win_width * 2); //(64, 128) or (48, 96)\r
+ Size win_stride(args.win_stride_width, args.win_stride_height);\r
\r
vector<float> detector;\r
-\r
- if (win_size == Size(64, 128))\r
+ if (win_size == Size(64, 128)) \r
detector = cv::gpu::HOGDescriptor::getPeopleDetector_64x128();\r
else\r
detector = cv::gpu::HOGDescriptor::getPeopleDetector_48x96();\r
\r
- // GPU's HOG classifier\r
cv::gpu::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, \r
cv::gpu::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr, \r
cv::gpu::HOGDescriptor::DEFAULT_NLEVELS);\r
- gpu_hog.setSVMDetector(detector);\r
-\r
- // CPU's HOG classifier\r
cv::HOGDescriptor cpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9, 1, -1, \r
HOGDescriptor::L2Hys, 0.2, gamma_corr, cv::HOGDescriptor::DEFAULT_NLEVELS);\r
+ gpu_hog.setSVMDetector(detector);\r
cpu_hog.setSVMDetector(detector);\r
\r
#ifdef WRITE_VIDEO\r
cv::VideoWriter video_writer;\r
-\r
video_writer.open("output.avi", CV_FOURCC('x','v','i','d'), 24., cv::Size(640, 480), true);\r
-\r
if (!video_writer.isOpened())\r
throw std::runtime_error("can't create video writer");\r
#endif\r
\r
- // Make endless cycle from video (if src is video)\r
while (running)\r
{\r
VideoCapture vc;\r
Mat frame;\r
\r
- if (settings.src_is_video)\r
+ if (args.src_is_video)\r
{\r
- vc.open(settings.src.c_str());\r
+ vc.open(args.src.c_str());\r
if (!vc.isOpened())\r
- throw runtime_error(string("Can't open video file: " + settings.src));\r
+ throw runtime_error(string("can't open video file: " + args.src));\r
+ vc >> frame;\r
+ }\r
+ else if (args.src_is_camera)\r
+ {\r
+ vc.open(args.camera_id);\r
+ if (!vc.isOpened())\r
+ throw runtime_error(string("can't open video file: " + args.src));\r
vc >> frame;\r
}\r
else\r
{\r
- frame = imread(settings.src);\r
+ frame = imread(args.src);\r
if (frame.empty())\r
- throw runtime_error(string("Can't open image file: " + settings.src));\r
+ throw runtime_error(string("can't open image file: " + args.src));\r
}\r
\r
Mat img_aux, img, img_to_show;\r
// Iterate over all frames\r
while (running && !frame.empty())\r
{\r
- WorkBegin();\r
-\r
- vector<Rect> found;\r
+ workBegin();\r
\r
- // Change format of the image (input must be 8UC3)\r
- if (make_gray)\r
- cvtColor(frame, img_aux, CV_BGR2GRAY);\r
- else if (use_gpu)\r
- cvtColor(frame, img_aux, CV_BGR2BGRA);\r
- else\r
- img_aux = frame;\r
+ // Change format of the image\r
+ if (make_gray) cvtColor(frame, img_aux, CV_BGR2GRAY);\r
+ else if (use_gpu) cvtColor(frame, img_aux, CV_BGR2BGRA);\r
+ else img_aux = frame;\r
\r
// Resize image\r
- if (settings.resize_src)\r
- resize(img_aux, img, Size(int(frame.cols * settings.resize_src_scale), int(frame.rows * settings.resize_src_scale)));\r
- else\r
- img = img_aux;\r
+ if (args.resize_src) resize(img_aux, img, Size(args.resized_width, args.resized_height));\r
+ else img = img_aux;\r
img_to_show = img;\r
\r
gpu_hog.nlevels = nlevels;\r
cpu_hog.nlevels = nlevels;\r
\r
+ vector<Rect> found;\r
+\r
// Perform HOG classification\r
- HogWorkBegin();\r
+ hogWorkBegin();\r
if (use_gpu)\r
{\r
gpu_img = img;\r
- gpu_hog.detectMultiScale(gpu_img, found, hit_threshold, win_stride, Size(0, 0), scale, gr_threshold);\r
+ gpu_hog.detectMultiScale(gpu_img, found, hit_threshold, win_stride, \r
+ Size(0, 0), scale, gr_threshold);\r
}\r
- else\r
- cpu_hog.detectMultiScale(img, found, hit_threshold, win_stride, Size(0, 0), scale, gr_threshold);\r
- HogWorkEnd();\r
+ else cpu_hog.detectMultiScale(img, found, hit_threshold, win_stride, \r
+ Size(0, 0), scale, gr_threshold);\r
+ hogWorkEnd();\r
\r
// Draw positive classified windows\r
for (size_t i = 0; i < found.size(); i++)\r
rectangle(img_to_show, r.tl(), r.br(), CV_RGB(0, 255, 0), 3);\r
}\r
\r
- // Show results\r
- putText(img_to_show, GetPerformanceSummary(), Point(5, 25), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 0, 255), 2);\r
+ putText(img_to_show, "FPS (HOG only): " + hogWorkFps(), Point(5, 25), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2);\r
+ putText(img_to_show, "FPS (total): " + workFps(), Point(5, 65), FONT_HERSHEY_SIMPLEX, 1., Scalar(255, 100, 0), 2);\r
imshow("opencv_gpu_hog", img_to_show);\r
- HandleKey((char)waitKey(3));\r
+ handleKey((char)waitKey(3));\r
\r
- if (settings.src_is_video)\r
- {\r
- vc >> frame;\r
- }\r
+ if (args.src_is_video || args.src_is_camera) vc >> frame;\r
\r
- WorkEnd();\r
+ workEnd();\r
\r
#ifdef WRITE_VIDEO\r
cvtColor(img_to_show, img, CV_BGRA2BGR);\r
}\r
\r
\r
-void App::HandleKey(char key)\r
+void App::handleKey(char key)\r
{\r
switch (key)\r
{\r
}\r
\r
\r
-inline void App::HogWorkBegin() { hog_work_begin = getTickCount(); }\r
+inline void App::hogWorkBegin() { hog_work_begin = getTickCount(); }\r
\r
-\r
-inline void App::HogWorkEnd()\r
+inline void App::hogWorkEnd()\r
{\r
int64 delta = getTickCount() - hog_work_begin;\r
double freq = getTickFrequency();\r
hog_work_fps = freq / delta;\r
}\r
\r
+inline string App::hogWorkFps() const\r
+{\r
+ stringstream ss;\r
+ ss << hog_work_fps;\r
+ return ss.str();\r
+}\r
\r
-inline double App::HogWorkFps() const { return hog_work_fps; }\r
-\r
-\r
-inline void App::WorkBegin() { work_begin = getTickCount(); }\r
\r
+inline void App::workBegin() { work_begin = getTickCount(); }\r
\r
-inline void App::WorkEnd()\r
+inline void App::workEnd()\r
{\r
int64 delta = getTickCount() - work_begin;\r
double freq = getTickFrequency();\r
work_fps = freq / delta;\r
}\r
\r
-\r
-inline double App::WorkFps() const { return work_fps; }\r
-\r
-\r
-inline const string App::GetPerformanceSummary() const\r
+inline string App::workFps() const\r
{\r
stringstream ss;\r
- ss << (use_gpu ? "GPU" : "CPU") << " HOG FPS: " << setiosflags(ios::left) << setprecision(4) <<\r
- setw(7) << HogWorkFps() << " Total FPS: " << setprecision(4) << setw(7) << WorkFps();\r
+ ss << work_fps;\r
return ss.str();\r
}\r