Thread Subject: how to pass cell of 3D matrices to C mex

Subject: how to pass cell of 3D matrices to C mex

From: oruganti murthy

Date: 24 Aug, 2009 09:08:03

Message: 1 of 16

Hi
I have a 1x30 cell. Each element in it consists of a MxNx3 matrix(image).
How can I send it into C mex file in similar format, but not read only.(duplicate will not work).
Basically it contains video frames.


Thanking you very much,

with regards,
ramana

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 24 Aug, 2009 10:12:04

Message: 2 of 16

"oruganti murthy" <omurthy@yahoo.com> wrote in message <h6tl9j$a0p$1@fred.mathworks.com>...
>
> I have a 1x30 cell. Each element in it consists of a MxNx3 matrix(image).
> How can I send it into C mex file in similar format, but not read only.(duplicate will not work).

Pass it in like any other variable. Then prhs[0] will be the cell array. If you want to modify it, use mxDuplicateArray to create a deep copy. Then use mxGetCell followed by mxGetPr to get at the cells and the arrays contained in the cells respectively. Why did you write that "duplicate will not work"?

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: oruganti murthy

Date: 26 Aug, 2009 09:09:04

Message: 3 of 16

 
> Pass it in like any other variable. Then prhs[0] will be the cell array. If you want to modify it, use mxDuplicateArray to create a deep copy. Then use mxGetCell followed by mxGetPr to get at the cells and the arrays contained in the cells respectively. Why did you write that "duplicate will not work"?
>
> James Tursa

Hi James,
I thought that duplicating will not allow the matrix to change. After your comment, I have verified it and I am taking my statement back.
As per your guidance, I wrote the following. and got the following output.
Can you please comment?

with regards,
ramana
************
#include "mex.h"
void
        mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    mxArray *cell_array_ptr, *cell_element_ptr;
    mwIndex i, j, index;
    mwSize m, n, total_num_of_cells, total_num_of_elements;
    double **carray;
    double *data;
    
    (void)plhs; /* unused parameter */
    
    /* Create a nrhs x 1 cell mxArray. */
    cell_array_ptr = mxCreateCellMatrix((mwSize)nrhs, 1);
    
    /* Fill cell matrix with input arguments */
    for( i=0; i<(mwIndex)nrhs; i++){
        mxSetCell(cell_array_ptr, i, mxDuplicateArray(prhs[i]));
    }
    total_num_of_cells = mxGetNumberOfElements(cell_array_ptr);
    
    for (index=0; index<total_num_of_cells; index++) {
        cell_element_ptr = mxGetCell(cell_array_ptr, index);
        data = mxGetPr(cell_element_ptr);
        m = mxGetM(cell_element_ptr);
        n = mxGetN(cell_element_ptr);
        carray = mxCalloc(n, sizeof(double*));
        for (j=0; j<n; j++)
            carray[j] = data+m*j;
        for (i=0;i<m;i++)
            for(j = 0;j<n;j++)
                mexPrintf("data(%i,%i) = %f \n", i+1, j+1, carray[i][j]);
    }
}
*********************************
clear all
clc
img = imread('cameraman.tif');
for i=1:3
    img1 = im2double(imresize(img,0.01*i));
    sources{i} = img1(:,:,1)';
end
struct1(sources)
**************
data(1,1) = 0.000000
data(1,2) = 0.000000
data(1,3) = 0.000000
>>

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 26 Aug, 2009 15:35:22

Message: 4 of 16

"oruganti murthy" <omurthy@yahoo.com> wrote in message <h72u3f$5qi$1@fred.mathworks.com>...
>

Try this:

#include "mex.h"
#define DATA(i,j) data[i+j*m]
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mxArray *cell_array_ptr, *cell_element_ptr;
    mwIndex i, j, index;
    mwSize m, n;
    double *data;
    
    (void)plhs; /* unused parameter */
    
    /* Create a nrhs x 1 cell mxArray. */
    cell_array_ptr = mxCreateCellMatrix(nrhs, 1);
    
    /* Fill cell matrix with input arguments */
    for( i=0; i<nrhs; i++){
        mxSetCell(cell_array_ptr, i, mxDuplicateArray(prhs[i]));
    }
    for (index=0; index<nrhs; index++) {
        cell_element_ptr = mxGetCell(cell_array_ptr, index);
        data = mxGetPr(cell_element_ptr);
        m = mxGetM(cell_element_ptr);
        n = mxGetN(cell_element_ptr);
        mexPrintf("Cell array index %d\n",index);
        for (i=0; i<m; i++)
            for(j=0; j<n; j++)
                mexPrintf("data(%i,%i) = %g \n", i+1, j+1, DATA(i,j));
        // other code to use cell_element_ptr
    }
    // other code to use cell_array_ptr
    mxDestroyArray(cell_array_ptr); // so this if not returned in a plhs
}

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: Ramana Murthy

