我正在将Matlab代码翻译成OpenCV。该代码涉及对大型矩阵的大量重塑。由于matlab重塑与OpenCV不同,因此您不能只使用OpenCV重塑。原因如下:假设我们有一个 2x4x3 矩阵,如下所示:
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
当我们执行reshape(a,4,3,2)
时,结果是
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
但是如果我们在OpenCV中执行类似的重塑,我们会得到
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
这是由于在OpenCV和Matlab中遍历矩阵的不同方式。Matlab 首先遍历列,然后遍历行和最后一个深度。OpenCV 首先遍历深度,然后遍历行和最后一列。所以我写了一个函数来对3D矩阵进行类似Matlab的重塑。首先,我将输入矩阵重塑为行矩阵。对于上面提到的矩阵,结果矩阵将被[1 2 3 ... 24]
然后我将行矩阵重塑为所需的通道。但正如你所看到的,这段代码涉及大量创建辅助矩阵以及复制和转置,这对性能不利。
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;
}
下面是一个示例:
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;
[24700 X 10 X 1]尺寸的整形矩阵与[130 X 190 X 10]尺寸的矩阵的性能比较
MY_CODE MATLAB
0.006222 0.000039
0.006528 0.000036
0.006716 0.000042
0.006733 0.000035
0.006508 0.000031
我很感激任何使我的代码更快的建议。
黑白 MATLAB 和 Opencv 重塑的区别在于,MATLAB 读取src_vals列并按列填充列,但在 OpenCV 中,它读取src_vals行并填充行。
cv::Mat reshape(cv::Mat src, int cn, int rows, int cols)
{
const std::vector<int> newshape = {cols, rows};
cv::Mat result = src.reshape(cn, newshape).t();//OpenCV function reshape.
return result;
}