🚀

2枚の画像を用いて特徴点のマッチングを行う

2023/09/21に公開

はじめに

平面射影変換を用いることで異なるカメラ姿勢間の点同士を対応づけられることを学んだ。その中で、イメージモザイキングについて知ったので、それに関連することとして、特徴点のマッチングを行う。

SIFTを用いて特徴点を表示する

少し見えにくいが、特徴点を表示。

import cv2

# 画像の読み込み
img = cv2.imread("img.jpg")

# 画像からSIFTを用いて特徴量を抽出
sift = cv2.SIFT_create()
keypoints = sift.detect(img, None)

# 特徴点の表示
img_sift = cv2.drawKeypoints(
img,
keypoints,
outImage=None,
color=None,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
)

cv2.imwrite("img_sift.png", img_sift)
元の画像 特徴点を描画した画像

マッチング結果を表示する

  • cv2.BFMatcher()を使ってBrute-Force Matcherを作成する。
    Brute-Force Matcher: 全ての特徴点同士を総当たりでマッチングする手法

  • matcher.knnMatch()によって、2枚の画像から抽出した特徴量を用いてマッチングを行う。k=2 は近傍の数を指定するパラメータで、2番目に近い特徴点までを返す。これにより、マッチングの信頼性を評価するための情報を得ることができる。

  • 各マッチング結果の対応する2つの特徴点間の距離(類似度)を比較する。k=2によって、2つの特徴点間の類似度の上位2個が取得されているので、1つ目の特徴点と2つ目の特徴点の距離が、2つ目の特徴点と3つ目の特徴点の距離よりも小さい(類似度が高い)場合、そのマッチングは信頼性が高いと判断する。そして、信頼性が高いと判断されたマッチングをgood_matchesに追加する。

# 画像の読み込み
img1 = cv2.imread("img1.jpg")
img2 = cv2.imread("img2.jpg")

# グレースケール化
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

# 画像からSIFTを用いて特徴量を抽出
sift = cv2.SIFT_create()
keypoints1, descriptors1 = sift.detectAndCompute(gray1, None)
keypoints2, descriptors2 = sift.detectAndCompute(gray2, None)

# マッチャーを作成
matcher = cv2.BFMatcher()
matches = matcher.knnMatch(descriptors1, descriptors2, k=2)

# マッチングをフィルタリング
good_matches = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
    good_matches.append(m)

# マッチングの可視化
img_matches = cv2.drawMatches(
img1,
keypoints1,
img2,
keypoints2,
good_matches,
None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS,
)

cv2.imwrite("img_matches.png", img_matches)
元の画像1 元の画像2


マッチング結果の可視化

参考

http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_feature2d/py_matcher/py_matcher.html

Discussion