Reputation: 902
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
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
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