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

标签 c++ opencv image-processing mat

在我的程序中,我加载了一些图像,从中提取了一些特征并使用 cv::Mat 来存储这些特征。根据我知道的图像数量,cv::Mat 的大小为 700.000 x 256(行 x 列),约为 720Mb。但是当我运行我的程序时,当它达到大约 400.000 x 256 (400Mb) 并尝试添加更多时,它只会因 fatal error 而崩溃。谁能确认 400Mb 确实是 cv::Mat 存储容量的限制?我应该检查更多问题吗?解决这个问题的可能方法?

最佳答案

挖掘源代码,使用push_back:

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

来自 matrix.cpp :

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

*this = m;

所以它本质上是:

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

这意味着,在您的情况下,它需要足够的空间来容纳 (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 而不是 malloc/memcpy 吗?

关于C++ OpenCV cv::Mat 的最大存储容量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40518449/

相关文章:

python - Anaconda Jupyter Python2.7 "ImportError: No module named opencv"

java - 使用 Java(无开源库)从图像中检测硬币

c++ - 深度+颜色的3D投影

c++ - 如何避免out参数?

c++ - 从非常大的范围返回非重复的随机值

c++ - 分配 cv::Mat 对象的最通用方法是什么?

python - 错误 : recursion is detected during loading of "cv2" binary extensions. 检查 OpenCV 安装

c++ - 从球体上的 3d 点计算 RPY(滚动俯仰偏航)

c++ - std::uniform_real_distribution - 获取所有可能的数字

python - 适用于图像密集型 Web 应用程序的最佳 Python/Django 架构