Date: 27 Aug, 2009 03:18:03

Message: 5 of 16

Hi james,
I compiled your code. But I am getting some strange output

Cell array index 0
data(1,1) = 8.41049e-288
data(1,2) = 5.45389e-312
data(1,3) = -9.60206e+303


I was expecting to print the individual elements(of matrix) of each entry of cell.

with regards,
ramana

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 27 Aug, 2009 07:15:20

Message: 6 of 16

"Ramana murthy" <omurthy@yahoo.com> wrote in message <h74ttb$t3r$1@fred.mathworks.com>...
> Hi james,
> I compiled your code. But I am getting some strange output
>
> Cell array index 0
> data(1,1) = 8.41049e-288
> data(1,2) = 5.45389e-312
> data(1,3) = -9.60206e+303
>
>
> I was expecting to print the individual elements(of matrix) of each entry of cell.
>
> with regards,
> ramana

Your posted code had double * for the data type, so I assumed that was the data type being passed in. Your strange results are because the data type being passed in is not double. Just check what the data type is and then adjust the code accordingly. e.g., if the data type is int8, then change these lines:

    double *data;
                :
        data = mxGetPr(cell_element_ptr);
                        :
                mexPrintf("data(%i,%i) = %g \n", i+1, j+1, DATA(i,j));

to this:

    signed char *data;
                :
        data = mxGetData(cell_element_ptr);
                        :
                mexPrintf("data(%i,%i) = %d \n", i+1, j+1, DATA(i,j));

Or if the data is uint16, then change the lines to this:

    unsigned short *data;
                :
        data = mxGetData(cell_element_ptr);
                        :
                mexPrintf("data(%i,%i) = %d \n", i+1, j+1, DATA(i,j));

etc. etc.

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: Ramana Murthy

Date: 27 Aug, 2009 08:21:01

Message: 7 of 16

Hi James,
As I have posted in my previous mail,
My matlab code calling this mex file is

*********************************
clear all
clc
img = imread('cameraman.tif');
for i=1:3
    img1 = im2double(imresize(img,0.01*i));
    sources{i} = img1(:,:,1)';
end
struct1(sources)
**************
Clearly, I'm passing a matrix of double values.
My problem is
1. I'm not getting output matrices
2. Very strange values
Any suggestions?


with regards,
ramana

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 27 Aug, 2009 09:18:02

Message: 8 of 16

"Ramana murthy" <omurthy@yahoo.com> wrote in message <h75fld$ort$1@fred.mathworks.com>...
> Hi James,
> As I have posted in my previous mail,
> My matlab code calling this mex file is
>
> *********************************
> clear all
> clc
> img = imread('cameraman.tif');
> for i=1:3
> img1 = im2double(imresize(img,0.01*i));
> sources{i} = img1(:,:,1)';
> end
> struct1(sources)
> **************
> Clearly, I'm passing a matrix of double values.

OK, please clear something up. Is your function called "struct1", and are you passing in your "sources" variable? If that is the case, then you are passing in a cell array, not a double. e.g., try out this code to verify what the mex file is actually getting:

#include "mex.h"
#define DATA(i,j) data[i+j*m]
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mxArray *cell_array_ptr, *cell_element_ptr;
    mwIndex i, j, index;
    mwSize m, n;
    double *data;
    
    (void)plhs; /* unused parameter */
    
    /* Create a nrhs x 1 cell mxArray. */
    cell_array_ptr = mxCreateCellMatrix(nrhs, 1);
    
    /* Fill cell matrix with input arguments */
    for( i=0; i<nrhs; i++){
        if( !mxIsDouble(prhs[i]) ) {
            mexPrintf("Input argument is not double, it is %s\n",mxGetClassName(prhs[i]));
            mxDestroyArray(cell_array_ptr);
            mexErrMsgTxt("Returning to MATLAB");
        }
        mxSetCell(cell_array_ptr, i, mxDuplicateArray(prhs[i]));
    }
    for (index=0; index<nrhs; index++) {
        cell_element_ptr = mxGetCell(cell_array_ptr, index);
        data = mxGetPr(cell_element_ptr);
        m = mxGetM(cell_element_ptr);
        n = mxGetN(cell_element_ptr);
        mexPrintf("Cell array index %d\n",index);
        for (i=0; i<m; i++)
            for(j=0; j<n; j++)
                mexPrintf("data(%i,%i) = %g \n", i+1, j+1, DATA(i,j));
        // other code to use cell_element_ptr
    }
    // other code to use cell_array_ptr
    mxDestroyArray(cell_array_ptr); // so this if not returned in a plhs
}

After doing that, please advise me what, exactly, you would like the mex file to do, as I have been under the apparently mistaken impression you wanted to copy some double inputs into a cell array for manipulation inside the mex routine.

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: Ramana Murthy

