使用ORB的OpenCV图像Aligment

时间:2017-03-21 10:36:03

标签: python opencv image-processing image-registration

我需要精确对齐两幅图像。为此,我使用增强相关系数(ECC)。除了旋转很多的图像外,这给了我很好的结果。例如,如果参考图像(基本图像)和测试图像(我想要对齐)旋转90度ECC方法根据findTransformECC()的文档说明

  

请注意,如果图像经历强烈的位移/旋转,则需要粗略对齐图像的初始变换(例如,允许图像大致显示相同图像内容的简单欧几里德/相似变换)。

所以我必须使用基于特征点的对齐方法来进行粗略对齐。我尝试了SIFT和ORB,但我遇到了同样的问题。它适用于某些图像,对于其他图像,所产生的转换在错误的一侧移动或旋转。

这些是输入图像: Reference image Image to be aligned

我认为问题是由错误的匹配引起的,但如果我只使用距离较小的10个关键点,那么在我看来它们都是很好的匹配(当我使用100个关键点时,结果完全相同)

这是匹配的结果: enter image description here

这是结果: Result

如果您比较旋转的图像,它会向右移动并上下颠倒。 我错过了什么?

这是我的代码:

        # 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)

1 个答案:

答案 0 :(得分:0)

这个问题的答案既平凡又令人讨厌。假设这与我遇到的问题相同(我认为是):

问题与解释 大多数相机使用带有“方向”值的EXIF标签保存图像。从OpenCV 3.2开始,当使用cv.imread()加载图像时,将自动读取此方向标记,并且基于该标记对图像进行定向(有8种可能的方向,包括90 *旋转,镜像和翻转)。某些图像查看应用程序(例如Linux Mint Cinnamon中的Image Viewer和Adobe Photoshop)将显示沿EXIF Orientation标签方向旋转的图像。其他应用程序(例如QGIS和OpenCV <3.2)将忽略该标签。如果您的图片1具有方向标签,而图片2具有方向标签,并且您在OpenCV中使用ORB(我尚未尝试过SIFT)执行对齐,则您对齐的图片2将以正确的方向(即图片1)在读取EXIF方向标签的应用程序中打开时。但是,如果您在忽略EXIF Orientation标签的应用程序中打开两个图像,则它们看起来不会具有相同的方向。当一个图像具有方向标记而另一个图像没有方向标记时,此问题将变得更加明显。

一个可能的解决方案 在将图像读入OpenCV之前,请删除EXIF Orientation标签。现在,从OpenCV 3.4(也许是3.3?)开始,可以选择忽略标签加载图像,但是这样做后,它们将被加载为灰度(1通道),如果您需要color {{1 }}其中128表示“忽略方向”。因此,我在python中使用pyexiv2从图像中删除了令人反感的EXIF Orientation标记:

cv.imread('image.jpg',128)