前回のやり残しで、FLANNでの特徴点マッチングをやります。
特徴点のマッチング — OpenCV-Python Tutorials 1 documentation
概要
前回のおさらいですが、FLANNはFast Library for Approximate Nearest Neighborの略で、近似的に特徴量空間での最近傍点を探索する手法です。総当たりマッチングより高速で実施することができます。
やること
前回はcv2.BFMatcher()
でマッチングしましたが、今回はcv2.FlannBasedMatcher()
を使います。
これは2つのdict
型オブジェクトを引数に取ります。
dict
が何なのか分かっていないのでググる。
Pythonで辞書を作成するdict()と波括弧、辞書内包表記 | note.nkmk.me
dict
は辞書オブジェクトで、キーと値をペアで保持するものとのこと。
キー、値の型はある程度制限はあるものの、文字列および整数でないといけない、ということはなさそう。
【Python】 辞書(dict)の使い方の基本 | Hbk project
【Python】辞書型変数(dictionary) - Qiita
なぜcv2.FlannBasedMatcher()
の引数をdict
型で与えないといけないかはわかりませんが、とりあえず使ってみます。
使用画像
前回と同じシャルトル大聖堂です。
img_both = cv2.imread('Chartres_both.JPG') img_right = cv2.imread('Chartres_right.JPG') img_left = cv2.imread('Chartres_left.JPG') img_both = cv2.resize(img_both, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA) img_right = cv2.resize(img_right, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA) img_left = cv2.resize(img_left, None, fx=0.25, fy=0.25, interpolation=cv2.INTER_AREA) cv2.imshow('Image both', img_both) cv2.imshow('Image right', img_right) cv2.imshow('Image left', img_left)
実施
SIFTで特徴点マッチングして、前回の総当たりマッチングと比較します。
sift = cv2.SIFT_create() kp_both, des_both = sift.detectAndCompute(img_both, None) kp_right, des_right = sift.detectAndCompute(img_right, None) kp_left, des_left = sift.detectAndCompute(img_left, None)
FLANNのオブジェクトは、SIFTを使う場合は以下のように生成します。
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)
index_params
はアルゴリズムの選択、および関連パラメータのよう。 使用する特徴点検出器によって変えるといいようです。今回のSIFTでは1を選択していますが、ORBだと6(FLANN_INDEX_LSH)が良いようです。
search_params
は、「インデックス中の木構造を再帰的にたどっていく回数」とのこと。
これを増やすと精度が上がりますが、実行時間が伸びます。
あとはマッチングを実施しますが、チュートリアルではratio testをやっていました。
今回はこれに倣います。
matches_right = flann.knnMatch(des_both, des_right, k=2) good_matches_right = [] for m,n in matches_right: if m.distance < 0.7*n.distance: good_matches_right.append([m])
最後に結果を表示します。
img_matches_right = cv2.drawMatchesKnn(img_both, kp_both, img_right, kp_right, good_matches_right[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) cv2.imshow('Matches right', img_matches_right)
結果は前回より悪くなってしまった…
シャルトル大聖堂向かって左側は、
matches_left = flann.knnMatch(des_left, des_both, k=2) good_matches_left = [] for m,n in matches_left: if m.distance < 0.7*n.distance: good_matches_left.append([m]) img_matches_left = cv2.drawMatchesKnn(img_left, kp_left, img_both, kp_both, good_matches_left[:20], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) cv2.imshow('Matches left', img_matches_left)
こちらはまだ上の結果よりましですが、1つ明らかな誤検出があるので、前回と比べれば精度は落ちています。
扱う画像ごとにパラメータを調整したりしないといけないのか?
以上
前回総当たりマッチングをやっていましたが、その際は特に体感的に処理が遅い、ということはなく、実行してすぐに終わっていました。なのでFLANNのメリットを得ることができず。
次はチュートリアル通りで、特徴点マッチングとHomographyでの物体検出にします。