Date: 27 Aug, 2009 09:42:04

Message: 9 of 16


> After doing that, please advise me what, exactly, you would like the mex file to do, as I have been under the apparently mistaken impression you wanted to copy some double inputs into a cell array for manipulation inside the mex routine.
>
> James Tursa


Hi James,
Sorry if I have confused you. My C mex file name is struct1.c
I wanted to pass all all the 2D matrices in a cell to Mex file. In the mex file I want to use each element of any matrix according to my requirements
In C file I want all the 2D matrices accessible seperately.

By running your new code I got...
*****************
Input argument is not double, it is cell
??? Error using ==> struct1
Returning to MATLAB

***********************

Subject: how to pass cell of 3D matrices to C mex

From: Ramana Murthy

Date: 27 Aug, 2009 12:18:18

Message: 10 of 16

INput from Matlab file
A cell of size k, containing a MxN matrix entries
Desired variable in C MEx file
A 3D matrix data[i][j][k] where k is the kth cell entry
or equivalent representation so that I can access MxNth matrix elements

with regards,
ramana

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 27 Aug, 2009 15:37:01

Message: 11 of 16

"Ramana murthy" <omurthy@yahoo.com> wrote in message <h75tia$ov3$1@fred.mathworks.com>...
> INput from Matlab file
> A cell of size k, containing a MxN matrix entries
> Desired variable in C MEx file
> A 3D matrix data[i][j][k] where k is the kth cell entry
> or equivalent representation so that I can access MxNth matrix elements
>
> with regards,
> ramana

Try this:

#include "mex.h"
#define DOUBLEDATA(i,j) doubledata[i+j*m+k*m*n]
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mxArray *mxcell, *mxdouble;
    mwSize i, j, m, n, k, p, numel;
    mwSize ndim = 3;
    mwSize dims[3];
    double *celldata, *doubledata;
    
    (void)plhs; /* unused parameter */

    if( nrhs != 1 ) {
        mexErrMsgTxt("Need exactly one input");
    }
    if( nlhs != 0 ) {
        mexErrMsgTxt("Too many outputs");
    }
    if( !mxIsCell(prhs[0]) ) {
        mexPrintf("Input argument is not cell, it is %s\n",mxGetClassName(prhs[0]));
        mexErrMsgTxt("Returning to MATLAB");
    }
    
    p = mxGetNumberOfElements(prhs[0]);
    dims[2] = p;
    
    /* Fill 3D matrix with input arguments */
    for( i=0; i<p; i++){
        mxcell = mxGetCell(prhs[0],i);
        if( !mxIsDouble(mxcell) ) {
            mexPrintf("Input cell is not double, it is %s\n",mxGetClassName(mxcell));
        }
        if( mxIsComplex(mxcell) ) {
            mexErrMsgTxt("Input cell cannot be complex");
        }
        if( mxGetNumberOfDimensions(mxcell) != 2 ) {
            mexErrMsgTxt("Input cell must be 2D");
        }
        if( i == 0 ) {
            m = mxGetM(mxcell);
            n = mxGetN(mxcell);
            dims[0] = m;
            dims[1] = n;
            mxdouble = mxCreateNumericArray(ndim, dims, mxDOUBLE_CLASS, mxREAL);
            numel = mxGetNumberOfElements(mxcell);
            doubledata = mxGetPr(mxdouble);
        }
        if( mxGetM(mxcell) != m || mxGetN(mxcell) != n ) {
            mexErrMsgTxt("Input cell dimensions must all be the same");
        }
        celldata = mxGetPr(mxcell);
        for( j=0; j<numel; j++ ) {
            *doubledata++ = *celldata++;
        }
    }
    doubledata = mxGetPr(mxdouble);
    for (k=0; k<p; k++) {
        for (j=0; j<n; j++) {
            for(i=0; i<m; i++) {
                mexPrintf("data(%d,%d,%d) = %g \n", i+1, j+1, k+1, DOUBLEDATA(i,j,k));
            }
        }
    }
    // other code to use mxdouble
    mxDestroyArray(mxdouble); // do this if not returned in a plhs
}

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 27 Aug, 2009 15:41:04

Message: 12 of 16

"Ramana murthy" <omurthy@yahoo.com> wrote in message <h75tia$ov3$1@fred.mathworks.com>...
> INput from Matlab file
> A cell of size k, containing a MxN matrix entries
> Desired variable in C MEx file
> A 3D matrix data[i][j][k] where k is the kth cell entry
> or equivalent representation so that I can access MxNth matrix elements
>

Follow-up question: Are you going to be *changing* the data inside your mex routine, or are you treating it as read-only? In the latter case, a much more efficient mex routine can be written than the one I just posted.

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 27 Aug, 2009 17:25:21

Message: 13 of 16

