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.
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
精彩评论