テトラポット技術ブログ「TetLab」

社会人3年目エンジニアのブログ。趣味での開発や仕事で得た知見などを書いて行こうと思います。

PythonとOpenCVを用いた顔の類似度判定についての話

ハッカソンで使用したOpenCVを用いた顔の類似度判定について話をしようと思います。

環境

Python 3.5.2 OpenCV 3.1.0

やりかた

どうやって顔の類似度の判定を行うのかというと、特徴点のマッチングをします。簡単にいうと、判定したい2画像の特徴点を抽出し、それらの距離を比較します。

今回は、ジェフ・ベゾスの顔写真をターゲットとして、ビル・ゲイツスティーブ・ジョブズの顔写真と比べてみようと思います。

01.png f:id:tetrapod117:20170928163409p:plain

02.png

f:id:tetrapod117:20170928163426p:plain

target.png f:id:tetrapod117:20170928163448p:plain

コード

imagesというフォルダに比較したい顔写真とターゲットとなる写真を入れてください。

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

import cv2
import os

TARGET_FILE = 'target.png'
IMG_DIR = os.path.abspath(os.path.dirname(__file__)) + '/images/'
IMG_SIZE = (200, 200)
target_img_path = IMG_DIR + TARGET_FILE
target_img = cv2.imread(target_img_path, cv2.IMREAD_GRAYSCALE)
target_img = cv2.resize(target_img, IMG_SIZE)

bf = cv2.BFMatcher(cv2.NORM_HAMMING)

# ORBとAKAZEは特徴点や特徴量を抽出するアルゴリズム
# コメントアウトを調節することによりどちらでも行える

# detector = cv2.ORB_create()
detector = cv2.AKAZE_create()

# ターゲットの写真の特徴点を取得する
(target_kp, target_des) = detector.detectAndCompute(target_img, None)

print('TARGET_FILE: %s' % (TARGET_FILE))

files = os.listdir(IMG_DIR)
for file in files:
if file == '.DS_Store' or file == TARGET_FILE:
continue

comparing_img_path = IMG_DIR + file
try:
comparing_img = cv2.imread(comparing_img_path, cv2.IMREAD_GRAYSCALE)
comparing_img = cv2.resize(comparing_img, IMG_SIZE)
# 比較する写真の特徴点を取得する
(comparing_kp, comparing_des) = detector.detectAndCompute(comparing_img, None)
# BFMatcherで総当たりマッチングを行う
matches = bf.match(target_des, comparing_des)
#特徴量の距離を出し、平均を取る
dist = [m.distance for m in matches]
ret = sum(dist) / len(dist)
except cv2.error:
# cv2がエラーを吐いた場合の処理
ret = 100000

print(file, ret)

実行結果

ジェフ・ベゾスの顔写真を用いて、ビル・ゲイツスティーブ・ジョブズの顔写真と比べた結果が以下になります。 01.pngビルゲイツで、02.pngスティーブ・ジョブズです。

 

TARGET_FILE: target.png
01.png 128.7171717171717
02.png 123.4949494949495

距離の平均が近い方が似ているということなので、今回は02.pngつまりジョブズの写真の方が若干類似度が高いという感じになりました。

あとがき

今回は拾い物の画像で検証したため、写真の顔の位置などが違い、あまり高い類似度は出せませんでしたが、これを顔の位置がほぼ同じ場所で撮影した場合にはかなり高い類似度が出ると思います。(R-Stack Hack Dayで使用した写真ではもっと高かったので...)

画像の類似度判定といえば、機械化学習で行うイメージですが、このように機械化学習を行わなくても、簡単な類似度チェックは行えるということは覚えておいて欲しいですね。