SOL9 Sample: ContourFinder

SOL9 2.0 Samples

1 Screenshot


2 Source code

/*
 * ContourFinder.cpp 
 * Copyright (c) 2015 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 */


//2017/08/25
// This is a simple sample program based on CannyEdgeDetector program and
// the following sample program:
// See: http://docs.opencv.org/3.2.0/df/d0d/tutorial_find_contours.html

#define _CONSOLE_

#include <sol/StringT.h>
#include <sol/LabeledTrackBar.h>
#include <sol/FileDialog.h>
#include <sol/opencv/OpenCVApplicationView.h>
#include <sol/opencv/OpenCVImageView.h>

namespace SOL {

class MainView :public OpenCVApplicationView {

private:
  ///////////////////////////////////////////////
  //Inner classes start.
  class OriginalImageView: public OpenCVImageView{
  private:
    cv::Mat originalImage; 
 
    cv::Mat& getMat()
    {
      return originalImage;
    }
    
    virtual void display()
    {
       show(originalImage);
    }
 
  public:
    OriginalImageView(View* parent, const char* name, Args& args)
    :OpenCVImageView(parent, name, args)
    {
      try {
        const char* filename = (const char*)args.get(XmNimageFileName);
        int imageLoadingFlag = args.get(XmNimageLoadingFlag);

        loadImage(filename, imageLoadingFlag);
 
      } catch (SOL::Exception ex) {
        caught(ex);
      }
    } 

    ~OriginalImageView()
    {
    }
    
    void loadImage(const char* filename, 
                    int imageLoadingFlag= CV_LOAD_IMAGE_COLOR)
    {
      originalImage = readImage(filename, imageLoadingFlag);
      refresh();
    }    
  };

  class DetectedImageView: public OpenCVImageView {
  private:
    cv::Mat originalImage; 
    cv::Mat grayImage; 
    cv::Mat detectedImage; 
    cv::Mat contourImage; 

    //On RNG, See: http://docs.opencv.org/3.2.0/d1/dd6/classcv_1_1RNG.html
    cv::RNG rng;

    cv::Mat& getMat()
    {
      return contourImage;
    }
    
    //We display the scaledImage.
    virtual void display()
    {
      show(contourImage);
    }
 
  public:
    DetectedImageView(View* parent, const char* name, Args& args)
    :OpenCVImageView(parent, name, args)
    ,rng(35791)
    {
      try {
        const char* filename = (const char*)args.get(XmNimageFileName);
        int imageLoadingFlag = args.get(XmNimageLoadingFlag);

        loadImage(filename, imageLoadingFlag);

      } catch (SOL::Exception ex) {
        caught(ex);
      }
    } 

    ~DetectedImageView()
    {
    }
    
    void loadImage(const char* filename, 
                int imageLoadingFlag= CV_LOAD_IMAGE_COLOR)
    {
      originalImage = readImage(filename, imageLoadingFlag);
      detectedImage  = originalImage.clone();
      cv::cvtColor( originalImage, grayImage, COLOR_BGR2GRAY );
      contourImage = grayImage.clone();
    }    

    //The following method is based on the sample code
    // on  http://docs.opencv.org/3.2.0/df/d0d/tutorial_find_contours.html
    void detectEdge(int threshold1, int threshold2)
    {
      //1 Try to detect edges by cv::Canny on grayImage.
      threshold1 = (threshold1/2)*2 + 1;
      threshold2 = (threshold2/2)*2 + 1;

      cv::Canny(grayImage, detectedImage, 
                    (double)threshold1, (double)threshold2);

      std::vector<std::vector<cv::Point> > contours;
      std::vector<cv::Vec4i> hierarchy;

      //2 find contours on the canny edge-detected image  
      cv::findContours(detectedImage, contours, hierarchy, 
             RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0) );

      contourImage = Mat::zeros(detectedImage.size(), CV_8UC3 );

      for( size_t i = 0; i< contours.size(); i++ ) {
     
        cv::Scalar color = cv::Scalar( rng.uniform(0, 255), 
                       rng.uniform(0,255), rng.uniform(0,255) );
        cv::drawContours(contourImage, contours, (int)i, color, 2, 8, 
                      hierarchy, 0, Point() );
      }
      refresh();
    }
  };
  //Inner classes end.
    
private:

  StringT<char>                imageFileName;
  int                          imageLoadingFlag;

  SmartPtr<OriginalImageView>  originalImage;
  SmartPtr<DetectedImageView>  detectedImage;

  int                          threshold1Max;
  int                          threshold1;
  SmartPtr<LabeledTrackBar>    threshold1TrackBar;
  
  int                          threshold2Max;
  int                          threshold2;
  SmartPtr<LabeledTrackBar>    threshold2TrackBar;

