とある技術者の研鑽結果

SIerのお仕事でたまった鬱憤を最新テクノロジー勉強で晴らすためのブログです

OpenCV - SIFTを使った特徴量算出及びマッチング

Web+DB Express Vol.83を購入したところ特集として画像認識が

いやあWeb技術者もComputer Visionが必要な時代かあ。。。と思い読み進めると、Javaでのコーディング例も載っていてかなり実用的でいい感じ

しかしJavaよりかはPythonでお手軽にコーディングしたいよね!ってことで、掲載のと同じSIFTを使った特徴量算出及びマッチング、画像表示をPythonで書いてみました

import cv2

# 画像を読み込み白黒化する
im = cv2.imread('test.jpg')
im2 = cv2.imread('test2.jpg')
gray= cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
gray2= cv2.cvtColor(im2,cv2.COLOR_BGR2GRAY)
	
# SIFT特徴量算出アルゴリズムモジュールを呼び出す		
sift = cv2.SIFT()

# 特徴量を算出する
kp ,des = sift.detectAndCompute(gray, None)
kp2 ,des2 = sift.detectAndCompute(gray2, None)

# 類似点を算出する
matcher = cv2.DescriptorMatcher_create("FlannBased")
matches = matcher.match(des,des2)

# 類似点を表示する
img3 = cv2.drawMatches(gray,kp,gray2,kp2,matches[:10])

簡単、簡単♪と実行してみてると

AttributeError: 'module' object has no attribute 'drawMatches'

は????
え、python経由でdrawMatchesって使えないの???

ネットの海をあさった結果、なんか使えなさそうな雰囲気(詳しい人がいたら教えてほしいです…)
というわけでStackOverflowを参考にdrawMatchesを自作することに

import numpy as np
import cv2

def drawMatches(img1, kp1, img2, kp2, matches):
 
    rows1 = img1.shape[0]
    cols1 = img1.shape[1]
    rows2 = img2.shape[0]
    cols2 = img2.shape[1]

    out = np.zeros((max([rows1,rows2]),cols1+cols2,3), dtype='uint8')

    out[:rows1,:cols1,:] = np.dstack([img1, img1, img1])

    out[:rows2,cols1:cols1+cols2,:] = np.dstack([img2, img2, img2])

    for mat in matches:

        img1_idx = mat.queryIdx
        img2_idx = mat.trainIdx

        (x1,y1) = kp1[img1_idx].pt
        (x2,y2) = kp2[img2_idx].pt

        cv2.circle(out, (int(x1),int(y1)), 4, (255, 0, 0), 1)   
        cv2.circle(out, (int(x2)+cols1,int(y2)), 4, (255, 0, 0), 1)

        cv2.line(out, (int(x1),int(y1)), (int(x2)+cols1,int(y2)), (255, 0, 0), 1)

    cv2.imshow('Matched Features', out)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 画像を読み込み白黒化する
im = cv2.imread('test.jpg')
im2 = cv2.imread('test2.jpg')
gray= cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
gray2= cv2.cvtColor(im2,cv2.COLOR_BGR2GRAY)
	
# SIFT特徴量算出アルゴリズムモジュールを呼び出す		
sift = cv2.SIFT()

# 特徴量を算出する
kp ,des = sift.detectAndCompute(gray, None)
kp2 ,des2 = sift.detectAndCompute(gray2, None)

# 類似点を算出する
matcher = cv2.DescriptorMatcher_create("FlannBased")
matches = matcher.match(des,des2)

# 類似点を表示する
img3 = drawMatches(gray,kp,gray2,kp2,matches[:10])

これで動作は問題ないみたい
drawKeypointsはあるのになあ