I have an interesting problem. Namely like that; I am trying to use std::memcpy function inside by mex function and calling that mex function inside MATLAB like that;
I2 = b_filter(I);
When I copy the whole image, it works well;
plhs[0] = mxCreateDoubleMatrix(mxGetM(plhs[0]), mxGetN(plhs[0]), mxREAL);
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) *mxGetM(plhs[0]) * mxGetN(plhs[0]));
But when I try to copy some part of image
plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
memcpy(mxGetPr(plhs[0]), mxGetPr(prhs[0]), sizeof(double) * 100 * 100);
it doesn't give right image part but gives unmeaningful pixel values.
So what is going on here?
Ha Ha! You've been caught by one of the nastiest of mex file nuances! It's got me before too. Arrays in mex functions are stored in column order not row order, so you:
You still use column-first indexing like in Matlab, though
Try this page too for a nice picture of the ordering.
Finally I would recommend reading this thread to get a better idea behind the difference of C and MATLAB matrix memory being column-ordered.
As explained by @macduff, MATLAB uses a column-major order to store arrays, while C arrays are row-major.
Here is a sample implementation showing how to copy part of a matrix.
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *in, *out;
mwIndex i,j;
mwSize numRows;
/* input checks */
if (nrhs != 1 || nlhs > 1) {
mexErrMsgIdAndTxt("MATLAB:nargchk", "Wrong number of arguments.");
}
if (mxGetNumberOfDimensions(prhs[0])>2 || !mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MATLAB:wrongDims", "Expecting 2D double matrix.");
}
if (mxGetM(prhs[0])<100 || mxGetN(prhs[0])<100) {
mexErrMsgIdAndTxt("MATLAB:wrongDims", "Matrix size must be >= 100x100.");
}
/* extract sub-matrix */
plhs[0] = mxCreateDoubleMatrix(100, 100, mxREAL);
out = mxGetPr(plhs[0]);
in = mxGetPr(prhs[0]);
numRows = mxGetM(prhs[0]);
for(j=0; j<100; j++) {
for(i=0; i<100; i++) {
*out++ = in[i + numRows*j];
}
}
}
And to test this:
x = rand(1000);
y = x(1:100,1:100);
yy = matrix_slice_mex(x);
isequal(y,yy)
You could have also used memcpy
to copy each of the columns (one for-loop instead)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.