[Python] Better alignment techniques for large shifts in lighting with SIFT

Discussão em 'Python' iniciado por Stack, Fevereiro 16, 2025.

  1. Stack

    Stack Membro Participativo

    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...

Compartilhe esta Página