OpenCV  4.5.2
Open Source Computer Vision
Structured forest training

Introduction

In this tutorial we show how to train your own structured forest using author's initial Matlab implementation.

Training pipeline

  1. Download "Piotr's Toolbox" from link and put it into separate directory, e.g. PToolbox
  2. Download BSDS500 dataset from link <http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/BSR/> and put it into separate directory named exactly BSR
  3. Add both directory and their subdirectories to Matlab path.
  4. Download detector code from link <http://research.microsoft.com/en-us/downloads/389109f6-b4e8-404c-84bf-239f7cbf4e3d/> and put it into root directory. Now you should have :
    .
    BSR
    PToolbox
    models
    private
    Contents.m
    edgesChns.m
    edgesDemo.m
    edgesDemoRgbd.m
    edgesDetect.m
    edgesEval.m
    edgesEvalDir.m
    edgesEvalImg.m
    edgesEvalPlot.m
    edgesSweeps.m
    edgesTrain.m
    license.txt
    readme.txt
  5. Rename models/forest/modelFinal.mat to models/forest/modelFinal.mat.backup
  6. Open edgesChns.m and comment lines 26–41. Add after commented lines the following:
    shrink=opts.shrink;
    chns = single(getFeatures( im2double(I) ));
  7. Now it is time to compile promised getFeatures. I do with the following code:
    #include <cv.h>
    #include <highgui.h>
    #include <mat.h>
    #include <mex.h>
    #include "MxArray.hpp" // https://github.com/kyamagu/mexopencv
    class NewRFFeatureGetter : public cv::RFFeatureGetter
    {
    public:
    NewRFFeatureGetter() : name("NewRFFeatureGetter"){}
    virtual void getFeatures(const cv::Mat &src, NChannelsMat &features,
    const int gnrmRad, const int gsmthRad,
    const int shrink, const int outNum, const int gradNum) const
    {
    // here your feature extraction code, the default one is:
    // resulting features Mat should be n-channels, floating point matrix
    }
    protected:
    cv::String name;
    };
    MEXFUNCTION_LINKAGE void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    {
    if (nlhs != 1) mexErrMsgTxt("nlhs != 1");
    if (nrhs != 1) mexErrMsgTxt("nrhs != 1");
    cv::Mat src = MxArray(prhs[0]).toMat();
    std::string modelFile = MxArray(prhs[1]).toString();
    NewRFFeatureGetter *pDollar = createNewRFFeatureGetter();
    cv::Mat edges;
    pDollar->getFeatures(src, edges, 4, 0, 2, 13, 4);
    // you can use other numbers here
    plhs[0] = MxArray(edges);
    }
  8. Place compiled mex file into root dir and run edgesDemo. You will need to wait a couple of hours after that the new model will appear inside models/forest/.
  9. The final step is converting trained model from Matlab binary format to YAML which you can use with our ocv::StructuredEdgeDetection. For this purpose run opencv_contrib/ximgproc/tutorials/scripts/modelConvert(model, "model.yml")

How to use your model

Just use expanded constructor with above defined class NewRFFeatureGetter

cv::StructuredEdgeDetection pDollar
= cv::createStructuredEdgeDetection( modelName, makePtr<NewRFFeatureGetter>() );