poster
2019-12-10, 20:48
我在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); } 这个结果看起来是完全错误的,因为openCV使用了matlab以外的其他约定来存储图像(例如,它们交错了颜色通道)。
谁能解释约定的区别,并提供一些有关如何正确显示图像的指示?
回答:
花了一天时间完成有趣的图像格式转换我现在可以回答我自己的问题。
Matlab将图像存储为3维数组:高度×宽度×颜色
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); 将其转换为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); }
更多&回答... (https://stackoverflow.com/questions/3922494)
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); } 这个结果看起来是完全错误的,因为openCV使用了matlab以外的其他约定来存储图像(例如,它们交错了颜色通道)。
谁能解释约定的区别,并提供一些有关如何正确显示图像的指示?
回答:
花了一天时间完成有趣的图像格式转换我现在可以回答我自己的问题。
Matlab将图像存储为3维数组:高度×宽度×颜色
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); 将其转换为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); }
更多&回答... (https://stackoverflow.com/questions/3922494)