开发者

Reading image in matlab in a format acceptable to mex

Hi I use imread function in matlab to read an image. But now if i want to use this image in a mex file what should I do? I used im2double function to the image and then passed it to the mex file but the results i get are not acceptable.

so is the开发者_JAVA百科re any other function which can be used


Matlab has different data types, for example uint8, in32 and, most commonly, double. You can see those in the workspace or by using the whos command.

Reading image in matlab in a format acceptable to mex

These data types are quite similar to the ones in C(++). So for example, we could write this piece of c++/mex code printint.cpp:

#include <matrix.h>
#include <mex.h>


void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) {
    int nCols = mxGetDimensions(argin[0])[1];
    int nRows = mxGetDimensions(argin[0])[0];

    int *data = (int *)mxGetData(argin[0]);

    for(int row=0; row<nRows; ++row) {
        for(int col=0; col<nCols-1; ++col) {
            mexPrintf("%3d, ", data[nRows*col + row]);
        }
        mexPrintf("%3d\n", data[nRows*(nCols-1) + row]);
    }
}

This code simply prints all the numbers in a matrix, but it assumes that the elements in the matrix are integers. That is, the mxGetData returns a void pointer, which may point to any kind of data, also doubles. I cast the void pointer to an integer pointer, which is tricky but allowed in C(++).

This does however allow me to run printint on doubles, or any kind of matrix for that matter:

>> doubles=randi(10,[2,5])
doubles =
        8     3     1     7    10
        1     1     9     4     1
>> whos('doubles')
    Name         Size            Bytes  Class     Attributes
    doubles      2x5                80  double              
>> printint(doubles)
    0,   0,   0,   0,   0
1075838976, 1072693248, 1074266112, 1072693248, 1072693248

One can see that the output is garbage, I have interpreted doubles as if they were integers. This may also cause segmentation faults, namely if the actual sizeof of the data one inputs is smaller than the sizeof of an int; like uint8. If one inputs integers, the method does work:

>> integers = int32(doubles)
integers =
                    8           3           1           7          10
                    1           1           9           4           1
>> whos('integers')
    Name          Size            Bytes  Class    Attributes
    integers      2x5                40  int32              
>> printint(integers)
    8,   3,   1,   7,  10
    1,   1,   9,   4,   1

I typically assume a certain data type to be input, since I use mex to speed up certain parts of the code and don't want to spend time on creating flexible and fool proof API's. This comes at the cost of running into unexpected behavior when the input and assumed data types do not match. Therefore, one may consider programatically testing the data type that is input, in order to handle it correctly.

Your problem: In case you use I=imread(filename), Matlab returns a rows x cols x channels 3-D matrix of type uint8, which is equal to an unsigned char in C(++). In order to work with this data, one could write a simple class to wrap the image. This is done here:

#include <matrix.h>
#include <mex.h>

class MatlabImage {
public:
    MatlabImage(const mxArray *data) {
        this->data = (unsigned char*)mxGetData(data);
        this->rows = mxGetDimensions(data)[0];
        this->cols = mxGetDimensions(data)[1];
        this->channels = mxGetDimensions(data)[2];
    }
    unsigned char *data;
    int rows, cols, channels;
    int get(int row, int col, int channel) {
        return this->data[row + rows*(col + cols*channel)];
    }
};

void mexFunction(int nargout, mxArray *argout[], int nargin, const mxArray *argin[]) {
    MatlabImage image(argin[0]);
    int row=316; int col=253;
    mexPrintf("I(%d, %d) = (%3d, %3d, %3d)\n", row, col, image.get(row,col,0), image.get(row,col,1), image.get(row,col,2));
}

This can then be used in Matlab like this:

>> I = imread('workspace.png');
>> whos('I')
    Name        Size                Bytes  Class    Attributes
    I         328x344x3            338496  uint8              
>> getpixel(I)
I(316, 253) = (197, 214, 233)
>> I(317,254,:)
ans(:,:,1) =
    197
ans(:,:,2) =
    214
ans(:,:,3) =
    233

One can also work with doubles in a similar way. double(I) would convert the image to doubles, and im2double(I) does the same, but then divides all values by 255, such that they lie between 0 and 1. In both case one would need to cast the result of mxGetData(...) to (double *) instead of (unsigned char *).Finally note that C(++) starts indexing from 0 and Matlab from 1, so passing indexes from one to another always requires incrementing or decrementing them somewhere.


Convert to double and divided by 255. In Mex file Matlab double array is used to represent the image

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