Performane issue for matlab-like reshape in OpenCV

时间:2015-06-15 14:19:28

标签: c++ matlab opencv

I am translating a Matlab code to OpenCV. The Code Involves lots of reshaping of large Matrices. As the matlab reshape differs from OpenCV you can't just use OpenCV reshape. Here is why: Let's suppose we have a 2x4x3 matrix such as this:

a(:,:,1) =

     1     3     5     7
     2     4     6     8

a(:,:,2) =

     9    11    13    15
    10    12    14    16

a(:,:,3) =

    17    19    21    23
    18    20    22    24

when we perform reshape(a,4,3,2) the result is

ans(:,:,1) =

     1     5     9
     2     6    10
     3     7    11
     4     8    12

ans(:,:,2) =

    13    17    21
    14    18    22
    15    19    23
    16    20    24

But if we perform a similar reshape in OpenCV we get

ans(:,:,1) =

     1     17   11
     5     21   15
     2     18   12
     6     22   16

ans(:,:,2) =

    9     3     19
    13    7     23
    10    4     20
    14    8     24

This is due to the different ways of traversing the Matrix in OpenCV and Matlab. Matlab first traverse columns then rows and last depth. OpenCV first traverse depth then rows and last columns. So I have written a function to do a Matlab-like reshape for 3D Matrices. First I reshape the input matrix to a row matrix. For the matrix mentioned above the result matrix will be [1 2 3 ... 24] then I reshape the row Matrix to the desired channels. But as You see this code Involves lots of creating auxiliary matrices and copying and transposing that will not be good for the performance.

Mat matlab_reshape(const Mat &m, int new_row, int new_col, int new_ch)
{
    int old_row, old_col, old_ch;
    old_row = m.size().height;
    old_col = m.size().width;
    old_ch = m.channels();

    Mat m1 ( 1, new_row*new_col*new_ch, m.depth() );

    vector <Mat> p(old_ch);
    split(m,p);
    for ( int i=0; i<p.size(); ++i ){
        Mat t ( p[i].size().height, p[i].size().width, m1.type() );
        t = p[i].t();
        Mat aux = m1.colRange(i*old_row*old_col,(i+1)*old_row*old_col).rowRange(0,1);
        t.reshape(0,1).copyTo(aux);
    }

    vector <Mat> r(new_ch);
    for ( int i=0; i<r.size(); ++i ){
        Mat aux = m1.colRange(i*new_row*new_col,(i+1)*new_row*new_col).rowRange(0,1);
        r[i] = aux.reshape(0, new_col);
        r[i] = r[i].t();
    }

    Mat result;
    merge(r, result);
    return result;
} 

Here is an example:

Mat_ <Vec3b> m(2,4);
m(0,0) = Vec3b(1,9,17);
m(0,1) = Vec3b(3,11,19);
m(0,2) = Vec3b(5.1,13,21);
m(0,3) = Vec3b(7,15,23);
m(1,0) = Vec3b(2,10,18);
m(1,1) = Vec3b(4,12,20);
m(1,2) = Vec3b(6,14,22);
m(1,3) = Vec3b(8,16,24);
cout << m << endl;
cout << m.reshape(2,4) << endl;
cout << matlab_reshape(m,4,3,2) << endl;

Performance Comparison of reshaping matrices of [24700 X 10 X 1]size to matrices of [130 X 190 X 10] size

MY_CODE      MATLAB
0.006222     0.000039 
0.006528     0.000036
0.006716     0.000042
0.006733     0.000035
0.006508     0.000031

I appreciate any suggestion to make my code faster.

0 个答案:

没有答案