kyamagu / mexopencv

Collection and a development kit of matlab mex functions for OpenCV library
http://kyamagu.github.io/mexopencv
Other
658 stars 318 forks source link

Corrupt string printed #389

Closed munum closed 6 years ago

munum commented 6 years ago

Hi

I'm working with this mex function:

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();
    cv::ximgproc::SuperpixelSLIC *test = cv::ximgproc::createSuperpixelSLIC(src);
}

I get the following error:

Unexpected Standard exception from MEX file.
What() is:/Volumes/Documents/openCV/modules/imgproc/src/filter.cpp:3741: error: (-213)
Unsupported combination of buffer format (=6), and destination format (=5) in function
getLinearColumnFilter

The line that's causing the error is cv::ximgproc::SuperpixelSLIC *test = cv::ximgproc::createSuperpixelSLIC(src); so I wonder if src is created/converted properly.

amroamroamro commented 6 years ago

re: RFFeatureGetter

Ignoring the errors there in your c++ code, I'm confused, what are you trying to do here?

Do you want to use the StructuredEdgeDetection class in MATLAB? If so, it's already exposed in mexopencv and you can use it directly. There's a pretrained model provided by opencv model.yml.gz you can load. See this demo:

Or are you trying to train your own model?

If that's the case, I gotta say the tutorial is misleading in the sense that opencv doesn't even implement the training part, and you must do so in MATLAB using the "Structured Edge Detection Toolbox" by Piotr Dollar. In doing so, you don't need either opencv or mexopencv; You just need a feature extraction function, either the existing one in the toolbox edgesChns or creating your own (i.e getFeatures), whether it's written in pure MATLAB or in C++ as a MEX-function. I guess mexopencv was used there only for its MxArray being a helper class, not for its role as an opencv wrapper for MATLAB...

re: SuperpixelSLIC

Same thing, you don't have to write MEX-files yourself, we already expose superpixel classes in mexopencv. See this demo for an example:

munum commented 6 years ago

@amroamroamro Indeed, I'm trying to train my own model and trying to get getFeatures() to work. Nonetheless, re SuperpixelSLIC, if createSuperpixelSLIC() is used in a MEX-function, isn't the way I did it correct? Since the argument is already a Mat, it shouldn't be giving an error - right? I just wonder if it's somehow upset with the resulting Mat object returned by MxArray().toMat().

amroamroamro commented 6 years ago

Indeed, I'm trying to train my own model.

ok. did you implemented your own feature detector function? or are you going to use opencv's implementation? namely this: https://github.com/opencv/opencv_contrib/blob/master/modules/ximgproc/src/structured_edge_detection.cpp#L348-L394

Here's how you can use opencv's implementation:

getFeatures.cpp

#include "mexopencv.hpp"
#include "opencv2/ximgproc.hpp"
using namespace std;
using namespace cv;
using namespace cv::ximgproc;

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    // check the number of arguments
    nargchk(nrhs == 2 && nlhs <= 1);

    // arguments vector
    vector<MxArray> rhs(prhs, prhs + nrhs);

    // inputs (image and options structure)
    Mat src(rhs[0].toMat(CV_32F)),
        features;
    int gnrmRad  = rhs[1].at("normRad").toInt();   // 4
    int gsmthRad = rhs[1].at("grdSmooth").toInt(); // 0
    int shrink   = rhs[1].at("shrink").toInt();    // 2
    int outNum   = rhs[1].at("nChns").toInt();     // 13
    int gradNum  = rhs[1].at("nOrients").toInt();  // 4

    // extracts feature
    Ptr<RFFeatureGetter> obj = createRFFeatureGetter();
    obj->getFeatures(src, features, gnrmRad, gsmthRad, shrink, outNum, gradNum);

    // output
    plhs[0] = MxArray(features);
}

and here's the modified edgesChns function:

edgesChns.m

function [chnsReg, chnsSim] = edgesChns(I, opts)
    %EDGESCHNS  Compute features for structured edge detection.

    % call our MEX-function
    chns = getFeatures(im2single(I), opts);

    chnSm = opts.chnSmooth/opts.shrink;
    if (chnSm>1), chnSm = round(chnSm); end
    simSm = opts.simSmooth/opts.shrink;
    if (simSm>1), simSm = round(simSm); end

    chnsReg = convTri(chns, chnSm);
    chnsSim = convTri(chns, simSm);
end
amroamroamro commented 6 years ago

re: SuperpixelSLIC

You're using the API incorrectly, createSuperpixelSLIC returns a smart pointer, not a raw one! See the docs: https://docs.opencv.org/3.3.1/df/d6c/group__ximgproc__superpixel.html#gacf29df20eaca242645a8d3a2d88e6c06

Ptr<SuperpixelSLIC> cv::ximgproc::createSuperpixelSLIC (InputArray image, int algorithm=SLICO, int region_size=10, float ruler=10.0f)

Also did you read the note there about the expected input...

For enhanced results it is recommended for color images to preprocess image with little Gaussian blur using a small 3 x 3 kernel and additional conversion into CIELAB color space

The error means you're passing an image with the wrong type..

munum commented 6 years ago

I had to reinstall Matlab and it's fixed now. I also had to rebuild opencv for some reason.

amroamroamro commented 6 years ago

PS: I added RFFeatureGetter::getFeatures in latest mexopencv (#390), exposed as a static function. So now in edgesChns.m, you can just write the following without creating your own mex-file:

function [chnsReg, chnsSim] = edgesChns(I, opts)
    chns = cv.StructuredEdgeDetection.getFeatures(im2single(I), opts);
    % ... the rest
end