いろいろな画像を見比べて、「あの画像に写ってるのアレは、この画像に写ってるコレと同じかな?」なんてことを、機械的にやるとしたら、という話。
OpenCVに頼る
難しいことは考えないで、OpenCVに頼る。自分で考えるよりも、世界中の賢い人々が考えてくれた成果物を利用するべきなのだ。
というわけで、早速、 OpenCV: Feature Detection and Descriptionを参照して、お勉強を始める。
画像を用意する
適当な著作権フリーっぽい画像もないし、自分で撮影するのも面倒なので、今回は以下の画像を適当に作った。
このutsu1.png(游明朝)と、utsu2.png(ヒラギノ角ゴシック)を使うことにする。
特徴点の抽出
まずは、http://docs.opencv.org/master/da/df5/tutorial_py_sift_intro.html に従い、utsu1.pngを走査してSIFT特徴量を重畳表示する。
img1 = cv2.imread('img/utsu1.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp1 = sift.detect(gray1)
img1_sift = cv2.drawKeypoints(gray1, kp1, None, flags=4)
すると、こんな感じ。
ところで、SIFTという手法は特許が取られているらしいので、とりあえずAKAZE法で同じように書いてみる。
AKAZE
img1 = cv2.imread('img/utsu1.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
akaze = cv2.AKAZE_create()
kp1 = akaze.detect(gray1)
img1_akaze = cv2.drawKeypoints(gray1, kp1, None, flags=4)
これによって選ばれるkeypointsは、SIFTとは違うんだけれど、それも踏まえてdetectorとして何を選ぶべきなのか?っていうのは、正直言うとよく分からない。
特徴点の比較
これは、http://docs.opencv.org/master/dc/dc3/tutorial_py_matcher.html からコピペに限る。
img1 = cv2.imread('img/utsu1.png')
img2 = cv2.imread('img/utsu2.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
akaze = cv2.AKAZE_create()
kp1, des1 = akaze.detectAndCompute(gray1, None)
kp2, des2 = akaze.detectAndCompute(gray2, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1,des2)
matches = sorted(matches, key = lambda x:x.distance)
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)
コピペしつつ、ORBではなくAKAZEを使うように変更したのと、cv2.drawMatches()の引数がチュートリアルに書いてあるものと微妙に違っているので修正してみた。
ちなみに、結果は以下のようになる。
続けて、チュートリアルの続きを進める。
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)
good = []
for m,n in matches:
if m.distance < 0.5*n.distance:
good.append([m])
img4 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)
というワケで、游明朝の鬱とヒラギノ角ゴシックの鬱の特徴点を抽出して、類似していると思われる点のマッチングまでできるようになりました。
まとめ
理論は分かってなくても、画像から特徴点抽出をすることは、OpenCVを使えば簡単にできる。