  FileDialog                   filedlg;

public:
  void updateCaption()
  {
    char caption[1024];
    sprintf_s(caption, CountOf(caption), "%s - %s", (const char*)imageFileName, 
      getAppName());
    setText(caption);
  }
  
  
  void trackBarScrolled1(Action& action)
  {
    threshold1 = threshold1TrackBar->getPosition();
    threshold2 = threshold2TrackBar->getPosition();
    detectedImage->detectEdge(threshold1, threshold2);
  }

  void trackBarScrolled2(Action& action)
  {
    threshold1 = threshold1TrackBar->getPosition();
    threshold2 = threshold2TrackBar->getPosition();
    
    detectedImage->detectEdge(threshold1, threshold2);
  }


  void openFile(const char* filename)
  {
    try {  
      imageFileName = filename;
      //originalImage->invalidate();
      originalImage->loadImage(filename,  imageLoadingFlag);

      //originalImage->invalidate();
      detectedImage ->loadImage(filename, imageLoadingFlag); 

      threshold1 = threshold1TrackBar->getPosition();
      threshold2 = threshold2TrackBar->getPosition();

      detectedImage->detectEdge(threshold1, threshold2);

      updateCaption();

      //resize(width(), height());
      
      //flush();
      
    } catch (SOL::Exception& ex) {
       caught(ex);
    } 
  }

  void resize(int w, int h)
  {
    int CP_WIDTH = 200;
    int ww =  w-CP_WIDTH;
    if (originalImage && detectedImage ) {
      originalImage-> reshape(0,      0, ww/2,   h);
      detectedImage -> reshape(ww/2,  0 , ww/2-1, h);
     
      threshold1TrackBar -> reshape(ww+1,   0, CP_WIDTH-2, 60);
      threshold2TrackBar -> reshape(ww+1, 100, CP_WIDTH-2, 60);
    }
  }

  void open(Action& action)
  {
    Args ar;
    
    char dir[MAX_PATH] = { 0 };
    if (restoreFileFolder(dir, CountOf(dir))) {
      ar.set(XmNdirectory, dir);
      filedlg.setValues(ar);
    }
    
    try {    
      if(filedlg.open()) {
    
        const char* filename = filedlg.getFileName();
        saveFileFolder(filename);
  
        openFile(filename);
      }
    } catch (Exception& ex) {
      caught(ex);
    }
  }  
  
public:
  MainView(OpenCVApplication& applet, const char* name, Args& args)
  :OpenCVApplicationView(applet, name, args) 
  {
    imageFileName    = "../images/Geometry.png";
    imageLoadingFlag = CV_LOAD_IMAGE_COLOR;

    try {
      Args ar;
      ar.reset();
      ar.set(XmNimageFileName, (const char*)imageFileName);
      ar.set(XmNimageLoadingFlag, imageLoadingFlag);
      originalImage = new OriginalImageView(this, "", ar);

      ar.reset();
      ar.set(XmNimageFileName, (const char*)imageFileName);
      ar.set(XmNimageLoadingFlag, imageLoadingFlag);

      detectedImage   = new DetectedImageView(this, "", ar);

      threshold1Max = 300;
      threshold2Max = 300;

      threshold1 =  50;
      threshold2 = 100;
        
      ar.reset();
      ar.set(XmNminimum, 0);
      ar.set(XmNmaximum,  threshold1Max);
      ar.set(XmNposition,    threshold1); 
      threshold1TrackBar = new LabeledTrackBar(this, "CannyThreshold1", ar);
      threshold1TrackBar->addCallback(XmNtrackBarScrollCallback, this,
        (Callback)&MainView::trackBarScrolled1, NULL);

      ar.reset();
      ar.set(XmNminimum, 0);
      ar.set(XmNmaximum,  threshold1Max);
      ar.set(XmNposition,    threshold2);
      threshold2TrackBar = new LabeledTrackBar(this, "CannyThreshold2", ar);
      threshold2TrackBar->addCallback(XmNtrackBarScrollCallback, this,
        (Callback)&MainView::trackBarScrolled2, NULL);

      detectedImage->detectEdge(threshold1, threshold2);

      ar.reset();

      ar.set(XmNfilter, FileDialog::getImageFilesFilter());
      filedlg.create(this, "OpenFile", ar);
      
      updateCaption();
      
      postResizeRequest();
      
    } catch(SOL::Exception& ex) {
      caught(ex);
    }
  }

  ~MainView()
  {
  }
};

}

//
void main(int argc, char** argv) 
{
  try {
    ModuleFileName module(argv[0]);
    
    const char*  name = module.getAppName();
    
    OpenCVApplication applet(name, argc, argv);

    Args args;
    args.set(XmNwidth,  900);
    args.set(XmNheight, 380);
    MainView view(applet, name, args);
    view.realize();

    applet.run();
    
  } catch (SOL::Exception& ex) {
    caught(ex);
  }
}


Last modified: 2 Dec. 2017

Copyright (c) 2017 Antillia.com ALL RIGHTS RESERVED.