【问题标题】:OpenCV: memory corruption when align multi imagesOpenCV:对齐多张图像时内存损坏
【发布时间】:2015-04-23 21:49:12
【问题描述】:

我正在处理图像对齐问题。

我有几张从一台相机拍摄的图像(每张 480x640)。这些图像形成一个圆柱面,每对调整后的图像共享几个相似的列,以帮助将所有图像对齐为全景图像。

一开始,我假设每对图像之间没有旋转或放大/缩小,所以我只计算两个图像之间的移位向量而不是断层扫描矩阵。

我的代码是:

//Store all images into a cv::Mat vector
std::vector<cv::Mat> image = ...
//Create a result Mat and set its content using the first image
cv::Mat result = image[0];

for (int i = 1; i < image.size(); i++) {
    //calculate the shift vector(image[i]-result) based on feature points using SURF.
    //this function works correctly and matched_diff[0] is det_x, and matched_diff[1] is det_y
    std::vector<int> matched_diff= surfMatch (result,image[i]);

    //Create a new Mat with size after combination
    cv::Mat temp(image[i].rows+abs(matched_diff[1]),image[i].cols+abs(matched_diff[0]),CV_8UC3);

    // Copy old result to its new position in temp
    // Copy image[i] to its new position in temp
    // Calculate pixel value of mixed range and copy them to their positions in temp
    ...

    //store the new result and go back to the first step
    result = temp.clone();
}

每次组合后det_x会增加300px左右,当然程序需要更多时间来完成下一次组合。

当我使用两个或三个图像对其进行测试时,该代码运行良好。

但在正确组合多张图片(大约 14 张)后,程序崩溃并出现错误:

malloc():内存损坏:0x0000000000cdae50 ***

我使用 GDB 检查内存问题发生的位置,但它告诉我问题是在 result = temp.clone(); 引起的。

我认为原因是经过多次组合,图像(Mat)变得相当大,创建temp需要更多内存,导致内存损坏错误。

我的问题是,根据我对 OpenCV 的理解,temp 对象将在每个 for 循环之后被解构。并且当崩溃时,下一个temp 的大小应该是3000px*640px。所以它需要的总内存是 3000*640*3Byte= 5.5Kb。 (对于 cv::Vec3b,每个像素需要 3 个 8 位来存储其 R G B 值。),但 GDB 表示它需要更多来克隆它。

因此,我真的很想知道我的理解是否有任何问题,我如何确定是我自己的错误还是内存问题?

谢谢!

【问题讨论】:

  • 要添加解决方案,请在下面写下您的答案。不要在问题中这样做。请修复这个帖子,这是个好东西。
  • 抱歉,感谢您的评论@karlphillip

标签: opencv memory


【解决方案1】:

您的 RAM 内存可能已用完

调整图像大小,使其为原始大小的一半,然后重试。如果失败,将它们的大小再减小一半。重复这个过程,直到成功。

如果没有,问题可能是其他问题,您必须分享MCVE (Minimal, Complete, and Verifiable example) 以获得更多帮助。

【讨论】:

  • 非常感谢!调整图像大小是使用 OpenCV 操作时调试的好方法!最后我发现是我的算法的错误导致了这个问题。我正在尝试解决它,并会在完成后更新。下次我问问题时,我会尝试制作一个 MCVE 而不是一个非常简短的结构,再次感谢!
  • 不用感谢。只需投票给答案。 ;D 回头见。
【解决方案2】:

如果有人和我有同样的情况,我想更新我找到的解决方案。

我听从了@karlphillip 的建议,将图像大小更改为原始大小的 1/4。然后我的程序运行得更快,占用的内存更少。所以在这种情况下我很容易调试。

当您将值复制或分配到内存的不存在部分时,总是会发生内存损坏。

在图像对齐问题中,两个图像之间有四个相关的位置。

-----              -----         -----                 ----- 
| A |              | A |         | B |                 | B |
---------      ---------         ---------         ---------
    | B |      | B |                 | A |         | A |
    -----      -----                 -----         -----

从中我们可以很容易地根据它们的相关位置确定detRow和detCol应该是正还是负。

然后我们可以计算组合后新图像的大小。

然而,实际上还有八种容易被忽略的情况。

您应该确定A和B之间的大小关系。即新图像的行/列不应小于A和B的行/列。否则您会将数据复制到 Mat 之外的某个位置,这会导致内存问题。

【讨论】:

  • 如果不是内存耗尽问题,我有一种预感,您正在为图像声明内存并通过 std::vector...temp 声明将其分配给指针增量。我无法从您的帖子中看出,但要查找匹配的列,如果您正在递增指针 imagetemp(从而将 起始地址 丢失到内存块),您可能会遇到难以追踪的内存损坏问题。 (这就是为什么涉及result = temp.clone() 是有道理的)。只是一种预感。您应该删除 C 标记。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-07
  • 2016-12-30
  • 1970-01-01
  • 1970-01-01
  • 2017-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多