import cv2
import numpy as np
def align_images(img1, img2):
# Detect ORB features and compute descriptors.
orb = cv2.ORB_create(nfeatures=5000)
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
# Match features using BFMatcher with Hamming distance.
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)
# Apply Lowe's ratio test to filter good matches.
good_matches = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good_matches.append(m)
if len(good_matches) < 4:
raise ValueError('Not enough good matches to compute homography.')
# Extract location of good matches.
src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)
# Compute homography using RANSAC to remove outliers.
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
# Warp img1 to align with img2.
height, width = img2.shape[:2]
aligned_img = cv2.warpPerspective(img1, H, (width, height))
return aligned_img, H, mask
# Example usage:
# img1 = cv2.imread('image1.jpg')
# img2 = cv2.imread('image2.jpg')
# aligned_img, H, mask = align_images(img1, img2)
# cv2.imwrite('aligned.jpg', aligned_img)