AI DeepLearning Python プログラミング

【python できること】pytorch facenetでAI 顔認証のアルゴリズム、実装方法の説明

顔認証は数年以上前からあり、生活に溶け込んでいる技術でもあります。

技術内容に差異はあれど、スマフォにパソコン、防犯カメラ、セキュリティゲートなどに使われているのではないでしょうか?

hituji
この顔認証技術を使ったアプリケーションを開発したいが、

どうしたら良いのかわからない!

そんな方はこの記事を参考にしてみてください。

 

本記事の内容

  • 顔認証とは
  • 顔認証技術の考え方
  • 顔認証を実装

 

顔認証の良いところは、顔は体の一部なので忘れることがなく、カードなどを取り出すといったことも不要です。

また、ICタグなど費用や配布などの準備をする必要がなく、システムを提供する側にとってもメリットがあります。

デメリットはマスク着用に弱かったり、ベンダーから購入しようとすると費用が高いなどでしょうか?

 

本記事では、顔認証技術と実装方法について理解できます。

ベンダーに頼らず、無料で顔認証アプリが開発できるようになります。

 

スポンサーリンク

顔認証とは

簡単に言えば、「カメラに写っている人」は誰?というのを「登録してある人」の顔と照合することです。

「登録してある人」というのは事前に、データベースにある社員の顔写真とかになります。

「カメラに写っている人」はセキュリティゲートとかのカメラの前にいる人などです。

アプリケーションによってカメラでなくても良いのですが、1対複数の顔を比較します。

顔認証技術の考え方

では、どうやって登録されいている人の顔とカメラに写っている顔が一致している!と精度よく確認できているのでしょうか?

照合方法

まず照合方法について説明していきます。

 

数値化

ディープ ニューラルネットワーク(DNN)によって、以下のステップで顔を数値化(ベクトル化)します。

  1. カメラの画像に顔があるか検出
  2. 顔を切り取って画像サイズを変更
  3. 顔の画像をディープニューラルネットワークに通して、数値化(ベクトル化)

2の画像サイズはどれくらい、3の数値化を何個にするかは人それぞれですが、

今回使う「facenet」は160×160にリサイズして、512個の数値にします。

類似度確認

顔が映った画像が512個の数値になったら、この数字を使って類似度を算出します。

これは、登録してある人は事前に数値化していますし、カメラに映っている人もすぐに数値化されます。

あとは、登録済みの数値と比較していき、類似度の高い(顔が似ている)データがあれば認証し、1つもなければ未登録者ですということになります。

類似度の算出にはコサイン類似度というものを求めるのが一般的です。

pythonのコードでは下記で求めることができます。

import numpy as np

def cos_similarity(p1, p2):
    return np.dot(p1, p2) / (np.linalg.norm(p1) * np.linalg.norm(p2))

詳しい使い方は、実装の箇所で説明いたします。

学習方法

実装するだけであれば、必要ないので、簡単に考え方だけ説明します。

先ほど512の数値化にすると言いましたが、この数値を

  • AさんとAさんを比較した場合は似た数値になるように
  • AさんとBさんを比較した場合は似てない数値になるように

というふうになるように、512個の数値で違いが判断できるようにディープラーニングで学習させていきます。

顔認証を実装する

pytorchの顔認証のライブラリで調べると「facenet」というライブラリがgithubにありましたので、これを活用させていただきます。

人の骨格検知などもそうですが、人の体に関するAIは自分では学習させず、すでに学習済みのものをありがたく使わせていただきます。

今回もfacenetにはすでに学習済みのものが提供されているので、それをそのまま使っていくので、すぐ実装が可能です。

インストール

インストールはQuickStartのところでも紹介してありますが、pipを使ってインストールしていきましょう。

pip install facenet-pytorch

他にも、pytorch、pillow、numpyとかが必要となりますが、インストールされてない方はインストールしてください。

実装例

ブルース・ウィルスとジェイソン・ステイサムを比較してみましょう。

左から順に仮にカメラに写った人と、登録された人に分けます。

  1. (仮)カメラに写った人:ブルースウィルス
  2. (仮)登録された人1:ブルースウィルス
  3. (仮)登録された人2:ジェイソンステイサム

