Search code examples
c++copencvmex

How to return a matrix structure from a mex function?


I have a struct that defines a 3d array, the size is known:

struct uchar3
{
  unsigned char x, y, z;
};

and I want to return it via mex function in order to use it in matlab like a three dimensional array, like an image. How can this be done?

EDIT:

This is apart of the function I use.

foo(uchar3 **imagePtr, Mat Im){
unsigned char *cvPtr = Im.ptr<unsigned char>(0);
    for (size_t i = 0; i < Im.rows * Im.cols; ++i) {
        (*imagePtr)[i].x = cvPtr[3 * i + 0];
        (*imagePtr)[i].y = cvPtr[3 * i + 1];
        (*imagePtr)[i].z = cvPtr[3 * i + 2];
    }
}

Shai's code:

cv::Mat imageRGB;
    cv::cvtColor(OutPutMat, imageRGB, CV_BGR2RGB);

    // uc3 is populated here 
    mwSize sz[3];
    sz[0] = imageRGB.rows; // matlab is row first
    sz[1] = imageRGB.cols;
    sz[2] = 3;
    plhs[0] = mxCreateNumericArray( 3, sz, mxDOUBLE_CLASS, // create double array, you can change the type here
        mxREAL ); // create real matrix
    float *cvPtr = imageRGB.ptr<float>(0);
    float* p = (float*)mxGetData(plhs[0]); // get a pointer to actual data
    for ( size_t y = 0 ; y < imageRGB.rows ; y++ ) {
        for ( size_t x = 0; x < imageRGB.cols ; x++ ) {
            int i = y * imageRGB.cols + x; // opencv is col first
            p[ x * imageRGB.rows + y ] = cvPtr[3 * i + 0];
            p[ imageRGB.cols * imageRGB.rows + x * imageRGB.rows + y ] = cvPtr[3 * i + 1];
            p[ 2*imageRGB.cols * imageRGB.rows + x * imageRGB.rows + y ] = cvPtr[3 * i + 2];
        }
    }

Solution

  • You need to use mxCreateNumericArray

    uchar3 uc3;  
    // uc3 is populated here 
    mwSize sz[3];
    sz[0] = Im.rows; // matlab is row first
    sz[1] = Im.cols;
    sz[2] = 3;
    mxArray* pOut = mxCreateNumericArray( 3, sz, mxDOUBLE_CLASS // create double array, you can change the type here
                                          mxREAL ); // create real matrix
    double* p = (double*)mxGetData(pOut); // get a pointer to actual data
    for ( size_t y = 0 ; y < Im.rows ; y++ ) {
        for ( size_t x = 0; x < Im.cols ; x++ ) {
            int i = y * Im.cols + x; // opencv is col first
            p[ x * Im.rows + y ] = cvPtr[3 * i + 0];
            p[ Im.cols*Im.rows + x * Im.rows + y ] = cvPtr[3 * i + 1];
            p[ 2*Im.cols*Im.rows + x * Im.rows + y ] = cvPtr[3 * i + 2];
        }
    }
    // set one of your mexFunction's outputs to pOut