特徴量+位置合わせ

画像位置合わせ:SIFTから深層学習まで - Qiita

OpenCV - 特徴点マッチングで物体検出、移動、回転量を推定する - pystyle

Pythonによる写真画像の位置合わせ | キャンプ工学

画像から特徴量を抽出し、透視変換行列を導出して画像を変形する - Qiita

ORB特徴量を用いて、ホモグラフィ変換を行う - Qiita

import cv2
import numpy as np

MAX_FEATURES = 500
GOOD_MATCH_PERCENT = 0.15

def alignImages(im1, im2):
    # 特徴量の抽出と記述子の計算
    detector = cv2.ORB_create(MAX_FEATURES)
    keypoints1, descriptors1 = detector.detectAndCompute(im1, None)
    keypoints2, descriptors2 = detector.detectAndCompute(im2, None)
   
    # 特徴量のマッチング
    matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING)
    matches = matcher.match(descriptors1, descriptors2, None)

    print(matches)

    
    # 特徴量をスコアでソート ハミング距離などで定義可能
#    matches.sort(key=lambda x: x.distance, reverse=False)
    matches = sorted(matches, key=lambda x: x.distance)

    # スコアのよい特徴量上位 N%を抽出
    numGoodMatches = int(len(matches) * GOOD_MATCH_PERCENT)
    matches = matches[:numGoodMatches]

    # 特徴量マッチングの結果の描画
    imMatches = cv2.drawMatches(im1, keypoints1, im2, keypoints2, matches, None)
    cv2.imwrite("matches.png", imMatches)

    # 特徴点と記述子の対応をとる
    points1 = np.zeros((len(matches), 2), dtype=np.float32)
    points2 = np.zeros((len(matches), 2), dtype=np.float32)

    for i, match in enumerate(matches):
        points1[i, :] = keypoints1[match.queryIdx].pt
        points2[i, :] = keypoints2[match.trainIdx].pt

    # 射影変換行列の算出と適用
    h, mask = cv2.findHomography(points1, points2, cv2.RANSAC)
    height, width, channels = im2.shape
    im1Reg = cv2.warpPerspective(im1, h, (width, height))
    
    return im1Reg



#実行用
if __name__ == '__main__':
    # 画像補正のリファレンス
    #    refFilename = "origin.png"
    refFilename = "lena.jpg"
    imReference = cv2.imread(refFilename, cv2.IMREAD_COLOR)
    
    # 射影補正ターゲットの画像
#    imFilename = "target.png"
    imFilename = "lena_copy.jpg"
    im = cv2.imread(imFilename, cv2.IMREAD_COLOR)
    
    # 射影変換の適用
    imReg = alignImages(im, imReference)
    
    # 補正した画像の保存
    outFilename = "aligned.png"
    cv2.imwrite(outFilename, imReg)

    imdiff = cv2.absdiff(imReference,imReg)
    cv2.imshow("diff",imdiff)