将图像从Matlab传输到OpenCV IplImage

Mar*_*iet 5 matlab opencv

我在Matlab中有一个图像:

img = imopen('image.jpg')

返回uint8数组高度x宽x通道(3通道:RGB).

现在我想使用openCV对它进行一些操作,所以我写了一个MEX文件,它将图像作为参数并从中构造一个IplImage:

#include "mex.h"
#include "cv.h"

void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs) {
    char *matlabImage = (char *)mxGetData(prhs[0]);
    const mwSize *dim = mxGetDimensions(prhs[0]);

    CvSize size;
    size.height = dim[0];
    size.width = dim[1];

    IplImage *iplImage = cvCreateImageHeader(size, IPL_DEPTH_8U, dim[2]);
    iplImage->imageData = matlabImage;
    iplImage->imageDataOrigin = iplImage->imageData;

    /* Show the openCV image */
    cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
    cvShowImage("mainWin", iplImage);
}
Run Code Online (Sandbox Code Playgroud)

这个结果看起来完全错误,因为openCV使用除matlab之外的其他约定来存储图像(例如,它们交错颜色通道).

任何人都可以解释约定的差异,并给出如何正确显示图像的一些指示?

Mar*_*iet 12

花了一天做有趣的图像格式转换后,</sarcasm>我现在可以回答我自己的问题.

Matlab将图像存储为三维数组:高度×宽度×颜色
OpenCV将图像存储为二维数组:(颜色×宽度)×高度

此外,为了获得最佳性能,OpenCV用零填充图像,因此行总是在32位块上对齐.

我在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);
Run Code Online (Sandbox Code Playgroud)

将其转换为IplImage的代码位于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);
}
Run Code Online (Sandbox Code Playgroud)