我正在Android中使用OpenCV编写代码。现在我想改变Mat对象的尺寸而不重新缩放它(这是保留以前的数据)。例如,4x4垫:
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
将其大小更改为6x6
0 0 0 0 0 0
0 1 1 0 0 0
0 1 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
我认为使用复制操作会降低性能,那么最有效的方法是什么?
答案 0 :(得分:0)
OpenCV Matrices存储为第一列的单个数组,这意味着第一个矩阵的内存实际上如下所示:
[0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0]
虽然第二个矩阵看起来像这样:
[0 0 0 0
0 0 0 1 1 0
0 0 0 1 1 0
0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 ]
粗体零是新值。意味着要将第一个数组转换为第二个数组,您将无法直接使用第一个数组,但仍然必须分别复制每一行。因此,保留原始数组并不能真正提高效率。
但是如果您想最小化内存占用,可以使用realloc
来更改已分配内存的大小。我发现这是一个有趣的练习,并创建了以下继承OpenCV Mat的类,并添加了resize
函数。
template <class T>
class ResizableMat : public cv::Mat_<T> {
public:
// This only works when allocating dynamic memory up front
ResizableMat(int rows, int cols) : cv::Mat_<T>(rows, cols, (T*)malloc(rows * cols * sizeof(T))) {;}
ResizableMat(int rows, int cols, T initial) : cv::Mat_<T>(rows, cols, (T*)malloc(rows * cols * sizeof(T))) {
std::fill((T*)this->data, ((T*)this->data) + rows * cols, initial);
}
~ResizableMat() {
if (this->data)
free(this->data);
}
void resize(const size_t width, const size_t height) {
assert(width > this->cols && "width must be bigger than original width");
assert(height > this->rows && "height must be bigger than original height");
const int newstep = width * sizeof(T);
const size_t step_diff = newstep - this->step;
this->data = (uchar *)realloc(this->data, width * height * sizeof(T)); // expand the memory
for (int y = this->rows-1; y > 0; y--) {
uchar *src = this->data + this->step * y;
uchar *dst = this->data + newstep * y;
memcpy(dst, src, this->step); // copy the rows
memset(&dst[this->step], 0, step_diff); // fill the remainder of this row with 0
}
memset(&this->data[this->step], 0, step_diff);
memset(&this->data[newstep * this->rows], 0, (newstep * height) - (newstep * this->rows)); // fill the remaining rows with 0
this->step = newstep;
this->rows = height;
this->cols = width;
}
};
这可以这样使用:
ResizableMat<uchar> m(3,3, 1);
cout << "before:" << endl << m << endl;
m.resize(5, 5);
cout << "after:" << endl << m << endl;
其中输出以下内容:
before:
[ 1, 1, 1;
1, 1, 1;
1, 1, 1]
after:
[ 1, 1, 1, 0, 0;
1, 1, 1, 0, 0;
1, 1, 1, 0, 0;
0, 0, 0, 0, 0;
0, 0, 0, 0, 0]
许多测试表明,当在非常大的矩阵上运行时,以及当新尺寸仅略大于原始尺寸时,它只会稍微快一些。在所有其他情况下,它较慢,因此我不建议使用此方法而不是标准。