Edited at
AidemyDay 8

顔画像から類似度を計算する


概要

乃木坂46のメンバー(斎藤飛鳥さん、生田絵梨花さん、白石麻衣さんなど)の顔と欅坂46の長濱ねるさんの顔がどれだけ類似しているかを出力するコードを作成しました。

スクリーンショット 2018-11-21 22.23.20 1.png

Confidenceが0に近くなれば、似ているということになります。

トレーニングに使用した画像をテストデータとして使用するとConfidenceが0になるので注意です。


トレーニングデータ・テストデータを用意する

PythonでGoogle Custom Search APIを使い画像収集してみた

これを参考に画像のスクレイピングをしてみてください!


類似度を計算するscript

OpenCVで乃木坂46秋元真夏と銀シャリ鰻和弘の類似度を調べてみた

こちらの記事を参考に作成してみました。


similarity.py

import cv2

import os
import numpy as np
from PIL import Image
import re
import os.path

# トレーニング画像
train_path = './train_乃木坂images'

# テスト画像
test_path = './test_images'

# Haar-like特徴分類器
cascadePath = './haarcascade_frontalface_alt.xml'
faceCascade = cv2.CascadeClassifier(cascadePath)
recognizer = cv2.face.LBPHFaceRecognizer_create()

# フォルダ内の画像を習得
def get_images_and_labels(path):
# 画像を格納する配列
images = []
# ラベルを格納する配列
labels = []
for f in os.listdir(path):
# 画像のパス
image_path = os.path.join(path, f)
# 白黒で読み込み
image_pil = Image.open(image_path).convert('L')
# Numpyの配列に格納
image = np.array(image_pil, 'uint8')
# Haar-like特徴分類器で顔を検知
faces = faceCascade.detectMultiScale(image)
# 検出した画像の処理
for(x, y, w, h) in faces:
# 200×200にリサイズ
roi = cv2.resize(image[y: y + h, x: x + w], (200, 200), interpolation=cv2.INTER_LINEAR)
#画像を配列に格納
images.append(roi)
int_number = re.findall("\d+", f)
for number in int_number:
labels.append(int(number))

return images, labels

# トレーニング画像を取得
images, labels = get_images_and_labels(train_path)

# トレーニング実施
recognizer.train(images, np.array(labels))

# テスト画像を取得
test_images, test_labels = get_images_and_labels(test_path)

in_jpg= os.listdir('./test_images')
for i in range(len(in_jpg)):
# テスト画像に対して予測実施
label, confidence = recognizer.predict(test_images[i])
# 予測結果をコンソール出力
print("Confidence: {:.2f}".format(confidence))


次にsimilarity.pyをカメラを起動させて画像を取得し、画面に類似度を出力させるコードも作成してみました。


camera.py

import numpy as np

import cv2
import os

if __name__ == '__main__':

print(" * Loading pre-trained model ...")
cascadePath = './haarcascade_frontalface_alt.xml'
faceCascade = cv2.CascadeClassifier(cascadePath)
recognizer = cv2.face.LBPHFaceRecognizer_create()
# recognizerのloadは次回の記事で触れます
recognizer.read('./sample_model.yml')

print(' * Loading end')

cap = cv2.VideoCapture(0)

# フレームの取得
ret,frame = cap.read()

# 文字のフォント設定
font = cv2.FONT_HERSHEY_PLAIN
# 文字のサイズ設定
font_size = 5

while(True):
ret, frame = cap.read()
if ret == True:
# Webカメラからの画像を白黒画像として読み込み
image_pil = 299/1000 * frame[:, :, 0] + 587/1000 * frame[:, :, 1] + 114/1000 * frame[:, :, 2]
image = np.array(image_pil, 'uint8')
# Haar-like特徴分類器で顔を検知
image1 = faceCascade.detectMultiScale(image)
if len(image1) > 0 :
x, y, w, h = image1[0][0], image1[0][1], image1[0][2], image1[0][3]
# 200×200にリサイズ
image2 = cv2.resize(image[y: y + h, x: x + w],(200, 200), interpolation=cv2.INTER_LINEAR)
# 類似度を予測
label, predict_Confidence = recognizer.predict(image2)
# 類似度を画面に表示
cv2.putText(frame,str(predict_Confidence),(50,700),font,font_size,(255,255,0),4)
cv2.imshow('Show', frame)

#1msecキー入力待ち
cv2.waitKey(1)
else:
break


次回の記事

毎回similarity.pyを実行していると時間がかかるので、次回は、recognizerSaveして、FlaskでrecognizerLoadし、類似度をブラウザで出力するAPIを作成してみたいと思います!

参考記事

OpenCVを使って誰の顔なのかを推定する(Eigenface, Fisherface, LBPH)

OpenCVで乃木坂46秋元真夏と銀シャリ鰻和弘の類似度を調べてみた

OpenCV ビデオCapture