目的

ラズパイで撮影した画像を使って、画像の類似度チェックを行いたいと思います。


類似度チェックとは

この記事で行う、類似度チェックとはどういうことかと言いますと。。

まずは、以下のような、リモコンをラズパイで撮影しました。
この向きの状態を基準とします。



次にリモコンを少し向きを変えた状態のものを、2つ撮影します。
1つ目は真横に傾けたものAとします


もう一つは基準からほんの少しだけ傾けたものBとします。



上記の画像AとBで、どちらが基準に近い状態かのチェックを行います。

人間の目でひと目見れば、Bの方が基準の画像に近いです。
これをプログラム上で判断できるようにします。

pythonのOpenCVライブラリを使用すれば、簡単に基準となる画像との類似度を数値化することができます。


判定プログラム

今回は以下のような pythonプログラム(matching.py )を作成しました。

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

import cv2

# 1.比較元イメージを読み込む
okImage = cv2.imread("./okImage.JPG")

# 2.カメラでの撮影
cap = cv2.VideoCapture(0)
ret, frame = cap.read()
taImage = frame

# 3.比較する
orb = cv2.ORB_create()
kpOk, desOk = orb.detectAndCompute(okImage, None)
kpTa, desTa = orb.detectAndCompute(taImage, None)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(desOk, desTa)
matches = sorted(matches, key = lambda x:x.distance)
dist = [m.distance for m in matches]

# 4.比較結果を出力する
print(sum(dist) / len(dist))
coImage = cv2.drawMatches(okImage,kpOk,taImage,kpTa,matches[:10], None, flags=2)
cv2.imwrite("./coImage.JPG", coImage)

ざっくりの説明ですが、

1.の「okImage.JPG」は

予め撮影していた  基準  となるリモコン画像を指定しておきます。以下の基準画像のことです。

2.では

現在ラズパイのカメラの前にあるリモコン画像を撮影します。
プログラム実行時のリモコンの向き A もしくは B の状態の画像を取得できます。

3.では

OpenCVライブラリを使った比較処理を行っています。
最終的に、比較結果の画像に使われるmatches変数と類似度を表すdist変数を求めます。

4.では

プログラム実行後のコンソールに類似値を表示しているのと比較結果の画像をcoImage.JPGという名前で保存しています。


リモコンを傾けて上記プログラムを実行すると

$ python matching.py 


その状態が撮影され、基準のokImage.JPGと比較します。


まずA

の状態のリモコンでプログラムを実行します。

すると、類似値が表示され、比較画像(coImage.JPG)が実行ディレクトリに保存されます。

$ python matching.py 
72.73684210526316


比較画像については、基準Aが並んでいて、リモコンのいろんな箇所がカラフルな線で結ばれています。

プログラム実行後に表示される数値については、 このカラフル線の長さを図っている ようです。


次にB

のようにして、プログラムを実行しました。

今回も類似値が表示され、比較画像(coImage.JPG)が実行ディレクトリに保存されます。
※画像は上書きされるので注意です。

$ python matching.py 
37.648648648648646


今回は類似値は37となりました。
A72とは2倍違います。

似た画像だと類似値37、似ていない場合は72になるということで、
類似値が小さい方が類似度が高いよう(似ている画像) となるようです。


先に述べた通り、カラフル線の長さのようなので、
類似値が0になることは無いかと。

今回のプログラムを用いると
基準となる画像を用意しておくことで、
あるタイミング撮影した画像との類似度を調べる
事ができるようになりました。

今回は以上です。