How overlap 2 images with keypoints in OpenCV Python?

33 Views Asked by At

I try to create a new picture (map) from 2 blueprints but the code is not correct.

There is an overlap between the 2 picture and I tried to find it and merge them. I'm a beginner using opencv and python so I tried to find it like that, but it's not working properly every time. If I miss converting the pictures to grayscale and blur it, sometimes it works but I need the gray one. What did I miss?

The code is:

def align_images(image1_path, image2_path):
    img1 = cv.imread(image1_path)  
    img2 = cv.imread(image2_path) 

    imgGray1 = cv.cvtColor(img1, cv.COLOR_BGR2GRAY)
    imgGray2 = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)

    blurred1 = cv.GaussianBlur(imgGray1, (5, 5), 0)
    blurred2 = cv.GaussianBlur(imgGray2, (5, 5), 0)

    threshold = 127

    dark_parts1 = np.zeros_like(blurred1)
    dark_parts1[blurred1 > threshold] = 255

    dark_parts2 = np.zeros_like(blurred2)
    dark_parts2[blurred2 > threshold] = 255

    # cv.imshow("Image 1", dark_parts1)
    # cv.imshow("Image 2", dark_parts2)

    img1 = dark_parts1
    img2 = dark_parts2

    orb = cv.ORB_create()

    kp1, des1 = orb.detectAndCompute(img1, None)
    kp2, des2 = orb.detectAndCompute(img2, None)

    bf = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True)
    matches = bf.match(des1, des2)
    matches = sorted(matches, key=lambda x: x.distance)

    if len(matches) > 10:
        src_pts = np.float32([kp1[m.queryIdx].pt for m in matches[:10]]).reshape(-1, 1, 2)
        dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches[:10]]).reshape(-1, 1, 2)

        M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 5.0)

        img1_transformed = cv.warpPerspective(img1, M, (img2.shape[1], img2.shape[0]))

        mask = np.zeros_like(img2, dtype=np.uint8)
        roi_corners = np.int32([[[0, 0], [0, img2.shape[0]-1], [img2.shape[1]-1, img2.shape[0]-1], [img2.shape[1]-1, 0]]])
        ignore_mask_color = (255,)
        cv.fillPoly(mask, roi_corners, ignore_mask_color)

        border_color = (255, 0, 0)
        border_thickness = 2

        cv.rectangle(mask, (0, 0), (mask.shape[1] - 1, mask.shape[0] - 1), border_color, thickness=border_thickness)

        img2_masked = cv.bitwise_and(img2, mask)
        img_combined = cv.add(img2_masked, img1_transformed)

        img_combined = cv.add(img2_masked, img1_transformed)

        cv.imshow("Aligned Image", img_combined)
        cv.waitKey(0)
        cv.destroyAllWindows()
    else:
        print("Error")
align_images('photos/cropped4.png', 'photos/test_map.pgm')
0

There are 0 best solutions below