OZ++ Sample: HOGPeopleDetector






/******************************************************************************  *  * Copyright (c) 2017 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions, and the following disclaimer.  *    * 2. The name of the author may not be used to endorse or promote products  *    derived from this software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  *  *  *  HOGPeopleDetector.cpp  *  *****************************************************************************/ // //2018/04/10 //On cv::HOGDescriptor Struct, see:  https://docs.opencv.org/3.4.1/d5/d33/structcv_1_1HOGDescriptor.html /* //Constructor cv::HOGDescriptor::HOGDescriptor ( Size  _winSize, //Detection window size. Align to block size and block stride. Default value is Size(64,128).    Size  _blockSize,                                //Block size in pixels. Align to cell size. Default value is Size(16,16).    Size  _blockStride,                              //Block stride. It must be a multiple of cell size. Default value is Size(8,8).    Size  _cellSize,                                 //Cell size. Default value is Size(8,8).    int  _nbins,                                     //Number of bins used in the calculation of histogram of gradients. Default value is 9.    int  _derivAperture = 1,                         //not documented ?   double  _winSigma = -1,     int  _histogramNormType = HOGDescriptor::L2Hys,  //histogramNormType    double  _L2HysThreshold = 0.2,                   //L2-Hys normalization method shrinkage.    bool  _gammaCorrection = false,                  //Flag to specify whether the gamma correction preprocessing is required or not.    int  _nlevels = HOGDescriptor::DEFAULT_NLEVELS,  //Maximum number of detection window increases. Default value is 64.    bool  _signedGradient = false                    //Indicates signed gradient will be used or not.   )   ////////////////////////////////////////////////////// Please note the following attributes. Public Attributes  Size  blockSize    Block size in pixels. Align to cell size. Default value is Size(16,16). More... Size  blockStride    Block stride. It must be a multiple of cell size. Default value is Size(8,8). More... Size  cellSize    Cell size. Default value is Size(8,8). More... int  derivAperture    not documented More... float  free_coef    not documented More... bool  gammaCorrection    Flag to specify whether the gamma correction preprocessing is required or not. More... int  histogramNormType    histogramNormType More... double  L2HysThreshold    L2-Hys normalization method shrinkage. More... int  nbins    Number of bins used in the calculation of histogram of gradients. Default value is 9. More... int  nlevels    Maximum number of detection window increases. Default value is 64. More... UMat  oclSvmDetector    coefficients for the linear SVM classifier used when OpenCL is enabled More... bool  signedGradient    Indicates signed gradient will be used or not. More... std::vector< float >  svmDetector    coefficients for the linear SVM classifier. More... double  winSigma    Gaussian smoothing window parameter. More... Size  winSize    Detection window size. Align to block size and block stri  */ /* train_HOG.cpp See also: https://docs.opencv.org/3.4.1/d5/d77/train_HOG_8cpp-example.html#a34 */ #include <es++/Pair.h> #include <es++/gtkmm-3.0/Application.h> #include <es++/gtkmm-3.0/Label.h> #include <es++/gtkmm-3.0/LabeledTrackBar.h> #include <es++/gtkmm-3.0/FileOpenDialog.h> #include <es++/opencv-3.0/OpenCVMainView.h> #include <es++/opencv-3.0/OpenCVScrolledImageView.h> #include <es++/opencv-3.0/OpenCVScaleComboBox.h> using namespace Gtk; namespace Es { class MainView :public Es::OpenCVMainView { private:    typedef enum {     DEFAULT      = 0,     DAIMLER      = 1,     USER_DEFINED = 2   } HOG_TYPE;      private:   ///////////////////////////////////////////////////////    //Inner classes start.   class OriginalImageView :public Es::OpenCVScrolledImageView {   public:     OriginalImageView()     {     }         void rescale(int scaling_ratio)     {       OpenCVScrolledImageView::scaleImage(scaling_ratio);     }   };   class DetectedImageView :public Es::OpenCVScrolledImageView {   private:     cv::Mat gray_image;     cv::Mat detected_image;   public:     DetectedImageView()     {     }     void loadImage(const std::string& filename,          int imageLoadingFlag= CV_LOAD_IMAGE_COLOR,                 int scaling_ratio=100)     {       OpenCVScrolledImageView::loadImage(filename, imageLoadingFlag,                                 scaling_ratio);         cv::Mat& original_image = getOriginalImage();      //1 Convert it to a gray image.       cv::cvtColor(original_image, gray_image, COLOR_BGR2GRAY );       //2 Apply equalizeHist to the gray image.       cv::equalizeHist(gray_image, gray_image);       detected_image  = original_image.clone();       scaleImage(detected_image, scaling_ratio);     }         void clear(int scalingRatio)     {       cv::Mat& original_image = getOriginalImage();       cv::Mat image = original_image.clone();       detected_image = image;       scaleImage(detected_image, scalingRatio);       refresh();     }     void detect(HOG_TYPE descriptor,int scaling_ratio)     {       cv::Mat& original_image = getOriginalImage();       detected_image = original_image.clone();       //Please refer the method size_t HOGDescriptor::getDescriptorSize() const in opencv-3.4.1/module/objdetect/src/hog.cpp       //Note the following restrictions on blockSize, winSize, blockStride and cellSize:       // (blockSize.width % cellSize.width == 0 &&       //  blockSize.height % cellSize.height == 0);       //((winSize.width - blockSize.width) % blockStride.width == 0 &&        // (winSize.height - blockSize.height) % blockStride.height == 0)               cv::HOGDescriptor hog ;          switch(descriptor) {       case DEFAULT:         hog.winSize     = cv::Size(64,128);         hog.blockSize   = cv::Size(16, 16);         hog.blockStride = cv::Size( 8,  8);         hog.cellSize    = cv::Size( 8,  8);         hog.nbins       = 9;         hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());          break;                case DAIMLER:         hog.winSize     = cv::Size(48, 96);         hog.blockSize   = cv::Size(16, 16);         hog.blockStride = cv::Size( 8,  8);         hog.cellSize    = cv::Size( 8,  8);         hog.nbins       = 9;         hog.setSVMDetector(cv::HOGDescriptor::getDaimlerPeopleDetector());          break;                case USER_DEFINED:         hog.winSize     = cv::Size(32,64);         hog.blockSize   = cv::Size( 8, 8);         hog.blockStride = cv::Size( 4, 4);         hog.cellSize    = cv::Size( 4, 4);         hog.nbins       = 9;         hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());          break;       }          std::vector<cv::Rect> people;       hog.detectMultiScale(gray_image, people);              for (std::vector<cv::Rect>::const_iterator it = people.begin();                           it != people.end(); ++it) {         cv::Rect r = *it;         cv::rectangle(detected_image, r.tl(), r.br(), CV_RGB(255, 0, 0), 3);       }             scaleImage(detected_image, scaling_ratio);     }     void rescale(int scaling_ratio)     {       OpenCVScrolledImageView::scaleImage(detected_image, scaling_ratio);     }   };   // Inner classes end.   ///////////////////////////////////////////////////////    Es::Label              filepath;   Es::HorizontalLayout   horiz_layout;   Es::VerticalLayout     control_pane;   OriginalImageView      original_image;   DetectedImageView      detected_image;   int                    loading_flag;   Es::OpenCVScaleComboBox scale_combobox;   int                    blockSize;   Es::LabeledTrackBar    blockSize_trackbar;      int                    ksize;   Es::LabeledTrackBar    ksize_trackbar;   HOG_TYPE               descriptor_index;   Es::LabeledComboBox    descriptor_combobox;   int                    scaling_ratio;  //Percentage.   static const int       CONTROLPANE_WIDTH = 200;   std::string            filename;     Es::FileOpenDialog     file_dialog; public:   //////////////////////////////////////////////   //Constructor   //   MainView(Es::Application& applet,            std::string&      name,           Es::Args&         args)   :OpenCVMainView(applet, name, args)   ,scaling_ratio(100)  //100%   ,file_dialog(*this, Es::FileOpenDialog::IMAGE_FILES)   {     int w = (int)args.get(XmNwidth);     int h = (int)args.get(XmNheight);     int ratio = (int)args.get(XmNscalingRatio);     scaling_ratio = OpenCVImageView::validateScale(ratio);     Es::MainLayout& main_layout = get_main_layout();     main_layout.pack_start(filepath, FALSE, FALSE, 0);     main_layout.pack_start(horiz_layout);     filename = "../../images/Pedestrian.png";     filepath.set_label(filename);     int ww = (w - CONTROLPANE_WIDTH)/2;     filepath.set_size_request(w, 30);     original_image.set_size_request(ww, h);     detected_image.set_size_request(ww, h);     control_pane.set_size_request( CONTROLPANE_WIDTH, h);     horiz_layout.pack_start(original_image);     horiz_layout.pack_start(detected_image);     horiz_layout.pack_start(control_pane, FALSE, FALSE, 0);     scale_combobox.set_selection(scaling_ratio);     scale_combobox.set_changed_callback(              sigc::mem_fun(*this, &MainView::scale_changed) );     descriptor_index = DEFAULT;     const char* types[] = {        "DEFAULT",        "DAIMLER",        "USER_DEFINED",     };     descriptor_combobox.append_items(types, CountOf(types));     descriptor_combobox.set_label("Descriptor");     descriptor_combobox.set_active_text(types[0]);     descriptor_combobox.set_changed_callback(              sigc::mem_fun(*this, &MainView::descriptor_changed) );     control_pane.set_spacing(20);     control_pane.pack_start(scale_combobox, Gtk::PACK_SHRINK);     control_pane.pack_start(descriptor_combobox, Gtk::PACK_SHRINK);     loading_flag = IMREAD_COLOR;     original_image.loadImage(filename, loading_flag, scaling_ratio);     detected_image.loadImage(filename, loading_flag, scaling_ratio);     detected_image.detect(DEFAULT,                           scaling_ratio);     show_all();   }   void scale_changed()   {     std::string scale = scale_combobox.get_active_text();     printf("scale_changed %s\n", scale.c_str());     scaling_ratio = scale_combobox.get_selection();     original_image.rescale(scaling_ratio);     detected_image.rescale(scaling_ratio);   }   void descriptor_changed()   {    const Pair<const char*, HOG_TYPE> types[] = {        {"DEFAULT", DEFAULT},        {"DAIMLER", DAIMLER},        {"USER_DEFINED", USER_DEFINED},     };     std::string type = descriptor_combobox.get_active_text();     for (int i = 0; i<CountOf(types); i++) {       if (strcmp(type.c_str(), types[i].first) == 0) {         descriptor_index = types[i].second;         break;       }     }     detected_image.detect(descriptor_index,                           scaling_ratio);   }   void file_open()   {     int rc = file_dialog.popup();     if (rc == Gtk::RESPONSE_OK) {       const std::string filename = file_dialog.get_filename();       filepath.set_label(filename);       original_image.loadImage(filename, loading_flag, scaling_ratio);       detected_image.loadImage(filename, loading_flag, scaling_ratio);       detected_image.detect(DEFAULT,                           scaling_ratio);     }   } }; } int main(int argc, char** argv) {   Es::Environment env;   try {     std::string name = argv[0];     Es::Application applet(argc, argv);     Es::Args args;     args.set(XmNx, 20);     args.set(XmNy, 40);     args.set(XmNwidth, 900);     args.set(XmNheight, 400);     args.set(XmNscalingRatio, 60); //60%     Es::MainView mainv(applet, name, args);     mainv.show();     applet.run(mainv);   } catch (Es::Exception& ex) {     caught(ex);   } catch (...) {     printf("Get exception \n");   }   return 0; }