【问题标题】:How to align 2 images based on their content with OpenCV如何根据内容与 OpenCV 对齐 2 个图像
【发布时间】:2017-05-26 10:40:31
【问题描述】:

我对 OpenCV 完全陌生,我已经开始深入研究它。但我需要一点帮助。

所以我想合并这两张图片:

我希望这 2 张图像沿着它们的边缘匹配(暂时忽略图像的最右侧部分)

谁能指出我正确的方向?我试过使用findTransformECC 函数。这是我的实现:

cv::Mat im1 = [imageArray[1] CVMat3];
cv::Mat im2 = [imageArray[0] CVMat3];

// Convert images to gray scale;
cv::Mat im1_gray, im2_gray;
cvtColor(im1, im1_gray, CV_BGR2GRAY);
cvtColor(im2, im2_gray, CV_BGR2GRAY);

// Define the motion model
const int warp_mode = cv::MOTION_AFFINE;

// Set a 2x3 or 3x3 warp matrix depending on the motion model.
cv::Mat warp_matrix;

// Initialize the matrix to identity
if ( warp_mode == cv::MOTION_HOMOGRAPHY )
    warp_matrix = cv::Mat::eye(3, 3, CV_32F);
else
    warp_matrix = cv::Mat::eye(2, 3, CV_32F);

// Specify the number of iterations.
int number_of_iterations = 50;

// Specify the threshold of the increment
// in the correlation coefficient between two iterations
double termination_eps = 1e-10;

// Define termination criteria
cv::TermCriteria criteria (cv::TermCriteria::COUNT+cv::TermCriteria::EPS,   number_of_iterations, termination_eps);

// Run the ECC algorithm. The results are stored in warp_matrix.
findTransformECC(
                 im1_gray,
                 im2_gray,
                 warp_matrix,
                 warp_mode,
                 criteria
                 );

// Storage for warped image.
cv::Mat im2_aligned;

if (warp_mode != cv::MOTION_HOMOGRAPHY)
    // Use warpAffine for Translation, Euclidean and Affine
    warpAffine(im2, im2_aligned, warp_matrix, im1.size(), cv::INTER_LINEAR + cv::WARP_INVERSE_MAP);
else
    // Use warpPerspective for Homography
    warpPerspective (im2, im2_aligned, warp_matrix, im1.size(),cv::INTER_LINEAR + cv::WARP_INVERSE_MAP);


UIImage* result =  [UIImage imageWithCVMat:im2_aligned];
return result;

我尝试过使用termination_epsnumber_of_iterations 并增加/减少这些值,但它们并没有真正产生很大的不同。

结果如下:

我可以做些什么来改善我的结果?

编辑:我用红色圆圈标记了有问题的边缘。目标是扭曲底部图像并使其与上图中的线条匹配:

我做了一些研究,恐怕findTransformECC 函数不会给我想要的结果:-(

需要补充的重要内容: 实际上,我有一组图像“条纹”,在这种情况下为 8 个,它们看起来都与此处显示的图像相似,并且都需要进行处理以匹配线条。我试过用 OpenCV 的 stitch 函数做实验,但结果很糟糕。

编辑:

以下是 3 张源图片:

结果应该是这样的:

我按照应该匹配的线条转换了每张图片。距离太远的线可以忽略(图片右侧的阴影和路段)

【问题讨论】:

  • 您能否向我们展示您希望结果看起来如何的示例?
  • @alhadhrami 当然。我在问题中添加了一些细节。
  • 你误解了我的意思。我要求查看正确输出的示例,即您希望通过代码创建的输出。 @gasparuff
  • 另外,能否提供两张图片,以便我自己进行测试?
  • 嗨@alhadhrami。对不起,我的回复晚了,很多事情正在发生。我今晚会更新我的问题并添加您要求的信息。谢谢

标签: c++ opencv image-processing computer-vision image-stitching


【解决方案1】:

根据您的图像,它们似乎重叠。既然你说stitch 函数没有得到你想要的结果,那就实现你自己的拼接。我也在尝试做一些接近于此的事情。这是一个关于如何在 c++ 中实现它的教程:https://ramsrigoutham.com/2012/11/22/panorama-image-stitching-in-opencv/

【讨论】:

  • 感谢您的意见。事实上,我已经检查过了,但结果还没有真正有用。我还在想办法。
【解决方案2】:

您可以在两张图像上使用高阈值的霍夫算法,然后比较它们的垂直线 - 大多数应该移动一点,但保持角度。

这是我在其中一张图片上运行这个算法得到的结果:

过滤掉水平线应该很容易(因为它们表示为 Vec4i),然后您可以将剩余的线对齐。

这里是在OpenCV's documentation中使用它的例子。

更新:另一个想法。可以使用类似于互相关函数如何工作的概念来将线条对齐在一起。如果图片 1 有 10 行,而图片 2 有 100 行,则与 大多数 行对齐的移位位置(主要是 CCF 的最大值)应该非常接近答案,尽管这可能需要一些调整——例如根据每条线的长度、角度等给每条线赋予权重。计算机视觉从来没有直接的方法,呵呵:)

更新 2:我实际上想知道是否将顶部图像的底部像素线作为数组 1,将底部图像的顶部像素线作为数组 2,并在它们上运行通用 CCF,然后使用其最大值作为移位也可以工作......但我认为如果效果好的话,这将是一种已知的方法。

【讨论】:

  • 感谢您的宝贵意见。虽然我真的不知道如何把这个理论变成代码。您的 UPDATE 2 也是我一直在考虑的事情。但我需要了解 CCF 是如何工作的。
  • @gasparuff CCF(A, B) == REV_FFT(FFT(A)*CONJ(FFT(B))),其中 A, B - 长度为 2 的输入向量,用余数填充零,FFT 是快速傅里叶变换,REV_FFT 是反向变换,CONJ 是复共轭。 A和B的虚部最初是零,实部是对应像素线的灰度值。 CCF的结果也很复杂,每一个元素都要转化为(re^2)+(im^2)。
  • 结果的最大元素将提供您需要的转变。
  • 你能告诉我一个如何实现的例子吗?我仍在寻找答案:-(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2021-12-26
  • 2016-12-12
  • 2014-02-18
  • 2019-10-31
相关资源
最近更新 更多