为了快速加载jpeg,我为turbojpeg实现了一个.mex-wrapper,以便高效地将(大的)jpeg读取到MATLAB中。对于4000x3000px的图像,实际解码只需要大约120ms(而不是5ms)。但是,像素排序是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),大约与实际解码的时间一样长。关于如何让这段代码更有效率有什么建议吗?
由于一个bug,我更新了处理时间。
发布于 2015-08-18 06:55:50
编辑: turbojpeg 99%的C库将存储图像的行长,这意味着如果你从得到一个3xWH(一个二维数组),你可以把它当做一个3xWxH(上面预期的输入)。在这个表示中,像素读过然后向下读。你需要把它们读下来,然后在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将给定的数据缓冲区视为特定的大小。
https://stackoverflow.com/questions/32059654
复制相似问题