【问题标题】:Image Alignment of Multispectral Images Fails with ECC多光谱图像的图像对齐失败与 ECC
【发布时间】:2021-09-15 23:51:54
【问题描述】:

我正在尝试将 RGB 图像与 IR 图像(单通道)对齐。 目标是创建一个 4 通道图像 R、G、B、IR。 为此,我使用cv2.findTransformECC,如this very neat guide 中所述。代码现在没有改变,除了第 13 行,Motion 设置为 Euclidian,因为我想在将来处理旋转。我正在使用 Python。

为了验证软件的工作原理,我使用了指南中的图像。它工作得很好,所以我想如上所述关联来自多个光谱的卫星图像。不幸的是,我在这里遇到了问题。

算法有时会收敛(经过多年),有时会因为无法收敛而立即崩溃,有时会“找到”明显错误的解决方案。在附件中,您发现从人类的角度来看,这两张图像很容易匹配,但算法失败了。图像不会以任何方式旋转,它们只是不完全相同的图像(检查边界),因此预计会发生平移运动。图片来自奥地利的新西德勒湖,来源是 Sentinelhub。

编辑:对于“有时”,我指的是使用来自 Sentinel 的不同图像。一对图像始终具有相同的结果。

我知道 ECC 不是基于功能的,这可能会造成问题。

我还读到它在某种程度上取决于初始扭曲矩阵。

我的问题是:

  1. 我用cv2.findTransformECC错了吗?
  2. 有没有更好的方法来做到这一点?
  3. 我是否应该尝试“蒙特卡罗”初始矩阵直到它收敛? (感觉不对)
  4. 您是否建议使用基于特征的算法?
  5. 如果有,是否有可用的,还是我必须自己实现?

感谢您的帮助!

【问题讨论】:

  • 你可以试试Feature Based Image Alignment
  • 感谢@Rotem 的评论。我从早上开始就这样做了,它失败了......我的意思是悲惨!这对我来说是多么糟糕,这绝对是惊人的。我将提出另一个问题,关于 SIFT 如何以及为什么无法检测和关联清晰可见的特征。

标签: python opencv image-processing image-stitching


【解决方案1】:

您是否建议使用基于特征的算法?

当然。 有many feature detections algorithms。 我一般会选择 SIFT,因为它提供了很好的匹配结果,而且运行时间非常快。

import cv2 as cv
import numpy as np

# read the images
ir = cv.imread('ir.jpg', cv.IMREAD_GRAYSCALE)
rgb = cv.imread('rgb.jpg', cv.IMREAD_COLOR)

descriptor = cv.SIFT.create()
matcher = cv.FlannBasedMatcher()

# get features from images
kps_ir, desc_ir = descriptor.detectAndCompute(ir, mask=None)
gray = cv.cvtColor(rgb, cv.COLOR_BGR2GRAY)
kps_color, desc_color = descriptor.detectAndCompute(gray, mask=None)

# find the corresponding point pairs
if (desc_ir is not None and desc_color is not None and len(desc_ir) >=2 and len(desc_color) >= 2):
    rawMatch = matcher.knnMatch(desc_color, desc_ir, k=2)
matches = []
# ensure the distance is within a certain ratio of each other (i.e. Lowe's ratio test)
ratio = 0.75
for m in rawMatch:
    if len(m) == 2 and m[0].distance < m[1].distance * ratio:
        matches.append((m[0].trainIdx, m[0].queryIdx))

# convert keypoints to points
pts_ir, pts_color = [], []
for id_ir, id_color in matches:
    pts_ir.append(kps_ir[id_ir].pt)
    pts_color.append(kps_color[id_color].pt)
pts_ir = np.array(pts_ir, dtype=np.float32)
pts_color = np.array(pts_color, dtype=np.float32)

# compute homography
if len(matches) > 4:
    H, status = cv.findHomography(pts_ir, pts_color, cv.RANSAC)

warped = cv.warpPerspective(ir, H, (rgb.shape[1], rgb.shape[0]))
warped = cv.cvtColor(warped, cv.COLOR_GRAY2BGR)

# visualize the result
winname = 'result'
cv.namedWindow(winname, cv.WINDOW_KEEPRATIO)
alpha = 5
# res = cv.addWeighted(rgb, 0.5, warped, 0.5, 0)
res = None
def onChange(alpha):
    global rgb, warped, res, winname
    res = cv.addWeighted(rgb, alpha/10, warped, 1 - alpha/10, 0)
    cv.imshow(winname, res)
onChange(alpha)
cv.createTrackbar('alpha', winname, alpha, 10, onChange)
cv.imshow(winname, res)
cv.waitKey()
cv.destroyWindow(winname)

结果(alpha=8)

编辑: SIFT 似乎不是最佳选择,因为它在其他一些示例中失败了。 Example images are in another question.

在这种情况下,我建议使用 SURF。 它是一种专利算法,因此它不附带最新的 OpenCV PIP 安装。 您可以安装以前版本的 OpenCV 或从源代码构建它。

descriptor = cv.xfeatures2d.SURF_create()

结果(alpha=8)

Edit2:现在很明显,完成这项任务的关键是选择正确的特征描述符。最后一点,我建议选择合适的motion model。在这种情况下,仿射变换比单应性更适合。

H, _ = cv.estimateAffine2D(pts_ir, pts_color)
H = np.vstack((H, [0, 0, 1]))

仿射变换结果:

【讨论】:

  • 嗨 Burak,感谢您的回复,而您在回答时我已经使用 SIFT 编写了自己的匹配(我使用了一个示例 tbf),虽然它似乎适用于这对图像(纯机会)它对其他人不起作用,我对 SIFT 如何在这里失败感到震惊。 stackoverflow.com/questions/68256426/… 查看新线程的结果。你的代码有同样的问题,就像我在另一个线程中描述的一样。它也无法匹配其他图像。
  • @Clex 我查看了新帖子,但没有图像可以尝试代码。你能用更多的例子编辑这两个帖子吗?
  • 感谢您的输入,我添加了两张图片以及如何获得自己的图片的教程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 2014-08-17
  • 2020-05-25
  • 1970-01-01
相关资源
最近更新 更多