Después de pasar el día haciendo conversiones de formato de imagen divertidas </sarcasm>
ahora puedo responder mi propia pregunta.
Matlab almacena las imágenes como 3 arrays dimensionales: altura × anchura × de color
almacena OpenCV imágenes como 2 arrays dimensionales: (color × anchura) × altura
Además, para un mejor rendimiento, OpenCV almohadillas de las imágenes con ceros así que las filas siempre están alineadas en bloques de 32 bits.
que he hecho la conversión en Matlab:
function [cv_img, dim, depth, width_step] = convert_to_cv(img)
% Exchange rows and columns (handles 3D cases as well)
img2 = permute(img(:,end:-1:1,:), [2 1 3]);
dim = [size(img2,1), size(img2,2)];
% Convert double precision to single precision if necessary
if(isa(img2, 'double'))
img2 = single(img2);
end
% Determine image depth
if(ndims(img2) == 3 && size(img2,3) == 3)
depth = 3;
else
depth = 1;
end
% Handle color images
if(depth == 3)
% Switch from RGB to BGR
img2(:,:,[3 2 1]) = img2;
% Interleave the colors
img2 = reshape(permute(img2, [3 1 2]), [size(img2,1)*size(img2,3) size(img2,2)]);
end
% Pad the image
width_step = size(img2,1) + mod(size(img2,1), 4);
img3 = uint8(zeros(width_step, size(img2,2)));
img3(1:size(img2,1), 1:size(img2,2)) = img2;
cv_img = img3;
% Output to openCV
cv_display(cv_img, dim, depth, width_step);
El código para transformar esto en una IplImage está en el archivo MEX:
#include "mex.h"
#include "cv.h"
#include "highgui.h"
#define IN_IMAGE prhs[0]
#define IN_DIMENSIONS prhs[1]
#define IN_DEPTH prhs[2]
#define IN_WIDTH_STEP prhs[3]
void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs) {
bool intInput = true;
if(nrhs != 4)
mexErrMsgTxt("Usage: cv_disp(image, dimensions, depth, width_step)");
if(mxIsUint8(IN_IMAGE))
intInput = true;
else if(mxIsSingle(IN_IMAGE))
intInput = false;
else
mexErrMsgTxt("Input should be a matrix of uint8 or single precision floats.");
if(mxGetNumberOfElements(IN_DIMENSIONS) != 2)
mexErrMsgTxt("Dimension vector should contain two elements: [width, height].");
char *matlabImage = (char *)mxGetData(IN_IMAGE);
double *imgSize = mxGetPr(IN_DIMENSIONS);
size_t width = (size_t) imgSize[0];
size_t height = (size_t) imgSize[1];
size_t depth = (size_t) *mxGetPr(IN_DEPTH);
size_t widthStep = (size_t) *mxGetPr(IN_WIDTH_STEP) * (intInput ? sizeof(unsigned char):sizeof(float));
CvSize size;
size.height = height;
size.width = width;
IplImage *iplImage = cvCreateImageHeader(size, intInput ? IPL_DEPTH_8U:IPL_DEPTH_32F, depth);
iplImage->imageData = matlabImage;
iplImage->widthStep = widthStep;
iplImage->imageDataOrigin = iplImage->imageData;
/* Show the openCV image */
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvShowImage("mainWin", iplImage);
}
es probable que sea más fácil simplemente pasar el nombre de archivo para el MEX y dejar OpenCV cuidar de cargar la imagen desde el archivo ? –
http://mirone.googlecode.com/svn/tags/1.3.0/mex/cvcolor_mex.c – karlphillip
Sí, sería más fácil dejar que OpenCV se encargue de cargar la imagen. Sin embargo, lo que quiero lograr es crear un archivo MEX de matlab que realice la detección de punto clave SURF en la GPU usando esta lib: http://www.mis.tu-darmstadt.de/surf La lib requiere una IplImage como entrada . Escenarios de uso será alguien haciendo manipulaciones de imagen en Matlab, luego ejecutando el resultado a través de la lib de SURF, y felizmente utilizando el resultado en Matlab. –