refactored hog, added camera support into hog_sample
authorAlexey Spizhevoy <no@email>
Wed, 29 Dec 2010 15:45:01 +0000 (15:45 +0000)
committerAlexey Spizhevoy <no@email>
Wed, 29 Dec 2010 15:45:01 +0000 (15:45 +0000)
modules/gpu/include/opencv2/gpu/gpu.hpp
samples/gpu/hog.cpp

index 0ac16e2..b7e85a3 100644 (file)
@@ -1178,21 +1178,25 @@ namespace cv
 \r
             size_t getDescriptorSize() const;\r
             size_t getBlockHistogramSize() const;\r
-            double getWinSigma() const;\r
+\r
+            void setSVMDetector(const vector<float>& detector);\r
+            bool checkDetectorSize() const;\r
 \r
             static vector<float> getDefaultPeopleDetector();\r
             static vector<float> getPeopleDetector_48x96();\r
             static vector<float> getPeopleDetector_64x128();\r
-            void setSVMDetector(const vector<float>& detector);\r
-            bool checkDetectorSize() const;\r
 \r
-            void detect(const GpuMat& img, vector<Point>& found_locations, double hit_threshold=0,\r
-                        Size win_stride=Size(), Size padding=Size());\r
+            void detect(const GpuMat& img, vector<Point>& found_locations, \r
+                        double hit_threshold=0, Size win_stride=Size(), \r
+                        Size padding=Size());\r
+\r
             void detectMultiScale(const GpuMat& img, vector<Rect>& found_locations,\r
-                                  double hit_threshold=0, Size win_stride=Size(), Size padding=Size(),\r
-                                  double scale0=1.05, int group_threshold=2);\r
+                                  double hit_threshold=0, Size win_stride=Size(), \r
+                                  Size padding=Size(), double scale0=1.05, \r
+                                  int group_threshold=2);\r
 \r
-            void getDescriptors(const GpuMat& img, Size win_stride, GpuMat& descriptors,\r
+            void getDescriptors(const GpuMat& img, Size win_stride, \r
+                                GpuMat& descriptors,\r
                                 int descr_format=DESCR_FORMAT_COL_BY_COL);\r
 \r
             Size win_size;\r
@@ -1208,6 +1212,7 @@ namespace cv
         protected:\r
             void computeBlockHistograms(const GpuMat& img);\r
             void computeGradient(const GpuMat& img, GpuMat& grad, GpuMat& qangle);\r
+            double getWinSigma() const;\r
 \r
             static int numPartsWithin(int size, int part_size, int stride);\r
             static Size numPartsWithin(Size size, Size part_size, Size stride);\r
index 466f709..ebcdc64 100644 (file)
@@ -12,61 +12,56 @@ using namespace cv;
 \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
@@ -89,26 +84,29 @@ int main(int argc, char** argv)
 {\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
@@ -117,56 +115,63 @@ int main(int argc, char** argv)
 }\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
@@ -178,79 +183,81 @@ App::App(const Settings &s)
          << 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
@@ -259,38 +266,34 @@ void App::RunOpencvGui()
         // 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
@@ -299,17 +302,14 @@ void App::RunOpencvGui()
                 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
@@ -320,7 +320,7 @@ void App::RunOpencvGui()
 }\r
 \r
 \r
-void App::HandleKey(char key)\r
+void App::handleKey(char key)\r
 {\r
     switch (key)\r
     {\r
@@ -382,38 +382,35 @@ void App::HandleKey(char key)
 }\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