使用ORB算法的OpenCV图像对齐

3
我需要精确对齐两个图像。为此,我使用了增强相关系数(ECC)。这给了我很好的结果,除了旋转角度较大的图像。例如,如果参考图像(基本图像)和测试图像(我想对齐的图像)旋转了90度,则ECC方法无法工作,这是根据findTransformECC()文档的说明正确的。
因此,我必须使用特征点对齐方法进行一些粗略的对齐。我尝试了SIFT和ORB,但在两者中都遇到了同样的问题。它适用于某些图像,而对于其他图像,得到的变换会向错误的方向移动或旋转。
这些是输入图像: 参考图像 需要对齐的图像 我认为问题是由错误的匹配引起的,但如果我只使用10个关键点并缩小距离,那么所有关键点似乎都是好的匹配(当我使用100个关键点时,我得到完全相同的结果)。
这是匹配的结果: 在此输入图片描述 这是结果: 结果 如果您比较旋转后的图像,它会向右移动并且上下颠倒。 我错过了什么?
这是我的代码:
        # Initiate detector
    orb = cv2.ORB_create()

    # find the keypoints with ORB
    kp_base = orb.detect(base_gray, None)
    kp_test = orb.detect(test_gray, None)

    # compute the descriptors with ORB
    kp_base, des_base = orb.compute(base_gray, kp_base)
    kp_test, des_test = orb.compute(test_gray, kp_test)

    # Debug print
    base_keypoints = cv2.drawKeypoints(base_gray, kp_base, color=(0, 0, 255), flags=0, outImage=base_gray)
    test_keypoints = cv2.drawKeypoints(test_gray, kp_test, color=(0, 0, 255), flags=0, outImage=test_gray)

    output.debug_show("Base image keypoints",base_keypoints, debug_mode=debug_mode,fxy=fxy,waitkey=True)
    output.debug_show("Test image keypoints",test_keypoints, debug_mode=debug_mode,fxy=fxy,waitkey=True)

    # find matches
    # create BFMatcher object
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    # Match descriptors.
    matches = bf.match(des_base, des_test)
    # Sort them in the order of their distance.
    matches = sorted(matches, key=lambda x: x.distance)


    # Debug print - Draw first 10 matches.
    number_of_matches = 10
    matches_img = cv2.drawMatches(base_gray, kp_base, test_gray, kp_test, matches[:number_of_matches], flags=2, outImg=base_gray)
    output.debug_show("Matches", matches_img, debug_mode=debug_mode,fxy=fxy,waitkey=True)

    # calculate transformation matrix
    base_keypoints = np.float32([kp_base[m.queryIdx].pt for m in matches[:number_of_matches]]).reshape(-1, 1, 2)
    test_keypoints = np.float32([kp_test[m.trainIdx].pt for m in matches[:number_of_matches]]).reshape(-1, 1, 2)
    # Calculate Homography
    h, status = cv2.findHomography(base_keypoints, test_keypoints)
    # Warp source image to destination based on homography
    im_out = cv2.warpPerspective(test_gray, h, (base_gray.shape[1], base_gray.shape[0]))
    output.debug_show("After rotation", im_out, debug_mode=debug_mode, fxy=fxy)

你有没有找到这个问题的答案?我也在旋转时遇到了“走位”翻译的问题。图像的正常翻译工作得很好,但是一旦图像旋转,单应性矩阵的翻译部分(在我的情况下,estimateRigidTransform效果更好)就不会保持不变(当围绕中心旋转时应该保持不变)。 - Scuba Kay
@ScubaKay 嗯,我有点作弊:D 因为我知道在裁剪后电路板将成为一个矩形,它将是“竖立的”(矩形的较短边与水平线平行)或“横放的”(较长边将与水平线平行)。所以我只是将其中一张图片旋转了4次90度,并在每次旋转后比较了两张图片。然后我简单地选择了最相似的旋转图像。之后ORB就像个冠军! - hory
1个回答

0
这个问题的答案既平凡又令人恼火。假设这是我遇到的同样问题(我认为是的):
问题和解释 大多数相机保存带有EXIF标签的图像,其中包括“定向”值。从OpenCV 3.2开始,当使用cv.imread()加载图像时,该方向标记将自动读取,并根据标记对图像进行定向(有8种可能的定向,包括90度旋转、镜像和翻转)。一些图像查看应用程序(如Linux Mint Cinnamon中的Image Viewer和Adobe Photoshop)会以EXIF定向标记的方向显示旋转后的图像。其他应用程序(如QGIS和OpenCV <3.2)忽略该标记。如果您的图像1具有方向标记,而图像2也具有方向标记,并且您在OpenCV中使用ORB进行对齐(我没有尝试过SIFT),则在读取EXIF定向标记的应用程序中打开时,您对齐的图像2将显示正确的方向(与图像1相同)。但是,如果您在忽略EXIF定向标记的应用程序中同时打开两个图像,则它们看起来方向不同。当一个图像具有方向标记而另一个没有时,这个问题变得更加明显。

一种可能的解决方案 在将图像读入OpenCV之前,请删除EXIF方向标记。现在,在OpenCV 3.4(也许是3.3?)中,有一个选项可以忽略标记加载图像,但是当这样做时,它们被加载为灰度(1通道),如果你需要颜色就没用了,cv.imread('image.jpg',128) 其中128表示“忽略方向”。所以,我使用Python中的pyexiv2从我的图像中删除冒犯的EXIF方向标记:

import pyexiv2
image = path_to_image
imageMetadata = pyexiv2.ImageMetadata(image)
imageMetadata.read()
try:
    del imageMetadata['Exif.Image.Orientation']
    imageMetadata.write()
except:
    continue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接