高效的重新排序和同时旋转图像的方式

时间:2015-08-17 21:02:56

标签: c++ image matlab rotation mex

对于快速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),大约与实际解码一样长。有关如何提高此代码效率的任何建议吗?

由于存在错误,我更新了处理时间。

1 个答案:

答案 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将给定的数据缓冲区视为一定的大小。