OZ++ Sample: CustomYoloObjectDetector








/******************************************************************************  *  * Copyright (c) 2019 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.  *  *  *  CustomYoloObjectDetector.cpp  *  *****************************************************************************/ //2019/06/09 //#define OPENCV #include <opencv2/stitching.hpp> #include <oz++/motif/Label.h> #include <oz++/motif/RowColumn.h> #include <oz++/motif/LabeledComboBox.h> #include <oz++/motif/LabeledTrackBar.h> #include <oz++/motif/DropdownScaler.h> #include <oz++/opencv/OpenCVMainView.h> #include <oz++/opencv/OpenCVScrolledImageView.h> #include <oz++/motif/FileOpenDialog.h> #include <oz++/motif/ScrolledTableView.h> #include <oz++/ConfigParser.h> #include <oz++/yolov3/Detector3.h> #include <oz++/yolov3/DetectedObjectList.h> namespace OZ { class MainView :public OpenCVMainView {     private:   ///////////////////////////////////////////////   class DetectedImageView: public OpenCVScrolledImageView {   private:     cv::Mat originalImage;      cv::Mat scaledImage;          virtual void display()     {        show(scaledImage);     }     public:     DetectedImageView(View* parent, const char* name, Args& args)     :OpenCVScrolledImageView(parent, name, args)     {       try {         const char* filename = (const char*)args.get(XmNimageFileName);         int imageLoadingFlag = args.get(XmNimageLoadingFlag);         int scalingRatio = (int)args.get(XmNimageScalingRatio);         loadImage(filename, imageLoadingFlag, scalingRatio);         } catch (OZ::Exception ex) {         caught(ex);       }     }      ~DetectedImageView()     {     }          void loadImage(const char* filename,          int imageLoadingFlag= CV_LOAD_IMAGE_COLOR,                 int scalingRatio=100)     {       originalImage = readImage(filename, imageLoadingFlag);       scaleImage(originalImage, scaledImage, scalingRatio);       refresh();     }         void setImage(cv::Mat& image, int scalingRatio=100 )     {       originalImage = image;       rescale(scalingRatio);     }       void rescale(int scalingRatio)     {       scaledImage.release();       scaleImage(originalImage, scaledImage, scalingRatio);     }   };      private:   std::string         imageFile;   std::string         csv_filename;   int                 imageLoadingFlag = CV_LOAD_IMAGE_COLOR;   int                 imageScalingRatio =80; //percentage    ConfigParser        parser;   SmartPtr<Detector3> detector;   std::string         darknet_root;   std::string         cfg_filename;   std::string         coco_filename;   std::string         weight_filename;   SmartPtr<DetectedImageView>   detectedImage;   SmartPtr<Form>                controlPane;   SmartPtr<DetectedObjectList>  objectList;   SmartPtr<RowColumn>        topPane;   SmartPtr<Label>            label;   SmartPtr<DropdownScaler>   scaleComboBox;   SmartPtr<PushButton>       reloadButton;   SmartPtr<PushButton>       detectButton;     SmartPtr<FileOpenDialog>   fileDialog; public:   void cancel(Action& action)   {     fileDialog->popdown();   }   void fileOpen(Action& action)   {     fileDialog->popup();   }   void scaleChanged(Action& action)   {     int val = scaleComboBox->getScale();     if (val > 0 && imageScalingRatio != val) {       imageScalingRatio = val;       detectedImage -> rescale(imageScalingRatio);      }   }     void updateTitle(const char* filename)   {      std::string appname = getAppName();      std::string title = filename;      title += std::string(" - ");      title += appname;       setTitle(title.c_str());   }   void ok(Action& action)   {     try {         imageFile  = fileDialog->getFileName();       const char* filename = (const char*)imageFile.c_str();         printf("filename: %s\n", filename);       fileDialog->popdown();            detectedImage ->loadImage(filename, imageLoadingFlag, imageScalingRatio);       detectedImage->unmap();       detectedImage->map();       csv_filename = createCSVFilename(imageFile);       //resize(width(), height());       updateTitle(filename);       flush();     } catch (OZ::Exception& ex) {        caught(ex);     }    }   void resize(Dimension w, Dimension h)   {     int CP_WIDTH = 330;     int LB_HEIGHT = 30;     int ww =  w-CP_WIDTH;     int hh = h - LB_HEIGHT;          if (topPane && detectButton && detectedImage && controlPane ) {       detectButton->get(XmNheight, LB_HEIGHT);       hh = h - LB_HEIGHT -15;       detectedImage -> reshape(0, LB_HEIGHT+5, ww-2, hh-30);             controlPane  -> reshape(ww+1, LB_HEIGHT+5, CP_WIDTH-4, hh-30);     }     flush();   }   void reload(Action& event)   {     detectedImage -> loadImage(imageFile.c_str(),                 imageLoadingFlag,                 imageScalingRatio);   }   std::string createCSVFilename(std::string& filename)   {     std::string csv_fname = filename;     auto pos = filename.rfind("/");     if (pos != std::string::npos) {        std::string nameonly= filename.substr(pos+1);       csv_fname = std::string("./") + nameonly + std::string(".csv");        printf("csv_filename %s\n", csv_fname.c_str());     }     return csv_fname;   }   void detect(Action& event)   {     image timage = detector->detect_image(imageFile.c_str(), csv_filename.c_str());     cv::Mat mat = detector->image_to_mat(timage);     cv::Mat mbgr;     cv::cvtColor(mat, mbgr, cv::COLOR_RGB2BGR);     free_image(timage);     detectedImage->setImage(mbgr, imageScalingRatio);     TableView* tablev = objectList->getTableView();     tablev->removeAllItems();     tablev->readCSVFile(csv_filename);   } public:   MainView(OpenCVApplication& applet, const char* name, Args& args)   :OpenCVMainView(applet, name, args)    {     imageScalingRatio = 80;     char defaultScale[20] = {0};     sprintf(defaultScale, "%d%%", imageScalingRatio);     printf("%s¥n", defaultScale);     imageLoadingFlag = CV_LOAD_IMAGE_COLOR;     std::string config = "./CustomYoloObjectDetector.ini";     parser.parse(config);     darknet_root    = parser.getString("DARKNET_ROOT", "filename");     cfg_filename    = parser.getString("CFG_FILE", "filename");     coco_filename   = parser.getString("COCO_FILE", "filename");     weight_filename = parser.getString("WEIGHT_FILE", "filename");     BulletinBoard* bboard = getBulletinBoard();     imageFile = "../../images/JRShinjukuStation.2.jpg";     csv_filename = createCSVFilename(imageFile);     // Create a instance oF OZ::Detector3.     detector = new OZ::Detector3(darknet_root, cfg_filename, weight_filename, coco_filename);     try {       Args ar;       ar.set(XmNx, 0);       ar.set(XmNy, 0);       ar.set(XmNmarginHeight, 1);       ar.set(XmNmarginWidth, 1);       ar.set(XmNorientation, XmHORIZONTAL);       ar.set(XmNspacing, 20);       topPane = new RowColumn(bboard, "", ar);       ar.reset();       label = new Label(topPane, "Scale", ar);       ar.reset();       ar.set(XmNdefaultScale, defaultScale);       scaleComboBox = new DropdownScaler(topPane, "", ar);       scaleComboBox->addCallback(XmNselectionCallback, this,         (Callback)&MainView::scaleChanged, NULL);       ar.set(XmNx, 0);       ar.set(XmNy, 0);       ar.set(XmNalignment, XmALIGNMENT_BEGINNING);        reloadButton = new PushButton(topPane, " Reload ", ar);       reloadButton->addCallback(XmNactivateCallback, this,                  (Callback)&MainView::reload, NULL);       ar.reset();        ar.set(XmNx, 120);       ar.set(XmNy, 0);       ar.set(XmNalignment, XmALIGNMENT_BEGINNING);        detectButton = new PushButton(topPane, " Detect ", ar);       detectButton->addCallback(XmNactivateCallback, this,                  (Callback)&MainView::detect, NULL);       updateTitle((const char*)imageFile.c_str());       ar.reset();       ar.set(XmNimageFileName, imageFile.c_str());       ar.set(XmNimageLoadingFlag, imageLoadingFlag);       ar.set(XmNimageScalingRatio, imageScalingRatio);       detectedImage   = new DetectedImageView(bboard, "", ar);       ar.reset();       controlPane = new Form(bboard, "", ar);       ar.reset();       objectList = new DetectedObjectList(controlPane, "objectlist", ar);       ar.reset();       fileDialog = new FileOpenDialog(this, "FileOpenDialog", ar);       fileDialog  -> getOkButton()                   -> addCallback(XmNactivateCallback, this,                           (Callback)&MainView::ok, NULL);        sendConfigureEvent();      } catch(OZ::Exception& ex) {       caught(ex);     }   }   ~MainView()   {   } }; } // int main(int argc, char** argv)  {   try {     const char*  appclass = argv[0];     OpenCVApplication applet(appclass, argc, argv);     Args args;     args.set(XmNwidth,  1000);     args.set(XmNheight, 480);     MainView view(applet, appclass, args);     view.realize();     applet.run();        } catch (OZ::Exception& ex) {     caught(ex);   }   return 0; }