I have a use case where im trying to align a stack of very similar images that have different exposures, some light some dark. This stack aligns to a final target image. The target image has been edited but the homography is pretty much the same, just different lighting. How can i improve alignment? Here is what the script i've tried that have produced the best results, however it's still ghosting. # Alignment parameters RANSAC_THRESHOLD = 2.5 # Even stricter RANSAC threshold MATCH_RATIO = 0.5 # Even stricter ratio test MIN_MATCHES = 15 # More required matches MASK_HEIGHT_RATIO = 0.4 # Only use bottom 60% of image def feature_align_sift(final_img, raw_img): final_gray = cv2.cvtColor(final_img, cv2.COLOR_RGB2GRAY) raw_gray = cv2.cvtColor(raw_img, cv2.COLOR_RGB2GRAY) final_eq = cv2.equalizeHist(final_gray) raw_eq = cv2.equalizeHist(raw_gray) sift = cv2.SIFT_create() kp1, des1 = sift.detectAndCompute(final_eq, None) kp2, des2 = sift.detectAndCompute(raw_eq, None) if des1 is None or des2 is None or len(kp1) < 4 or len(kp2) < 4: print("⚠️ Not enough features for alignment.") return raw_img, None # FLANN ratio test FLANN_INDEX_KDTREE = 1 index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1, des2, k=2) good = [m for m, n in matches if m.distance < 0.7 * n.distance] if len(good) < 4: print("⚠️ Not enough good matches for homography.") return raw_img, None src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2) H, mask = cv2.findHomography(dst_pts, src_pts, cv2.RANSAC, RANSAC_REPROJ_THRESH) if H is None: print("⚠️ Homography estimation failed.") return raw_img, None aligned = cv2.warpPerspective(raw_img, H, (final_img.shape[1], final_img.shape[0]), flags=cv2.INTER_CUBIC) return aligned, H def compute_valid_region(H, raw_shape, final_shape): h_raw, w_raw = raw_shape[:2] corners = np.float32([[0,0],[w_raw,0],[w_raw,h_raw],[0,h_raw]]).reshape(-1,1,2) warped = cv2.perspectiveTransform(corners, H) x, y, w_box, h_box = cv2.boundingRect(warped) # clamp x = max(x, 0) y = max(y, 0) w_box = min(w_box, final_shape[1] - x) h_box = min(h_box, final_shape[0] - y) return x, y, w_box, h_box When I run this on my images, I expect to get perfect alignment, however the results cause ghosting and misalignment, I’ve included a picture here showing the misaligned image. enter image description here I expect to get perfect alignment of the target and final images and I’m a bit unsure where to go from here as I’ve tried orb, sift, and surf with pretty much every variation of settings and interpolation methods. Continue reading...