How to pass an image to a 2D array using Matlab MEX?

I want to read some image to run a C++ MEX function to process this image. The image is originally stored as a Matlab 3D matrix, and then converted to a 2D matrix and each slice of the image is stored as a 1D vector. Here is some example codes below.
The MEX function:
include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
unsigned int** ubuff;
size_t col_ubuff = mxGetN(prhs[0]);
size_t row_ubuff = mxGetM(prhs[0]);
ubuff = (unsigned int **)mxCalloc(col_ubuff, row_ubuff);
for(int x = 0; x < col_ubuff; x++) {
ubuff[x] = (unsigned int *) mxCalloc(row_ubuff, sizeof(unsigned int));
}
for (int col=0; col < col_ubuff; col++) {
for (int row=0; row < row_ubuff; row++) {
ubuff[col][row] = mxGetPr(prhs[0])[row+col*row_ubuff];
}
}
unsigned int the_pixel_i_want = ubuff[16][2*32 + 2];
printf ("Debug: %d\n\n", the_pixel_i_want);
return;
}
2. The program can be compiled; however, the results of running the program is strange; for example, I have some test codes and test image with all pixels to be 188,
%%Test input image as 2D array clc; clf; clear all; close all;
volImage = 188.*ones(32,32,32);
volImageVec = reshape(volImage, 32*32, 32)';
volImageVec = uint32(volImageVec);
TestInputImage(volImageVec');
But the output sometimes be 188 and sometimes be 0. Is there a memory leak somewhere in my code? Thanks very much for your help.

 Risposta accettata

Thanks for editing. I found a way from other people. Just put it here for other people's interest.
1) The line
ubuff = (unsigned int **)mxCalloc(col_ubuff, row_ubuff);
should be
ubuff = (unsigned int **)mxCalloc(col_ubuff, sizeof(unsigned int *));
2) The line
ubuff[col][row] = mxGetPr(prhs[0])[row+col*row_ubuff];
should be
ubuff[col][row] = ((unsigned int *)mxGetData(prhs[0]))[row+col*row_ubuff];

5 Commenti

I don't know if it matters to you or not, but the way you are doing this does not guarantee that your copy of the image is contiguous. I.e., each of the mxCalloc calls for ubuff[x] is not guaranteed to be next to the other ones in memory. If this does make a difference to you, allocate a single block of memory for your copy and then set the row pointers appropriately. E.g.,
ubuff = (unsigned int **)mxCalloc(col_ubuff, row_ubuff);
ubuff[0] = (unsigned int *) mxCalloc(row_ubuff*col_ubuff, sizeof(unsigned int));
for(int x = 1; x < col_ubuff; x++) {
ubuff[x] = ubuff[x-1] + row_ubuff;
}
That way the data copy is contiguous, and at the end you only have two free's to do:
mxFree(ubuff[0]);
mxFree(ubuff);
All of that being said, I would ask if you really need this 2D syntax in your C code at all? Instead of creating this array of pointers just so you can use the ubuff[col][row] syntax, why not just do inline calculations [row+col*rowbuff] on a "single dimension" array to get at the data?
Hi James,
Thanks very much for your help.
1. I don't think the copy of the image need to be contiguous in the memory for my project. But I do have a test with your codes. However, strangely, the output using printf shows zeros of the ubuff. Not sure if there is a problem with the codes you provided.
2. Regarding to the memory free. I use
mxFree((void *)ubuff);
instead of two frees you mentioned. Will that be a difference? Also, I think Matlab will do the garbage collection at the end. Should we really put the free at the end of the coding? Or it just tries to make a good programming style?
I am looking forward to your reply. Cheers.
Also, I have a follow up question about output the processed 'ubuff' (2D integer array) as the Matlab left hand side parameter. Not sure how to do this. Could you please have a look at my post at
Regarding the "free" question, yes you are correct that it will be garbage collected. But I think it is good programming practice to do it manually. To that end, what you are doing is inadequate ... you are only freeing the row pointers, not the rows themselves. To free everything you would need to do this (one mxFree for each mxCalloc):
for(int x = 0; x < col_ubuff; x++) {
mxFree(ubuff[x]);
}
mxFree(ubuff);
As to why you are getting 0's using the code I suggested, I would need to see exactly how you implemented it.
I got a follow up question about Matlab mex function input/output 2D array format. For example, I have a variable '`outputBuff`' defined as C++ 2D integer array. After processing it, I want to output it as a 'plhs' (parameter at left hand side). Not sure how to do this.
int** outputBuff;
size_t col_outputBuff = mxGetN(prhs[4]);
size_t row_outputBuff = mxGetM(prhs[4]);
// Allocate the memory for 2D array
outputBuff = (int **)mxCalloc(col_outputBuff, sizeof(int*));
for(int x = 0; x < col_outputBuff; x++) {
outputBuff[x] = (int *) mxCalloc(row_outputBuff, sizeof(int));
}
// Read in the data
for (int col=0; col < col_outputBuff; col++) {
for (int row=0; row < row_outputBuff; row++) {
outputBuff[col][row] = ((int *)mxGetPr(prhs[4]))[row+col*row_outputBuff];
}
}
Then output it as `plhs`
const mwSize dims[] = {col_outputBuff, row_outputBuff}; plhs[0] = mxCreateNumericArray(2, dims, mxINT32_CLASS, mxREAL);
mxArray *outputMatrix;
outputMatrix = mxCreateNumericMatrix(col_outputBuff, row_outputBuff, mxINT32_CLASS, mxREAL);
outputBuff[0] = (int *)mxGetPr(outputMatrix);
outputMatrix = (mxArray *)mxGetData(plhs[0]);
The codes can be compiled but output all zeros not as expected. Could you give me some hints? Thanks a lot.

Accedi per commentare.

Più risposte (1)

I got the answer with the help from someone. I put it here for others' reference.
// Output the results
plhs[0] = mxCreateNumericMatrix(col_outputBuff, row_outputBuff, mxINT32_CLASS, mxREAL);
int* outputMatrix = (int *)mxGetData(plhs[0]);
// Read in the data
for (int col=0; col < col_outputBuff; col++) {
for (int row=0; row < row_outputBuff; row++) {
outputMatrix[row + col*row_outputBuff] = outputBuff[col][row];
}
}

Categorie

Scopri di più su MATLAB Coder in Centro assistenza e File Exchange

Richiesto:

il 13 Feb 2014

Risposto:

il 15 Feb 2014

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by