画像中の位置だけわかれば良いだけで、テンプレートマッチングでも
良いのだけれど、角度が付くと厄介だったりします。
そこで特徴量で、テンプレートマッチング的な使い方をやってみようかと思います。
課題
A-KAZE検出器使用マッチングを行い検索先画像中より、検索元画像の四隅位置を取得します。
(A-KAZEの選択は適当です)
サンプル画像
検索元画像(テンプレート画像)
検索先画像
手順
- A-KAZE検出器の生成する。
- 特徴量の検出と特徴量ベクトルの計算を行う。
- 特徴量ベクトル同士をマッチングを行う。
- 画像間のホモグラフィ行列(RANSACメソッド)の推定を行う。
- 画像4隅の角座標を計算する。
実行環境
- Python 3.7.3 Anaconda
- OpenCV 3.4.1
- numpy 1.16.4
コード
import cv2
import sys
import copy
import numpy as np
def searchPosition(templ_img, query_img, good_match_rate=0.30):
# A-KAZE検出器の生成
detector = cv2.AKAZE_create()
templ_kp, templ_des = detector.detectAndCompute(templ_img, None)
# 特徴量の検出と特徴量ベクトルの計算
query_kp, query_des = detector.detectAndCompute(query_img, None)
# マッチング
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 特徴量ベクトル同士をマッチング
matches = bf.match(query_des, templ_des)
# 特徴量をマッチング状況に応じてソート
matches = sorted(matches, key = lambda x:x.distance)
good = matches[:int(len(matches) * good_match_rate)]
# 位置計算
src_pts = np.float32([templ_kp[m.trainIdx].pt for m in good])
dst_pts = np.float32([query_kp[m.queryIdx].pt for m in good])
Mx, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC)
# 画像4隅の角座標を取得
th = templ_img.shape[0]
tw = templ_img.shape[1]
pts = np.array([[[0,0], [0,th-1],[tw-1,th-1],[tw-1,0]]], dtype=np.float32)
dst = cv2.perspectiveTransform(pts,Mx)
return Mx, np.int32(dst)
結果画像
青の矩形は、検索元画像(テンプレート画像)の4隅を示します。
赤の十字は、検索元画像(テンプレート画像)の中心を示します。
結果
検出しているようだが、縮小しているのか?ちょっとずれている。
撮像をもうちょっとまともにやればいいのかは不明。今後の課題かな。
対象物のθ方向傾き角度や、拡大縮小率やらいろいろ取り出すことができます。
でもテンプレートマッチングでは、相関係数で相関具合を知ることができますが、
この場合どうしたものかと。マッチング距離全体をどのように表現すべきか。
これも今後の課題かな。
参考
@ka10ryu1さんの
画像から特徴量を抽出し、透視変換行列を導出して画像を変形する
本来であれば上記ページだけでも良く、わざわざ書く必要あるのかなとも
思いましたが書いちゃいました。
以上