对于快速jpeg加载,我为turbojpeg实现了一个.mex-wrapper,可以有效地将(大)jpegs读入MATLAB。对于4000x3000px图像,实际解码仅需约120毫秒(不是5毫秒)。但是,像素排序是RGBRGBRGB ...,而MATLAB需要一个[W x H x 3]矩阵,在内存中是W * H * 3阵列,其中第一个WH条目对应红色,第二个WH条目对应绿色,最后的WH条目为蓝色。 此外,图像从左上角到右下角围绕轴进行镜像。
重新排列循环的直接实现如下:
// buffer contains mirrored and scrambled output of turbojpe
// outImg contains image matrix for use in MATLAB
// imgSize is an array containing {H,W,3}
for(int j=0; j<imgSize[1]; j++) {
for(int i=0; i<imgSize[0]; i++) {
curIdx = j*imgSize[0] + i;
curBufIdx = (i*imgSize[1] + j)*3;
outImg[curIdx] = buffer[curBufIdx++];
outImg[curIdx + imgSize[0]*imgSize[1] ] = buffer[curBufIdx++];
outImg[curIdx + 2*imgSize[0]*imgSize[1] ] = buffer[curBufIdx];
}
}
它可以工作,但它需要大约120ms(而不是20ms),大约与实际解码一样长。有关如何提高此代码效率的任何建议吗?
由于存在错误,我更新了处理时间。
答案 0 :(得分:2)
编辑: 99%的C库将存储图像行主要,这意味着如果从turbojpeg获得3 x WH(2D阵列),您可以将其视为3 x W x H(上面的预期输入)。在此表示中,像素读取然后向下读取。你需要它们在MATLAB中读取。您还需要将像素顺序(RGBRGBRGB ...)转换为平面顺序(RRRR .... GGGGG .... BBBBB ...)。解决方案是permute(reshape(I,3,W,H),[3 2 1])
。
这是其中一种情况,其中MATLAB的permute
命令可能会比您在短时间内手动编码的任何事情更快(比所示的循环至少快50%)。我通常会使用mexCallMATLAB
来避开解决方案,但我认为这可能是一个例外。但是,输入是mxArray
,这可能不方便。无论如何,这里有permute(I,[3 2 1])
:
#include "mex.h"
int computePixelCtoPlanarMATLAB(mxArray*& imgPermuted, const mxArray* img)
{
mxArray *permuteRHSArgs[2];
// img must be row-major (across first), pixel order (RGBRGBRGB...)
permuteRHSArgs[0] = const_cast<mxArray*>(img);
permuteRHSArgs[1] = mxCreateDoubleMatrix(1,3,mxREAL);
// output is col-major, planar order (rows x cols x 3)
double *p = mxGetPr(permuteRHSArgs[1]);
p[0] = 3;
p[1] = 2;
p[2] = 1;
return mexCallMATLAB(1, &imgPermuted, 2, permuteRHSArgs, "permute");
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {
// do some argument checking first (not shown)
// ...
computePixelCtoPlanarMATLAB(plhs[0], prhs[0]);
}
或者在MATLAB中回复permute(I,[3 2 1])
。
首先从3xWH到3xWxH的reshape
怎么样?告诉代码它真的是3xWxH! reshape
不移动数据 - 它只是告诉MATLAB将给定的数据缓冲区视为一定的大小。