"James Tursa" <aclassyguy_with_a_k_not_a_c@hotmail.com> wrote in message <h7696t$i7u$1@fred.mathworks.com>...
>
> #define DOUBLEDATA(i,j) doubledata[i+j*m+k*m*n]

Typo. Should be:

#define DOUBLEDATA(i,j,k) doubledata[i+j*m+k*m*n]

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: Ramana Murthy

Date: 28 Aug, 2009 03:41:02

Message: 14 of 16

Hi James,
Thank you very much. Now it is working fine.
Yes, I want to change the contents of the matrices in the mex file. I don't want it as Read only file.
Though not required for my present application, I wanted to know if the matrices can be of different sizes. Right now, I see in your code you have restricted to be same size.


with regards,
ramana

Subject: how to pass cell of 3D matrices to C mex

From: James Tursa

Date: 28 Aug, 2009 07:04:01

Message: 15 of 16

"Ramana murthy" <omurthy@yahoo.com> wrote in message <h77jke$cl2$1@fred.mathworks.com>...
> Hi James,
> Thank you very much. Now it is working fine.
> Yes, I want to change the contents of the matrices in the mex file. I don't want it as Read only file.
> Though not required for my present application, I wanted to know if the matrices can be of different sizes. Right now, I see in your code you have restricted to be same size.

Yes, this can be done with a technique often used in C. Basically, instead of allocating one contiguous block of memory to hold everything, you create an array of double *, each one pointing to a copy of one of your 2D matrices. You allocate the matrix memory on the fly depending on how large the matrix is. It does take a little more clean-up at the end to free all the memory piecemeal, however. e.g.,

#include "mex.h"
#define ARRAYDATA(i,j,k) array[k][i+j*arrayM[k]]
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    mxArray *mxcell;
    mwSize i, j, m, n, k, p, numel;
    mwSize *arrayM, *arrayN;
    double *celldata, *arraydata;
    double **array;
    
    (void)plhs; /* unused parameter */

    if( nrhs != 1 ) {
        mexErrMsgTxt("Need exactly one input");
    }
    if( nlhs != 0 ) {
        mexErrMsgTxt("Too many outputs");
    }
    if( !mxIsCell(prhs[0]) ) {
        mexPrintf("Input argument is not cell, it is %s\n",mxGetClassName(prhs[0]));
        mexErrMsgTxt("Returning to MATLAB");
    }
    
    p = mxGetNumberOfElements(prhs[0]);
    array = mxMalloc(p * sizeof(*array));
    arrayM = mxMalloc(p * sizeof(*arrayM));
    arrayN = mxMalloc(p * sizeof(*arrayN));
    
    /* Fill 3D array with input arguments, each a different size */
    for( i=0; i<p; i++){
        mxcell = mxGetCell(prhs[0],i);
        if( !mxIsDouble(mxcell) ) {
            mexPrintf("Input cell is not double, it is %s\n",mxGetClassName(mxcell));
        }
        if( mxIsComplex(mxcell) ) {
            mexErrMsgTxt("Input cell cannot be complex");
        }
        if( mxGetNumberOfDimensions(mxcell) != 2 ) {
            mexErrMsgTxt("Input cell must be 2D");
        }
        celldata = mxGetPr(mxcell);
        arrayM[i] = mxGetM(mxcell);
        arrayN[i] = mxGetN(mxcell);
        numel = mxGetNumberOfElements(mxcell);
        array[i] = mxMalloc(numel * sizeof(**array));
        for( j=0; j<numel; j++ ) {
            array[i][j] = celldata[j]; // copy the data linearly, not as 2D
        }
    }
    for (k=0; k<p; k++) {
        for (j=0; j<arrayN[k]; j++) {
            for(i=0; i<arrayM[k]; i++) {
                mexPrintf("array(%d,%d,%d) = %g \n", i+1, j+1, k+1, ARRAYDATA(i,j,k));
            }
        }
    }
    // other code to use array here
    // free up the allocated memory when done
    for( k=0; k<p; k++ ) {
        mxFree(array[k]);
    }
    mxFree(array);
    mxFree(arrayM);
    mxFree(arrayN);
}

James Tursa

Subject: how to pass cell of 3D matrices to C mex

From: Ramana Murthy

Date: 28 Aug, 2009 09:00:19

Message: 16 of 16

Thank you very much Mr.James.

with regards,
Ramana

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
cell of matrix ... Sprinceana 26 Aug, 2009 05:21:41
mex passing cel... Sprinceana 26 Aug, 2009 05:21:41
mex passing Sprinceana 26 Aug, 2009 05:21:41
mex Sprinceana 26 Aug, 2009 05:21:41
rssFeed for this Thread
 

MATLAB Central Terms of Use

NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content. Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available via MATLAB Central. Read the complete Terms prior to use.

Contact us at files@mathworks.com