我正在处理图像对齐问题。
我从一台相机拍摄了几张照片(每幅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说它需要更多来克隆它。
因此,我真的想知道我的理解是否有任何不妥之处,我怎样才能确定是否是我自己的错误是内存问题?
谢谢!
答案 0 :(得分:2)
您可能正在耗尽RAM内存。
调整图像大小以使其大小为原始大小的一半,然后重试。如果失败,将其大小减少一半。重复此过程直到成功。
如果没有,问题可能是其他问题,您必须共享MCVE (Minimal, Complete, and Verifiable example)才能获得更多帮助。
答案 1 :(得分:0)
如果有人和我有同样的情况,我想更新我找到的解决方案。
我按照@karlphillip的建议,将图像尺寸更改为原始图像的1/4。然后我的程序运行得更快,内存更少。所以在这种情况下我很容易调试。
当您在内存的不存在部分中复制或分配值时,总会发生内存损坏。
在图像对齐问题中,两个图像之间有四个相关位置。
----- ----- ----- -----
| A | | A | | B | | B |
--------- --------- --------- ---------
| B | | B | | A | | A |
----- ----- ----- -----
我们可以根据相关位置轻松确定detRow和detCol应该是正面的还是负面的。
然后我们可以计算出合并后新图像的大小。
然而,实际上还有8个案例容易被忽略。
您应确定A和B之间的大小关系。即新图像的行/列不应小于A和B的行/列。或者您将数据复制到Mat的位置,这会导致内存问题。