1と2、1と3を比較していきます。

私はこの画像を使いますが、ご自身の写真や適当な写真を用意して試してください。

必要なライブラリの読み込み

まず、必要なライブラリの読み込みをします。

# ライブラリの宣言
from facenet_pytorch import MTCNN, InceptionResnetV1
from PIL import Image
import numpy as np

1つ目がfacenetのAIモデルです。

他は画像ライブラリのPILと行列演算に使うnumpyです。

AIモデルの宣言

次に、顔の場所を検出して切り取るAIモデルと512個の数値にするAIモデルを宣言します。

最初は、学習済みモデルをダウンロードするので、時間がかかります。

# 顔検出のAI
# image_size: 顔を検出して切り取るサイズ
# margin: 顔まわりの余白
mtcnn = MTCNN(image_size=160, margin=10)

# 切り取った顔を512個の数字にするAI
# 1回目の実行では学習済みのモデルをダウンロードしますので、少し時間かかります。
resnet = InceptionResnetV1(pretrained='vggface2').eval()

 

3つの画像を512個の数値化

次に、3つの画像を読み込んで、顔の検出、リサイズ、512個の数値化の処理です。

処理詳細は、コードのコメントに記載しておきます。

# 三人分の比較をします。
# 1つ目をカメラで取得した人として
# 2、3つ目を登録されている人とします。
image_path1 = "images1.jpeg"
image_path2 = "images2.jpeg"
image_path3 = "images3.jpeg"

# (仮)カメラで取得した方
# 画像データ取得
img1 = Image.open(image_path1) 
# 顔データを160×160に切り抜き
img_cropped1 = mtcnn(img1) 
# save_pathを指定すると、切り取った顔画像が確認できます。
# img_cropped1 = mtcnn(img1, save_path="cropped_img1.jpg")
# 切り抜いた顔データを512個の数字に
img_embedding1 = resnet(img_cropped1.unsqueeze(0))

# (仮)登録されたカメラと同じ人
img2 = Image.open(image_path2)
img_cropped2 = mtcnn(img2)
img_embedding2 = resnet(img_cropped2.unsqueeze(0))

# (仮)登録されたカメラと違う人
img3 = Image.open(image_path3)
img_cropped3 = mtcnn(img3)
img_embedding3 = resnet(img_cropped3.unsqueeze(0))

 

類似度計算(顔認証)

最後に、512個の数字から類似度を計算します。

類似度にはコサイン類似度を使っていきます。

# 類似度の関数
def cos_similarity(p1, p2): 
    return np.dot(p1, p2) / (np.linalg.norm(p1) * np.linalg.norm(p2))

# 512個の数字にしたものはpytorchのtensorという型なので、numpyの方に変換
p1 = img_embedding1.squeeze().to('cpu').detach().numpy().copy()
p2 = img_embedding2.squeeze().to('cpu').detach().numpy().copy()
p3 = img_embedding3.squeeze().to('cpu').detach().numpy().copy()

# 類似度を計算して顔認証
img1vs2 = cos_similarity(p1, p2)
img1vs3 = cos_similarity(p1, p3)

print("1つ目と2つ目の比較", img1vs2)
print("1つ目と3つ目の比較", img1vs3)

出力結果は

1つ目と2つ目の比較 0.73812187
1つ目と3つ目の比較 0.33622512

動作結果

1つ目と2つ目の類似度:0.73812187

1つ目と3つ目の類似度:0.33622512

となっています。同じ人と違う人で大きく値が離れていることがわかります。

値が大きいと似ているということなので、類似度>0.7で同じ人であるという判断にすると良いと思います。

同様に日本人で試しても精度よく判定してくれます。

どうでしょう、ライブラリのおかげで簡単に実装できますね。

これでオリジナルの顔認証アプリケーションが作れると思います。

 

実際にデスクトップアプリケーションの作り方は、次の記事を参照ください。

参考【python できること】pytorch facenetでAI 顔認証アプリ開発する方法

続きを見る

 

Pythonスキルを習得したら、ぜひ活用しましょう!

>> Python 副業の始め方紹介【隙間時間 で可能】

-AI, DeepLearning, Python, プログラミング