C++ OpenCV最大存储容量为cv :: Mat

Dim*_*htz 5 c++ opencv image-processing mat

在我的程序中,我加载一些图像,从中提取一些功能并使用a cv::Mat来存储这些功能.根据我知道的图像数量cv::Mat将是700.000 x 256(行x列),大约是720Mb.但是当我运行我的程序时它大约400.000 x 256(400Mb)并尝试添加更多它只是崩溃与致命错误.任何人都可以确认400Mb确实是cv::Mat存储容量的极限吗?我应该检查更多问题吗?克服这个问题的可能方法?

Bru*_*ira 4

通过使用以下内容挖掘源代码push_back

它检查是否有足够的空间容纳新元素,如果没有,它会重新分配矩阵,空间为(current_size * 3 + 1) / 2请参阅此处)。在您的示例中,大约 400,000 * 256(总共 102,400,000 个元素)它尝试另一个分配,因此它尝试为 307,200,001 / 2 = 153,600,000个元素分配空间。但是为了移动这个,需要分配一个新的空间,然后复制数据

来自矩阵.cpp

Mat m(dims, size.p, type());
size.p[0] = r;
if( r > 0 )
{
    Mat mpart = m.rowRange(0, r);
    copyTo(mpart);
}

*this = m;
Run Code Online (Sandbox Code Playgroud)

所以它本质上是:

  1. 为所有新创建的元素使用默认构造函数分配一个新矩阵
  2. 复制数据,然后删除旧数据
  3. 为此矩阵创建一个新标题,并包含足够的列
  4. 将此元素指向新分配的数据(释放旧分配的内存)

这意味着,在您的情况下,它需要足够的空间来容纳 (600,000 + 400,000) * 256 - 1GB 的数据,使用 4 字节整数。而且,它还创建了一个一行辅助矩阵,在本例中为 600,000 列,占用了 2,400,000 个额外字节。

因此,到下一次迭代时,当它达到 600,000 列时,它会尝试分配 900,000x256 元素 (900Mb) + 600,000x256 元素 (600Mb) + 600,000 (~3.4Mb)。因此,仅通过这种方式分配(使用push_back),您就可以进行多次重新分配。

换句话说:既然你已经知道矩阵的大致大小,那么使用reserve是必须的。它快了几倍(将避免重新分配和复制)。

另外,作为解决方法,您可以尝试插入到转置矩阵,然后在该过程完成后,再次转置它。

附带问题:这个实现不应该使用/realloc吗?mallocmemcpy