Darkmoor
Darkmoor

Reputation: 902

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];
        }
    }

Upvotes: 0

Views: 1335

Answers (2)

Vuwox
Vuwox

Reputation: 2359

Into your mex function do this :

plhs[0] = valueStruct(Test,Test2);

Where ValueStruct is a function

mxArray* valueStruct(const double& d,const double& d2)
{
    mxArray* p = mxCreateStructMatrix(1,1,2,_fieldnames);

    if (!p)
        mexErrMsgIdAndTxt("error","Allocation error");

    mxSetField(p,0,"d",mxArray(d));
    mxSetField(p,0,"d2",mxArray(d2));
    return p;
}

You can refer to mxCreateStructMatrix documentation for more informations.

And for mxSetField.

For an example, You can refer to mexopencv that create struct with his mxArray class where you can get here.

Upvotes: 0

Shai
Shai

Reputation: 114786

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

Upvotes: 1

Related Questions