From: Michael on
I am currently implementing some image processing operation that needs to be framed by two nested for-loops running over all columns and rows of the image.

Due to the slowness of nested for-loops in MATLAB I decided to code this problem using the MEX interface. I do know how to set up a mexFunction and how to pass input and output arguments between MATLAB and the mexFunction.

During the loop, I examine certain neighborhoods around the pixel that's actually adressed by the loop variables. Basically, I want to store the values of the neighborhood pixels in a vector, so that I can calculate statistical stuff like mean, median and variance of the neighborhood. In the end, I want to compare the statistics of several possible neighborhoods to determine the new value of the center pixel.

Anyway. Due to the fact there exist no pre-implemented mean, median, variance etc. functions in C/C++, I want to use the corresponding MATLAB functions, which can be adressed by mexCallMATLAB from a mexFunction. Unfortunately I haven't figured out how to interchange information between MATLAB and MEX/C cleanly.

Here's some example code:
#include <math.h>
#include "mex.h"
#include "matrix.h"

void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
int rows, cols;
float* image_in;
float* image_out;
float* ppix;
float* pmean;
mwSize ndim;
const mwSize *dims;
mxArray *pix;
mxArray *mean;

rows = (int)mxGetM(prhs[0]);
cols = (int)mxGetN(prhs[0]);

image_in = mxGetData(prhs[0]);

ndim = mxGetNumberOfDimensions(prhs[0]);
dims = mxGetDimensions(prhs[0]);

plhs[0] = mxCreateNumericArray(ndim, dims, mxSINGLE_CLASS, mxREAL);
image_out = mxGetData(plhs[0]);

pix = mxCreateNumericMatrix(9, 1, mxSINGLE_CLASS, mxREAL);
ppix = mxGetData(pix);

mean = mxCreateNumericMatrix(9, 1, mxSINGLE_CLASS, mxREAL);
pmean = mxGetData(pix);

for(j = 0; j < cols; j++) // loop over cols
{
for(i = 0; i < rows; i++) // loop over rows
{
ppix[0] = image_in[(rows*j-1)+i-1];
ppix[1] = image_in[(rows*j-1)+i];
ppix[2] = image_in[(rows*j-1)+i+1];
ppix[3] = image_in[(rows*j)+i-1];
ppix[4] = image_in[(rows*j)+i];
ppix[5] = image_in[(rows*j)+i+1];
ppix[6] = image_in[(rows*j+1)+i-1];
ppix[7] = image_in[(rows*j+1)+i];
ppix[8] = image_in[(rows*j+1)+i+1];

mexCallMATLAB(1, &mean, 1, &pix, "mean");
}
}
return;
}

I know this piece of code is incomplete, but I just wanted to show in what direction my problem goes. I want to calculate the variance and the median the same way I tried to calculate the mean. And I want to store the respective values in vectors/arrays with length according to the number of neighborhoods, e.g. 9.
Then I want to compare the values using MATLAB's built-in min and max functions.

Can anybody help unravel the snarl in my head coming from all those pointers, C arrays, MATLAB arrays etc. pp.?
From: James Tursa on
"Michael " <michael.schmittNOSPAM(a)bv.tum.de> wrote in message <hr4aam$9n5$1(a)fred.mathworks.com>...
>
> Here's some example code:
> #include <math.h>
> #include "mex.h"
> #include "matrix.h"

FYI, you don't really need the #include "matrix.h" since that is already included in the mex.h file.

> int rows, cols;
:
> rows = (int)mxGetM(prhs[0]);
> cols = (int)mxGetN(prhs[0]);

Why are you casting these results to int? Why not just declare rows and cols as mwSize and put the results of mxGetM and mxGetN into rows and cols directly without casting?

> mean = mxCreateNumericMatrix(9, 1, mxSINGLE_CLASS, mxREAL);
> pmean = mxGetData(pix);
:
> mexCallMATLAB(1, &mean, 1, &pix, "mean");

"mean" is going to be an output of the mexCallMATLAB call, it is not going to be something you as a programmer create ahead of time. Delete the above two lines creating mean and getting its data pointer.

James Tursa
From: James Tursa on
"Michael " <michael.schmittNOSPAM(a)bv.tum.de> wrote in message <hr4aam$9n5$1(a)fred.mathworks.com>...
>
> for(j = 0; j < cols; j++) // loop over cols
> {
> for(i = 0; i < rows; i++) // loop over rows
> {
> ppix[0] = image_in[(rows*j-1)+i-1];
> ppix[1] = image_in[(rows*j-1)+i];
> ppix[2] = image_in[(rows*j-1)+i+1];
> ppix[3] = image_in[(rows*j)+i-1];
> ppix[4] = image_in[(rows*j)+i];
> ppix[5] = image_in[(rows*j)+i+1];
> ppix[6] = image_in[(rows*j+1)+i-1];
> ppix[7] = image_in[(rows*j+1)+i];
> ppix[8] = image_in[(rows*j+1)+i+1];

Also, you are not doing your edge calculations correctly. e.g., for i==0 and j==0 you get the following:

ppix[0] = image_in[(rows*0-1)+0-1];

which works out to:

ppix[0] = image_in[-2];

which of course is going to access invalid memory. Similar comments apply for the other edges. So you need account for these edge cases in your code.

James Tursa
From: Michael on
Thank you for your advice, James!

I know about the indexing error in the edge case, but for the moment I was more interested in the functionality of the MEX/MATLAB interaction.

If I am not supposed to create any mean vector in advance, how do I work with the output of "mexCallMATLAB(1, &mean, 1, &pix, "mean");" within the MEX file? And how can I give an array created from several such calls back to MATLAB? That's the core of my problem.

Concerning the mwSize topic: I tried to declare rows and cols as mwSize like you suggested, but my compiler (Visual Studio) then gives me a warning for converting "size_t" to "mwSize", which might lead to some data loss...
From: James Tursa on
"Michael " <michael.schmittNOSPAM(a)bv.tum.de> wrote in message <hr63gk$8ts$1(a)fred.mathworks.com>...
>
> If I am not supposed to create any mean vector in advance, how do I work with the output of "mexCallMATLAB(1, &mean, 1, &pix, "mean");" within the MEX file? And how can I give an array created from several such calls back to MATLAB? That's the core of my problem.

The variable mean will point to an mxArray that contains the result of the "mean" function call. You can do whatever you want with it such as alter its data contents by using mxGetPr(mean) to get the data pointer, or return it back to MATLAB as one of the plhs elements if you like (e.g., plhs[0] = mean;), or both. Or you can treat it as a temporary variable inside you mex function and then when you are done with it just call mxDestroyArray(mean) to free it. If you state specifically what you want to do with it I can give you a more specific answer.

> Concerning the mwSize topic: I tried to declare rows and cols as mwSize like you suggested, but my compiler (Visual Studio) then gives me a warning for converting "size_t" to "mwSize", which might lead to some data loss...

What line is giving you a warning? I would have expected things to be matching up.

James Tursa
 |  Next  |  Last
Pages: 1 2
Prev: Fourier Transform (fft)
Next: fft on matlab