More than 1 year has passed since last update.

AKAZE特徴量とは

OpenCV3.0.0から追加された新しい特徴量で、OpenCV2.4時代の他の特徴点アルゴリズムよりもよいとの噂を聞きます。
参考 AKAZE特徴量の紹介と他特徴量との比較

SIFTもSURFも商用NGで使えないよ!と思っていたので、AKAZEを試してみました。

python2.7での実装

OpenCV3.0.0のpythonの公式チュートリアル、リファレンスを参考にしても、そんなメソッドねーよとか怒られてしまうので、StackOverFlowの過去の人の質問やC++のコードを参考にしながら書きました。
pythonでOpenCV3.0.0動くサンプルがほとんどなくて苦戦した・・・

以下、標準入力に画像ファイルパスを2つ入れると、特徴点をトラッキングして、結果を画像出力してくれるサンプルです。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import numpy as np
import cv2
import sys

img_path = sys.argv[1]
img_path2 = sys.argv[2]

img = cv2.imread(img_path)
img2 = cv2.imread(img_path2)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

# 特徴量記述
detector = cv2.AKAZE_create()
kp1, des1 = detector.detectAndCompute(gray, None)
kp2, des2 = detector.detectAndCompute(gray2, None)

# 比較器作成
bf = cv2.BFMatcher(cv2.NORM_HAMMING)

# 画像への特徴点の書き込み
matches = bf.match(des1, des2)
matches = sorted(matches, key = lambda x:x.distance)

# 出力画像作成 表示
h1, w1, c1 = img.shape[:3]
h2, w2, c2 = img2.shape[:3]
height = max([h1,h2])
width = w1 + w2
out = np.zeros((height, width, 3), np.uint8)

cv2.drawMatches(img, kp1, img2, kp2, matches[:50],out, flags=0)
cv2.imshow("name", out)
cv2.waitKey(0)

つまづいたポイント

detectorが変わってる!

公式には、

orb = cv2.ORB()

みたいに、使用するアルゴリズムの名前の大文字で宣言するように書かれてますが、これだと通りません。

detector = cv2.ORB_create()

のように、{アルゴリズム名}_createとしてください。

drawMatchesにoutImgを引数として与えなければいけない

以前および公式には、

python-tutorialには

img3 = cv2.drawMatches(img1,kp1,img2,kp2,matches[:10], flags=2)

といった使い方だったり、

API Referenceでは

Python: cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches1to2[, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]]) → outImg

と書かれているが、実際にこれをやると、

TypeError: Required argument 'outImg' (pos 6) not found

と言われてしまう。
outImgはoptionalのはずなのに、Requiredと言われる。
こちらの問題は、stackoverflowでも議論されていた。
TypeError: Required argument 'outImg' (pos 6) not found

outImgをNoneにするだけでよいそうだが、気づかなかったので、わざわざ2枚の画像の大きさから、outImgを作成した。

# 出力画像作成 表示
h1, w1, c1 = img.shape[:3]
h2, w2, c2 = img2.shape[:3]
height = max([h1,h2])
width = w1 + w2
out = np.zeros((height, width, 3), np.uint8)

最後に

pythonでOpenCV3.0のソースを書こうとすると、リファレンス通りにいかないことがあるみたいなので、気をつけて下さい。この情報もいつまで有効かわかりません。

参考