Pynote

Python、機械学習、画像処理について

画像認識 - face_recognition ライブラリで顔認識を試す。

概要

face_recognition ライブラリを使って、顔認識を行う方法を紹介する。

pynote.hatenablog.com

顔認識

顔認識とは、顔を予め登録されている人物の顔と照合し、それが誰かを特定する技術である。
画像を与えて顔認識を行う際は次の2つのステップが必要である。

  • 顔検出: 画像から顔の領域を検出する。
  • 顔認識: 顔を予め登録されている人物の顔と照合し、誰かを特定する。
  • 顔認証: 顔認識を利用して、認証を行うこと。顔も人間の身体的特徴なので、生体認証の一種である。 (例: 顔認証でスマホのパスワードを解除するシステム)

顔の特徴

顔認識の際の2つの顔が似ているかどうかは次のように判断する。

1. 人が他人を区別する際は、目や鼻、輪郭などの特徴を元に判断している。それを画像認識で行うために、まず顔画像からそうした特徴を抽出し、特徴量に変換する。
face_recognition ライブラリでは、face_encodings() で画像に含まれる顔をそれぞれ特徴量に変換することができる。

2. 特徴量同士を比較する。face_encodings() で画像から抽出された特徴と登録済みの顔の特徴量の類似度を距離関数で比較する。これは、face_distance() で計算できる。


sample1.png 検出対象の画像 (オバマ大統領を含む歴代大統領の画像)


sample2.jpg 登録されている顔画像 (オバマ大統領)

import face_recognition
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt


def draw_face_locations(img, locations):
    fig, ax = plt.subplots(figsize=(9, 9))
    ax.imshow(img)
    ax.set_axis_off()
    for i, (top, right, bottom, left) in enumerate(locations):
        w, h = right - left, bottom - top
        ax.add_patch(mpatches.Rectangle(xy=(left, top), width=w, height=h,
                                        ec='orange', lw=3, fill=None))
        ax.text(left, top - 30, 'No {}'.format(i), color='k', backgroundcolor='w')
    plt.show()

# 画像を読み込む。
img1 = face_recognition.load_image_file('sample1.png')  # 検出対象の画像
img2 = face_recognition.load_image_file('sample2.jpg')  # 登録されている人物の画像

# 検出対象の画像から顔検出する。
locations1 = face_recognition.face_locations(img1, model='cnn')
draw_face_locations(img1, locations1)

# 登録されている人物の画像から顔検出する。
locations2 = face_recognition.face_locations(img2, model='cnn')
draw_face_locations(img2, locations2)

# 検出対象の顔から特徴量を抽出する。
encodings = face_recognition.face_encodings(img1, locations1)

# 登録されている人物の顔から特徴量を抽出する。
encoding = face_recognition.face_encodings(img2, locations2)

# 登録されている人物の顔の特徴量 encoding[0] と検出対象の各顔の特徴量 encodings
# との距離を計算する。
dist = face_recognition.face_distance(encodings, encoding[0])
print(dist)  # [0.38737437 0.85547596 0.88470516 0.77036085 0.85636135]

# 登録されている人物の顔の特徴量 encoding[0] と最も距離が近い特徴量を持つ顔
print('最も距離が近いNo', np.argmin(dist))  # 最も距離が近いNo 0

検出対象の画像の No 0 が登録されているオバマ大統領の顔と最も類似している結果になり、合っていることがわかる。