普段はインフラエンジニアをやっている柳です。今回は顔認証ウェブサーバーの構築に挑戦しました。顔認証を提供する為にはバックエンドで機械学習による画像の解析処理が必要となります。この解析処理は日々研究され様々な手法が発表されています。今回はインターネット上で公開されているものを流用し構築します。言語はフロントにhtml, javascript、バックエンドにpythonを用います。これらの言語の知識があれば構築可能ですのでぜひ挑戦してください。
1.完成イメージ
ブラウザ上でリアルタイムに顔認証結果を表示させることをゴールとします。
2.H/W構成
リアルタイム画像解析処理はGPUによる高速な演算処理が必要となります。サーバーはGPUボード(Nvidia製、GPUメモリー4GB以上推奨)を搭載したPC、クライアントはカメラ付ノートパソコン、タブレット、スマホです。サーバー&クライアント間の通信はHTTPSとなります。
3.サーバー構成
フロント(HTML, API) のウェブアプリケーションフレームワークはFastAPI、バックエンドの機械学習フレームワークにはPyTorchを利用します。その他ミドルウェアとしてnginx(リバプロ、SSL証明書管理), gunicorn(HTTPサーバー), Faiss(近似最近傍探索比較)を用います。またクライアント側のカメラ起動にWebRTCのAPIを用います。
上記設計に至った比較結果です。
PyTorch vs TensorflowTensorflowはPyTorchと比較し動作が遅く感じられました。kerasのライブラリで比較を行ったことが起因していると思います。*keras: TensorFlowやTheano上で動くニューラルネットワークライブラリ、TensorFlow上の高レベルAPIFastAPI vs FlaskFastAPIがFlaskよりレスポンスが早いという情報があった為です。実際2通り開発しFastAPIの方が機械学習と相性が良いと感じました。共にWebSocket通信可能なため好みで良いと思います。Faiss vs 他特微比較アルゴリズム(近似最近傍探索比較)はこちらのページのデータを参考にしました。
FaissのみがGPU対応しています。FaissにはIndexFlatL2とIndexIVFFlat(ボロノイ領域を用いた比較)があり共に実装を行いました。画像データが少ない場合はIndexFlat2による総当り比較で十分高速です。
4.顔認証論理図
顔認証システムの論理図です。画像入力から結果出力まで3ステップあります。
(1)顔検出
画像から人の顔を検出する工程です。画像から顔のみを切り抜き次の工程に渡します。顔検出のアルゴリズムは下記ページを参考にさせて頂きMTCNN(マルチタスク畳込みニューラルネットワーク)を採用しました。今回の顔認証システムで演算処理が一番長いステップです。>参考ページ
(2)特徴量抽出
顔画像から顔の特徴量を抽出(数値化)するステップです。今回はInceptionResnetV1を採用しました。最終的には512次元(個)の数値をもつ特徴量ファイル(NumPy形式)とします。 *NumPy: 数値計算のためのライブラリで、ベクトルや行列の演算といった数値処理を得意にしている
(3)特徴量比較
顔の特徴量を比較し一番特徴量が近いファイル名と値を返します。比較結果が0に近い程、顔の特徴量が近く同一人物と判定できます。ただ、この特徴量は同一人物でも写真が同じでない限り同じ数値にはなりません。顔の色相、彩度、明度が異れば違う数値となります。この比較結果の閾値のチューニングも顔認証では重要なポイントです。
0.1以下:ほぼ同一人物0.5以上:似た人1以上:全く別人0以下(マイナスの場合):比較しているファイルにエラーが含まれている
処理速度
ModelCore i5 2.11GHzGTX 1080 Ti(1)顔検出MTCNN(540x960)158 msec60 sec(2)顔特徴量抽出InceptionResnetV176 msec19 sec(3)顔特徴量比較Faiss(1000名)1 msec0 msec
5.ブラウザ動作設計
画像取得から認証結果表示まで全て1画面で完了するようjavascriptで実装しています。クライアント側でリアルタイムに表示されるカメラ映像の上に、サーバーからの解析結果を表示させます。こちらのページを参考にさせて頂きました。
WebRTC API(getUserMedia)にてカメラを起動カメラデータをリアルタイムでImage canvas(HTMLで定義)にレンダリングImage Canvasから画像として取得しblob化blobデータをサーバーへpost画像から顔を検知し特微量抽出、近似検索し解析解析結果をWSGIに返すjson形式でクライアントへ解析結果送付(x,y,height,width,probability,userid,groupid,…)結果をDraw Canvas(HTMLで定義, Image Canvas上にレイヤリング)へレンダリング
6.顔認証システムのThread Safe化
顔認証システムのスレッドセーフ化について解説します。顔認証のアプリケーションはgunicornのワーカー数に応じてメインメモリ領域とGPUメモリ領域にデプロイされます。GPUメモリには①顔認識(MTCNN)、②特徴量抽出(InceptionResnetV1)、③特徴量ファイル(IndexFlatL2)がロードされます。 今回の実装では1ワーカーあたりGPUメモリを1.5G消費していました。2ワーカーなら3G消費することとなります。 MTCNNやInceptionResnetV1のモデルはGPUメモリにロードされた後、データが変化することはありません。しかしFaissは画像の「登録&削除」によりデータが変化します。GPUメモリにロードされたデータの変化はワーカー間では共有されない為、ワーカー間で全てのイベントを共有する(全てのワーカーに対して同じイベントを発生させる)仕組みが必要となります。この問題を解決するためにFaiss Event Managerを定義し全てのイベントを共有メモリ(テキストファイル・Redis)経由で管理するよう実装します。またFaiss Event Managerは親プロセスから分離し子プロセス化しイベントを適時検知&実行できるようにします。
7.開発環境準備
開発はWindows 10がインストールされたカメラ付ノートPC1台で進めます。全てを1台で完結させるため若干CPUパワーを必要としますが高速にデバッグ可能です。Intel Core i5で4FPS(4秒に1回認証結果表示)程の速度です。(モデルの学習やファインチューニングを行う場合は、Google ColaboratoryのGPUで行うと高速です。)*ファインチューニング: 既存の学習済モデル(出力層以外の部分)を、重みデータを一部再学習して特徴量抽出機として利用する
まずAnacondaをインストールし必要なライブラリをconda/pipでインストールします。最後に今回のアプリケーションをgithubからダウンロードしコンフィグしuvicornで立ち上げます。
(1)Anacondaインストール
こちらのページが参考になるかと思います。
(2)パッケージインストール
Anaconda Promptを開き開発に必要なpkgをインストールしていきます。
# pytorch, torchvision ※CPUモード
conda install pytorch torchvision cpuonly -c pytorch
# facenet-pytorch
pip install facenet-pytorch
# webサーバー関連
conda install -c conda-forge fastapi python-multipart nest-asyncio
conda install -c conda-forge uvicorn[standard]
conda install -c conda-forge websockets
conda install aiofiles jinja2
# faiss
conda install -c conda-forge faiss
# redis関連
conda install -c anaconda redis-py
(3)仮想環境作成
base環境をコピーし開発用のpoc環境を作成します。
conda create -n poc --clone base
conda activate poc
(4)git clone
アプリケーションをダウンロードします。
#gitインストール
conda install -c anaconda git
# clone
git clone https://github.com/masayay/maiface.git
(5)Config編集
# maifaceへ移動リネーム
mv conf_sample.py conf.py
# フォルダ作成&必要に応じてconf修正
C:\maiface
C:\maiface\embeddings
C:\maiface\cache
(6)Uvicornでアプリケーション起動
# アプリケーションディレクトリへ移動
cd maiface
# アプリケーション起動
uvicorn face_api:app
下記メッセージが表示されれば起動成功です。
FaceDetector started on device: cpu
Faiss index initialized. People: 1 Faces: 2
Faiss event manager started: Text
Started server process
Waiting for application startup.
Application startup complete.
Uvicorn running on [http://127.0.0.1:8000 (Press CTRL+C to quit)]
(7)接続テスト
ブラウザで 「顔認証画面」を開きます。 →グループ選択、ID入力、キャプチャ取得し登録します。 ※手順(1)~(6)実行後上記URLへアクセス可能です。
次に「顔認証画面」を開きます。 →先程のIDとグループが画面に表示されれば成功です。 ※手順 (1)~(6) 実行後上記URLへアクセス可能です。
以上で顔認証ウェブサーバーの開発環境の構築は完了です。本番用(Linux)構築手順はgithubに記載していますので参照ください。
顔認証もオープンソースを駆使し構築できることがわかりました。顔認証等のAI分野もオープンソースとしてもっと開発が進みAIが相互連携するようになれば面白いと感じます。
関連記事はこちら
https://developers.gmo.jp/18245/