Python OpenCV3.1 で特徴量マッチング


Python + OpenCV3.1 で 特徴量を検出しての画像マッチングを試してみました。
使用した検出方法は A-KAZE、KNN です。

A-KAZE(ACCELERATED-KAZE)は、有名な SURF や SHIFT と同様の検出アルゴリズムです。
SURF や SHIFT は著作権の関係で OpenCV では contrib ライブラリ行きになってしまっていますが、A-KAZE は core ライブラリから使用できます。

KNN(K-Nearest Neighbor algorithm)は、参考にした記事によると探索空間から最近傍のラベルをK個選択し、多数決でクラスラベルを割り当てるアルゴリズムだそうです。
二通りの探索方法、総当たり法(Brute-Force)と高速近似近傍探索法(FLANN: Fast Library for Approximate Nearest Neighbors)がありますが、今回は BFM で探索しています。

FLANN も試してみたのですが、僕の環境では cv2.error: /tmp/opencv3-20160705-3167-qqbjck/opencv-3.1.0/modules/python/src2/cv2.cpp:163: error: (-215) The data should normally be NULL! in function allocate とでて実行できませんでした。(参考にした記事でも実行できなかったようです…)

下記が今回試したテストコードです。

# coding: utf-8 
import cv2
import numpy as np

# 比較元の画像
img1 = cv2.imread("test.jpg")

# A-KAZE検出器の生成
akaze = cv2.AKAZE_create()

# カメラ
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4,480)
cap.set(5, 15)

# detect
def detect():
	while(cap.isOpened()):
		ret, frame = cap.read()

		# 特徴量の検出と特徴量ベクトルの計算
		kp1, des1 = akaze.detectAndCompute(img1, None)
		kp2, des2 = akaze.detectAndCompute(frame, None)

		# BFM 生成
		bf = cv2.BFMatcher()

		# 特徴量ベクトル同士を BFM&KNN でマッチング
		matches = bf.knnMatch(des1, des2, k=2)

		# 全部だと激重になるのでデータを間引きする
		ratio = 0.6
		good = []
		for m, n in matches:
			if m.distance < ratio * n.distance:
				good.append([m])

		# 特徴点同士を描画してつなぐ
		img3 = cv2.drawMatchesKnn(img1, kp1, frame, kp2, good, None, flags=2)

		# 画像表示
		cv2.imshow('frame', img3)

		if cv2.waitKey(1) & 0xFF == ord('q'):
			break

	cap.release()
	cv2.destroyAllWindows()


if __name__ == '__main__':
	detect()

カメラのキャリブレーションから姿勢推定を行って、これを検出に利用するとマーカーレス AR のようなこともできそうですね。(適当w)

今回参考にした記事:http://qiita.com/olympic2020/items/caac014b7ab246faf6b1
記事とはあまり関係ないけど姿勢推定についての自分用メモ:http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_calib3d/py_pose/py_pose.html