高效的重新排序和同时旋转图像的方式 [英] Highly efficient way of reordering and rotating image simultaneously

查看:193
本文介绍了高效的重新排序和同时旋转图像的方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于快速jpeg加载我实现了一个.mex包装turbojpeg有效地读取(大)jpegs到MATLAB。对于4000x3000px的图像,实际解码只需要大约120 ms(不是5ms)。然而,像素排序是RGBRGBRGB ...,而MATLAB需要一个[W x H x 3]矩阵,在存储器中是一个W * H * 3数组,其中第一WH条目对应于红色,第二WH条目绿色,最后WH条目为蓝色。

For fast jpeg-loading I implemented a .mex-wrapper for turbojpeg to read (large) jpegs into MATLAB efficiently. The actual decoding takes only around 120 ms (not 5ms) for a 4000x3000px image. However, the pixel ordering is RGBRGBRGB... , while MATLAB requires a [W x H x 3] matrix, which in memory is a W*H*3 array, where the first WH entries correspond to red, the second WH entries to green, and the last WH entries to blue. Additionally the image is mirrored around the axis from top left to bottom right.

重新排列循环的直接实现如下:

The straightforward implementation of a rearrangement loop is the following:

// 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 ),约等于实际解码。有关如何提高此代码的效率的任何建议?

It works, but it takes around 120ms (not 20ms), about as long as the actual decoding. Any suggestions on how to make this code more efficient?

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

Due to a bug I updated the processing times.

推荐答案

编辑: 99%的C库将存储图像row-major,这意味着如果你从turbojpeg获得一个3 x WH只是将其视为3 x W x H(上面的预期输入)。在这个表示中,像素然后向下读。你需要他们在MATLAB中阅读。你还需要将像素顺序(RGBRGBRGB ...)转换为平面顺序(RRRR .... GGGGG ... BBBBB ...)。解决方案是 permute(reshape(I,3,W,H),[3 2 1])

99% of C libraries will store images row-major, meaning if you get a 3 x WH (a 2D array) from turbojpeg, you can just treat it as a 3 x W x H (the expected input above). In this representation, pixels read across then down. You need them to read down then across in MATLAB. You also need to convert pixel order (RGBRGBRGB...) to planar order (RRRR....GGGGG....BBBBB...). The solution is permute(reshape(I,3,W,H),[3 2 1]).

这是其中一个MATLAB的 permute 命令可能会比你手动编写的任何代码快得多(至少比所示的循环快50%)。我通常会使用 mexCallMATLAB ,但我认为这可能是个例外。但是,输入是 mxArray ,这可能不方便。无论如何,这里是如何做 permute(I,[3 2 1])

This is one of those situations where MATLAB's permute command is probably going to be faster than anything you will code by hand on short notice (at least 50% faster than the loop shown). I usually steer away from solutions with mexCallMATLAB, but I think this may be an exception. However, the input is a mxArray, which may be inconvenient. Anyway, here's how to do a 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]);
}

或调用 permute(I,[3 2 1 ])自己回到MATLAB中。

Or call permute(I,[3 2 1]) yourself back in MATLAB.

reshape 3xWH到3xWxH?只是告诉代码,它真的3xWxH! reshape 移动无数据 - 它只是告诉MATLAB将给定的数据缓冲区视为一定大小。

What about the reshape to first go from 3xWH to 3xWxH? Just tell the code that it's really 3xWxH! reshape moves no data -- it just tells MATLAB to treat a given data buffer as being a certain size.

这篇关于高效的重新排序和同时旋转图像的方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