顔認識

顔検出・認識ライブラリ face_recognition を使って簡単な顔認識を行う。あらかじめ pip install face-recognition でインストールしておく。モジュール face-recognition,face-recognition-models,dlib,click がインストールされる。face_detection,face_recognition という二つのコマンドライン版のツールもインストールされるので,わざわざ Python でプログラムを書かなくてもいろいろ遊べる。詳しくはこちらに解説がある。

Mac でインストールするには CMake が必要(brew install cmake)。

開発環境が入っていない Windows の場合は Google Colaboratory を使うほうが楽であろう。ただ,なぜだか不明だが dlib がうまく動かないので CUDA を使わないように再インストールした(かなり時間がかかる):

!pip install --upgrade -v --install-option="--no" --install-option="DLIB_USE_CUDA" dlib
!pip install face-recognition

以下では faces_me というディレクトリに私の顔写真が10枚,弟の顔写真が1枚入っているとする。私の顔写真は,メガネをしていなかったころの比較的若いころのものから現在のものまで入っている。

import face_recognition
import pathlib

path = pathlib.Path("faces_me")
names = [p for p in path.iterdir() if p.match("*.jp*g")] # .jpg .jpeg

# あるいは import glob で name = glob.glob("faces_me/*.jp*g")

def encoding(name): # 128次元のエンコーディング
    img = face_recognition.load_image_file(name)
    return face_recognition.face_encodings(img)[0]

enc = [encoding(name) for name in names]

dist = [face_recognition.face_distance(enc, e) for e in enc] # 距離行列

# 表示(0.5より大きければ * を付ける)
for i in range(1, len(names)):
    for j in range(i):
        if dist[i][j] > 0.5:
            print(f" {dist[i][j]:4.2f}*", end="")
        else:
            print(f" {dist[i][j]:4.2f} ", end="")
    print()

結果は次のようになった:

 0.24 
 0.37  0.35 
 0.32  0.34  0.29 
 0.37  0.38  0.33  0.35 
 0.32  0.34  0.36  0.32  0.36 
 0.37  0.37  0.36  0.38  0.29  0.33 
 0.46  0.45  0.46  0.50  0.43  0.37  0.41 
 0.43  0.44  0.46  0.43  0.38  0.38  0.40  0.46 
 0.38  0.41  0.36  0.30  0.34  0.32  0.35  0.42  0.38 
 0.53* 0.59* 0.56* 0.56* 0.54* 0.56* 0.55* 0.54* 0.60* 0.59*

最後のものが弟の写真である。東洋人については精度が落ちがちな米国製のライブラリだが,とりあえず正しく見分けることができた。デフォルトでは 0.6 を閾値とするようであるが,それでは私と弟が区別できない。

ネットで拾ってきた顔写真10枚を入れたフォルダでも同様に試してみた:

 0.70*
 0.63* 0.65*
 0.60* 0.77* 0.64*
 0.55* 0.69* 0.60* 0.61*
 0.63* 0.67* 0.53* 0.58* 0.64*
 0.92* 0.77* 0.81* 0.88* 0.86* 0.82*
 0.61* 0.58* 0.50* 0.62* 0.63* 0.51* 0.76*
 0.42  0.70* 0.54* 0.57* 0.52* 0.52* 0.86* 0.50 
 0.73* 0.60* 0.61* 0.73* 0.77* 0.59* 0.71* 0.49  0.71*

0.42 というのは小さすぎると思って調べたら,画像では別人のように見えたけれど実は同一人物であった。0.50 と 0.49 は完全に別人のはずだがたまたま小さい値になったようである。距離 0.49 のペアは性別まで違うのに,不思議である。

ひょっとして米国人ならもっと見分けられるのか。そこで Wikipedia の 2020 Democratic Party presidential primaries にある15人の民主党候補の顔写真を取ってきて調べたら,113x160 ないし 123x160 の小さな画像にもかかわらず,どの距離も 0.6 を超えていた。

 0.82*
 0.85* 0.91*
 0.89* 0.98* 0.90*
 0.85* 0.83* 0.98* 0.90*
 0.67* 0.75* 0.91* 0.99* 0.80*
 0.92* 0.88* 0.77* 0.94* 0.91* 0.84*
 0.82* 0.80* 0.95* 0.65* 0.82* 0.89* 0.92*
 0.73* 0.71* 0.84* 0.83* 0.81* 0.71* 0.90* 0.80*
 0.83* 0.85* 0.75* 0.90* 0.95* 0.94* 0.74* 0.87* 0.87*
 0.73* 0.89* 0.81* 0.85* 0.83* 0.90* 0.95* 0.85* 0.79* 0.77*
 0.90* 0.86* 0.91* 0.81* 0.65* 0.88* 0.94* 0.79* 0.80* 0.94* 0.83*
 0.76* 0.77* 0.84* 0.88* 0.88* 0.82* 0.86* 0.81* 0.77* 0.79* 0.84* 0.90*
 0.92* 0.94* 0.73* 0.86* 0.86* 0.87* 0.85* 0.86* 0.85* 0.78* 0.88* 0.91* 0.91*
 0.72* 0.83* 0.88* 0.90* 0.77* 0.65* 0.89* 0.90* 0.73* 0.82* 0.82* 0.88* 0.73* 0.82*

やはり日本人には最適化されていないようだ。日本人の場合は閾値を 0.5 より少し小さくする必要がある。

ところでこの民主党大統領候補の一人 Andrew Yang は AI についても発言しているちょっと変わった候補だが,AI の大家 Andrew Ng 先生と名前も顔も似ている。Andrew Ng に載っている写真と上記 Andrew Yang の写真を比較してみたら,距離 0.412 であった。同一人物?!