Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在保留以前数据的情况下更改OpenCV Mat尺寸_Android_Opencv - Fatal编程技术网

Android 如何在保留以前数据的情况下更改OpenCV Mat尺寸

Android 如何在保留以前数据的情况下更改OpenCV Mat尺寸,android,opencv,Android,Opencv,我正在用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 我认为使用复制操作会降低性能,那么最有效的方法是什么呢?OpenCV矩阵存储为列首单个数组,这意味着第一个矩阵的内存实际上如下所示

我正在用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

我认为使用复制操作会降低性能,那么最有效的方法是什么呢?

OpenCV矩阵存储为列首单个数组,这意味着第一个矩阵的内存实际上如下所示:

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]
[0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0]

第二个矩阵如下所示:

[0 0 0 0
0 0
0 1 0
0 1 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;
    }
};

大量测试表明,当在非常大的矩阵上操作时,以及当新的尺寸仅略大于原始尺寸时,它的速度仅略快。在所有其他情况下,它都比较慢,因此我不建议在标准情况下使用此方法。

OpenCV矩阵存储为列首单个数组,这意味着第一个矩阵的内存实际上如下所示:

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]
[0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0]

第二个矩阵如下所示:

[0 0 0 0
0 0
0 1 0
0 1 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;
    }
};

大量测试表明,当在非常大的矩阵上操作时,以及当新的尺寸仅略大于原始尺寸时,它的速度仅略快。在所有其他情况下,它都比较慢,因此我不建议使用此方法而不是标准方法。

我只会使用
copyMakeBorder
在右侧和底部添加一个2的边框。如果这太慢了,您最好重新考虑所有代码,因为这不会成为应用程序的瓶颈。我将使用
copyMakeBorder
在右侧和底部添加一个2的边框。如果这太慢了,您最好重新考虑所有代码,因为这不会成为应用程序的瓶颈。