LoginSignup
16

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-12-07

概要

乃木坂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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16