顔認証ライブラリを利用して簡易顔認証サーバーを作ってみよう

近年、セキュリティ対策や入退室管理など、様々な分野で顔認証技術の活用が進んでいます。
しかし、顔認証システムを自社や個人で導入するには、専門的な知識や高価な機器が必要となる場合が多く、導入のハードルが高いと感じている方も多いのではないでしょうか。
今回は、オープンソースのPyTorchの顔認証ライブラリであるfacenet-pytorchを利用して、簡易的な顔認証サーバーを構築する方法をご紹介します。
顔認証とは
顔認証(Face Recognition)とは、カメラなどで撮影した画像から顔の特徴を抽出し、データベースに登録された顔画像と照合することで個人を識別する技術です。顔認証は、主に以下のステップで構成されます。
- 顔検出(Face Detection): 画像の中から顔の位置を特定します。
- 特徴抽出(Feature Extraction): 特定された顔領域から、目や鼻、口などの位置関係や形状などの特徴を抽出します。顔の形状やパーツの配置などを数値化したものです。
- 照合(Matching): 抽出された特徴とデータベースに登録された顔の特徴を比較し、一致度を算出します。
- 認証(Authentication): 一致度が閾値を超えた場合、本人と認証します。
顔認証は、セキュリティシステム、スマートフォンのロック解除、入退室管理など、さまざまな場面で利用されています。
顔認証ライブラリ関連について
facenet-pytorchライブラリ
facenet-pytorchライブラリは、事前学習済みのInceptionResNetV1モデルを提供しており、これによりユーザーはすぐに高精度の顔認識を利用できます。
またInceptionResNetV1のアーキテクチャは、PyTorchで容易に実装できるため、多くの研究者や開発者が独自の用途に合わせてモデルを構築しています。
Faissライブラリ
Faiss(Facebook AI Similarity Search)は、Facebook AIが開発した、大規模なベクトルデータの中から「類似したベクトル」を高速に検索するためのライブラリです。
Faissは、以下の特徴を持っています。InceptionResNetV1で抽出した特徴量の登録データを検索するのに使用します。
- 高い認識精度
- 高速な処理速度:大量の画像データを高速に処理できます。
- シンプルなAPI:RESTful APIを提供しており、簡単に統合できます。
- 軽量: リソース消費が少なく小規模なサーバーでも動作します。
- オープンソース
顔認証サーバーの構築方法
ここでは、顔認証ライブラリ関連の他に必要なフレームワーク、ライブラリを使用して全体で顔認証WEBサーバーとして稼働するものを構築します。
利用するアプリケーションはhttps://github.com/masayay/maifaceで公開されているものを使用します。これを利用して簡易的な顔認証サーバーを構築する手順をご紹介します。
環境構築
- Python3およびpipのインストール
- 顔認証ライブラリ関連および必要なライブラリのインストール
- WEBサーバー関連のインストール
全体構成のイメージ
インストールの実際
言語はpython3が必要です。筆者がインストールしたOSはAlmaLinux9.5でRHEL9系ディストリビューションであれば、Python3.9が利用できます。
# python --version Python 3.9.21
機能 | ライブラリ、アプリケーション |
概略 |
認証の探索部分の根幹 |
PyTorch |
開発元はMeta (旧Facebook)社深層学習で広く使われているオープンソースのフレームワーク。 |
facenet-pytorch |
PyTorchを使用して顔認識をするためのライブラリです。顔検出(MTCNN)と特徴抽出(InceptionResNetV1)の両方の機能を提供します。 |
|
Faiss |
Facebook AI Similarity Searchの略大規模なベクトルデータベース。顔埋め込みの高速な検索に使用。NVIDIAのGPUがあれば計算に利用されます。 |
|
Webアプリケーションサーバー | FastAPI |
ASGI(Asynchronous Server Gateway Interface)フレームワークです。非同期処理(async/await)に対応したWeb APIを構築するためのアプリケーションフレームワークです。 |
Gunicorn |
WSGI(Web Server Gateway Interface )サーバーです。WSGIとはWebアプリケーションとWebサーバーを繋ぐための「標準的な規格(プロトコル)」です。Gunicorn単体ではFastAPIを動かせませんがUvicorn(ASGIサーバー)をワーカーとして指定することで、FastAPIをGunicorn経由で実行できます。 |
|
WEBサーバー | Apache |
リバースプロキシサーバーとしてWebアプリケーションサーバーを繋ぎます。もちろん軽量のnginxを使用しても問題ありません。Webアプリケーションサーバーはポート8000で動作していますので、これをhttps(443)として動作させます。 |
pythonのライブラリをインストールするにはpipが必要ですのでインストールされていない場合はインストールを行います。
#pip --version -bash: pip: command not found # python -m pip install -U pip Successfully installed pip-25.0.1 # pip --version pip 25.0.1 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
必要なライブラリをpipでインストールします。
#pip install facenet-pytorch #pip install fastapi python-multipart nest-asyncio #pip install uvicorn[standard] Gunicorn #pip install websockets #pip install aiofiles jinja2 #pip install faiss-cpu #pip install faiss-gpu #pip install redis #pip install pillow
既に各種ライブラリをインストールされているユーザーでpipの厳格な依存関係チェックで一部ライブラリがインストールできない場合は、対象のライブラリをアップグレードする必要があります。
例えば、numpyの依存チェックでscipyのバージョンエラーの場合は-Uオプションでscipyをアップグレードします。
. . Attempting uninstall: numpy Found existing installation: numpy 1.23.1 faiss_gpu>=1.7.1.post2 Uninstalling numpy-1.23.1: Successfully uninstalled numpy-1.23.1 #ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. #scipy 1.9.0 requires numpy=1.18.5, but you have numpy 1.26.4 which is incompatible. # #pip install -U scipy scipy Successfully installed scipy-1.13.1
尚、今回のアプリケーションでscipyは必要ありませんので、未インストールの場合は依存関係チェックにscipyは対象外となります。必要ライブラリの筆者環境でのバージョンです。pip listでインストールされているライブラリのバージョンが確認できます。
Jinja2 3.1.5 aiofiles 24.1.0 numpy 1.26.4 pillow 10.2.0 pydantic 2.10.6 torch 2.2.2 torchvision 0.17.2 facenet-pytorch 2.6.0 faiss-cpu 1.10.0 faiss-gpu 1.7.2 fastapi 0.115.11 redis 5.2.1
PyTorch が導入されているか及びCUDAドライバーが有効か無効を認します。
# python >>> import torch >>> x = torch.rand(5, 3) >>> print(x) tensor([[0.1609, 0.1246, 0.4757], [0.8813, 0.9156, 0.2182], [0.0242, 0.0291, 0.1397], [0.5903, 0.2943, 0.6904], [0.5783, 0.4722, 0.7993]]) ```↑出力例 >>> import torch >>> torch.cuda.is_available() False ```↑出力例(CUDA無効の場合) >>> exit()
例では、5行3列の2次元テンソルが表示されればライブラリを利用可能です。またCUDAが有効な場合はTrueと表示され、GPUが利用できます。(今回Falseでも問題なく使用できます)
アプリケーションの構築
miface アプリケーションの複製
・直接ダウンロードする方法
https://github.com/masayay/maiface/archive/refs/heads/main.zip
でmain.zipをダウンロードする。ダウンロードしたmaiface-main.zipを適当なフォルダーに解凍します。
私の環境では、/var/www/に解凍しました。
・gitを使ってリモートリポジトリから自環境に複製する方法
#mkdir /var/www #cd /var/www #git clone https://github.com/masayay/maiface.git
どちらの方法でも構いません。ファイル構成は以下になります。
#tree –f /var/www/maiface/ |-- LICENSE.md |-- README.md |-- conf.py |-- conf_linux_sample.py |-- face_api.py |-- face_detect.py |-- feature_extraction_batch.py |-- maiface_config.py |-- nginx_sample.txt |-- requirements.txt |-- static | |-- css | | `-- main.css | `-- js | |-- getUserMedia.js | |-- objDetect.js | `-- registrationControl.js |-- systemd_sample.txt |-- templates | |-- recognition.html | `-- registration.html `-- utils |-- db_util.py |-- face_api_response.py `-- face_detect_util.py
アプリケーションの設定
linux用の設定ファイルをconf.pyにコピーします。
#cd maiface #cp conf_linux_sample.py conf.py
アプリケーションの起動確認
#uvicorn face_api:app INFO: FaceDetector started on device: cpu INFO: Faiss index initialized. People: 1 Faces: 3 INFO: Faiss event manager started: Text INFO: Started server process [2548670] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
curlコマンドでアクセスして反応があればこの段階ではOKです。
# curl http://127.0.0.1:8000/ INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: 127.0.0.1:55356 - "GET / HTTP/1.1" 200 OK
サーバーにGUIのWEBブラウザーがあれば、http://127.0.0.1:8000 にアクセスします。カメラ権限が要求されるので許可してください。デフォルトではローカルホスト(127.0.0.1)で動作します。これを例えば192.168.10.5として動作させる場合は以下のようにhostオプションで起動できます。
#uvicorn --host 192.168.10.5 face_api:app
これで他のクライアントPCからhttp://192.168.10.5:8000/でアクセスはできるのですが、最新のブラウザー(Google Chrome、Mozilla Firefoxなど)は、セキュリティ上の理由から、HTTP経由でのWebRTCアクセスを制限しているため、カメラが起動できません。
後の章でリバースプロキシを利用し、httpsでアクセスできるようにします。この段階では起動できるところまでの確認です。
Gunicornの設定
WSGIサーバーとしてGunicornを設定します。
#mkdir /etc/gunicorn #mv maiface_config.py /etc/gunicorn/maiface_config.py #mkdir /var/log/gunicorn #mkdir /var/lib/maiface #mkdir /var/lib/maiface/cache #mkdir /var/lib/maiface/embeddings
※/var/lib/maiface/*は、uvicorn face_api:appを実行したときに一部自動で生成されます。実行していない場合は、自分でフォルダーを作成します。
gunicornユーザーを作成し、さきほどのフォルダーのオーナーをgunicornにします。
#useradd -U -m -s /usr/sbin/nologin gunicorn #chown gunicorn:gunicorn /var/log/gunicorn #chown -R gunicorn:gunicorn /var/www/maiface #chown -R gunicorn:gunicorn /var/lib/maiface #chown -R gunicorn:gunicorn /etc/gunicorn
Gunicornでアプリケーションの起動確認
uvicornでの起動確認済みですがGunicornからの起動を確認します。
#/usr/bin/python3 /usr/local/bin/gunicorn --config /etc/gunicorn/maiface_config.py
起動プロセスを確認してみます。
# ps -eaf | grep maiface root 3750692 1 0 15:37 ? 00:00:00 /usr/bin/python3 /usr/local/bin/gunicorn --config /etc/gunicorn/maiface_config.py gunicorn 3750693 3750692 9 15:37 ? 00:00:05 /usr/bin/python3 /usr/local/bin/gunicorn --config /etc/gunicorn/maiface_config.py gunicorn 3750694 3750692 9 15:37 ? 00:00:05 /usr/bin/python3 /usr/local/bin/gunicorn --config /etc/gunicorn/maiface_config.py
解説:
3つのプロセスgunicornが走っています。Gunicornはマスター・ワーカー方式 で動作します。Gunicornのワーカー数のデフォルトは 2 です。マスター プロセス(親プロセス)と2つのワーカー プロセスの管理(起動・停止・再起動など)となります。
例えば、4コアのCPUであれば、ワーカー数を4つ程度に設定することが推奨されます
ワーカーを 4つにする場合は、/etc/gunicorn/maiface_config.py中のworkersを workers= 4にします。
動作ログは/var/log/gunicorn/maiface_error.log、アクセスログは/var/log/gunicorn/maiface_access.logに出力されます。エラー落ちする場合はmaiface_error.logを確認してください。
動作例:
/var/log/gunicorn/maiface_error.log
[2025-03-04 16:57:57 +0900] [3809987] [INFO] Starting gunicorn 23.0.0 [2025-03-04 16:57:57 +0900] [3809987] [INFO] Listening at: http://127.0.0.1:8000 (3809987) [2025-03-04 16:57:57 +0900] [3809987] [INFO] Using worker: uvicorn.workers.UvicornWorker [2025-03-04 16:57:57 +0900] [3810010] [INFO] Booting worker with pid: 3810010 [2025-03-04 16:57:57 +0900] [3810012] [INFO] Booting worker with pid: 3810012 [2025-03-04 16:58:01 +0900] [3810012] [INFO] Started server process [3810012] [2025-03-04 16:58:01 +0900] [3810012] [INFO] Waiting for application startup. [2025-03-04 16:58:01 +0900] [3810012] [INFO] Application startup complete. [2025-03-04 16:58:01 +0900] [3810010] [INFO] Started server process [3810010] [2025-03-04 16:58:01 +0900] [3810010] [INFO] Waiting for application startup. [2025-03-04 16:58:01 +0900] [3810010] [INFO] Application startup complete. [2025-03-04 16:58:33 +0900] [3810010] [ERROR] Exception in ASGI application Traceback (most recent call last): File "/var/www/maiface/face_api.py", line 82, in api_face_recognizer results = detector.face_search(img_pil, deviceid) File "/var/www/maiface/face_detect.py", line 191, in face_search faceid = self.index_ids[neighbors.squeeze()[0]] IndexError: list index out of range
起動はしているものの、face_detect.pyでIndexErrorが発生しています。顔データをまだ一度も登録していないので、データが空のためです。
アプリそのものはエラー落ちはしていませんが、このままで顔登録、顔認証を進めると今度はface_api_response.pyで別のエラーが発生して認証できません。
ただしく動作するようにface_api_response.pyのプログラムを修正します。(今回使用したpythonはバージョン3.9.21ですがバージョンによってはエラーしない場合があります。この場合は修正の必要はありません)
各関数の引数を初期化するように変更します。Optional[str]をOptional[str]=None、Optional[float]をOptional[float]=Noneに全て変更する。
. . class Group(BaseModel): groupid: Optional[str]=None groupname: Optional[str]=None . . class Face(BaseModel): faceid: Optional[str]=None groupid: Optional[str]=None userid: Optional[str]=None numfiles: Optional[int]=None . . class Message(BaseModel): mid: Optional[str]=None msg: Optional[str]=None . . class ApiResponse(Message): result: str = 'SUCCESS' groupid: Optional[str]=None userid: Optional[str]=None faceid: Optional[str]=None . . class FaceDetectResponse(BaseModel): result: str = 'no results' faceid: Optional[str]=None userid: Optional[str]=None username: Optional[str]=None groupid: Optional[str]=None groupname: Optional[str]=None probability: Optional[float]=None x: Optional[float]=None y: Optional[float]=None height: Optional[float]=None width: Optional[float]=None
アプリケーションの自動起動設定
#cp systemd_sample.txt /etc/systemd/system/maiface.service #systemctl daemon-reload #systemctl start maiface
プロセスが起動しているか確認します。先ほどと同様に3つのpython3/usr/local/bin/gunicornが起動していればOKです。
WEBサーバーと連携
WEBサーバにApacheを使ってプロキシサーバーの設定をします。WebRTCを利用し、https通信を前提としますので、SSL証明書が必要です。
SSL証明書は自己証明書かもしくはドメインを持っておられる方はLet's Encryptを利用して無料でSSL証明書を取得できます。
筆者の環境ではドメインfaceverify.sco.jpを用意しました。sco.jpはレジストラ「バリュードメイン」で取得してテスト用にいつも使っています。Value DomainではダイナミックDNSが無料で使用できますので、自宅サーバーからの自動設定に便利です。
Apache 設定例
/etc/httpd/conf.d/faceverify.conf
ServerName faceverify.sco.jp SetEnvIf User-Agent "internal dummy connection" nolog ErrorLog /projects/var/log/ssl_faceverify_sco_jp_error.log TransferLog /projects/var/log/ssl_faceverify_sco_jp_transfer.log CustomLog /projects/var/log/ssl_faceverify_sco_jp_access.log combined env=!nolog SSLEngine on SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 SSLCertificateFile /opt/dehydrated/certs/faceverify.sco.jp/cert.pem SSLCertificateKeyFile /opt/dehydrated/certs/faceverify.sco.jp/privkey.pem SSLCertificateChainFile /opt/dehydrated/certs/faceverify.sco.jp/chain.pem #プロキシサーバ設定 ProxyPreserveHost On ProxyPass / http://localhost:8000/ ProxyPassReverse / http://localhost:8000/ #####################
ProxyPreserveHost On
ProxyPass / http://localhost:8000/
ProxyPassReverse / http://localhost:8000/
の3行でリバースプロキシ―となります。SSL/TLS暗号化の処理をリバースプロキシで行いかつhttps:// faceverify.sco.jpへのアクセスは内部でhttp://localhost:8000/へのアクセスとなります。
※https://github.com/masayay/maifaceに添付されているリバースプロキシ―のサンプル設定(nginx_sample.txt)はNginx用です
Nginxで動かしたい方は、そちらを参考にしてください。
Nginxは「静的コンテンツの表示」や「リバースプロキシ」、「ロードバランサー」といったWebサーバーとしての基本的な動作を得意としています。筆者がApacheを選んだ理由はApacheがすでに検証用サーバーで動作していたためです。
WEBサーバーのリスタートで設定を反映させます。
#systemctl restart httpd
顔認証サーバーの動作の実際
システム構成
これで必要なアプリケーションは全て設定・起動しましたので、改めてシステム構成を見ておきましょう。

顔データの登録
https://faceverify.sco.jp/add/にアクセスして顔登録をします。
初めてアクセスした場合にカメラの使用許可をブラウザーから求められますので許可してください。
許可するとカメラ画像と共に登録画面が表示されます。

[capture]で自画像をキャプチャー、[restart]でやり直し、
[リストボックス]グループ名の選択(グループ名はface_api_response.pyに定義されています)、[ID入力]任意のIDを入力。
キャプチャーして良ければ[register] を押下して登録します。
faceverify.sco.jpに実際に顔データを登録していただいても構いません。サーバー側ではキャプチャーした顔画像そのものが保管されるわけではなく、内部で顔画像部分の特徴量をデータ化したファイルが/var/lib/maiface/embeddings/に.npyファイルとして保管されます。
.npyファイルはNumPyのデータ形式で、次のような情報を含みます
配列のメタデータ(データ型、次元情報)、埋め込みベクトル(512次元の浮動小数点数配列)データで1人分2ファイルが生成されます。
顔認証
https://faceverify.sco.jp/にアクセスします。

顔の範囲がリアルタイムで追尾され適合確率が50%以上の場合はグループ名とIDも表示されます。
サンプルプログラムでここまで簡単にできます。1対1認証の場合はサーチエリアを絞らないと複数人登録して画面上に複数人映るとそれぞれに適合確率が表示されます。
(※ニコニコマークはマスキング加工しています。実際は表示されません。)
眼鏡をはずして認証

眼鏡を付けている時よりも適合度は落ちますが、60%以上あるので認証できています。
眼鏡をはずして同じIDで登録すれば適合度は上がります。指紋認証で何回か場所をずらして登録するのと同じようなものです。
マスクをして認証

マスク着用時は30%を割り込んで認証はできていません。目、鼻、口、顎の位置関係で鼻、口の特徴量が欠落するためです。
帽子を被って認証

頭、顔の輪郭なども特徴量を取得しているはずですが、帽子を被っても影響はありませんでした。
サングラスをした時

設定ではIDENTICAL_DISTANCE = 0.49(conf.py)となっています。キャプチャーでは眼鏡を付けて登録していますが目そのもの特徴量が欠落するのでやはり認証はできていません。
事前学習済みのInceptionResNetV1(vggface2)使い顔の特徴を取得し、特徴量をデータ化しています。
またFaissによって顔特徴ベクトルを検索し、距離 (distance) が IDENTICAL_DISTANCE 未満なら同一人物と判定しています。どうだったでしょうかGPUなしでCPUのみでリアルタイム認証が問題なくできています。
今回、vggface2の学習済みモデルを読み込んで追加調整はしておりませんが、顔認証はある程度使い物になる結果が出ました。
vggface2学習済みモデルの一部の層のみを追加調整して再学習することで、さらに多様な応用が可能です。
例えば、自分の顔はだれと似ているのかなどです。学習済みモデルの再学習にはCPUだけでもできますが非常に時間がかかります。GPUがあるマシーンで行った方が処理は数十倍速いので、試される場合はGPUがあるマシーンもしくはAIクラウドでの実施が望ましいです。
まとめ
使用したアプリケーションの詳細はhttps://developers.gmo.jp/technology/17430/で公開されていますので参考になるかと思います。
今回は基本的な機能で顔認証サーバーを紹介しましたが、応用次第でさまざまな用途に活用できるでしょう。
顔認証サーバーに顔ログイン機能を持たせることもアプリケーションの改造で可能になりますので、興味のある方はチャレンジしてみてはと思います。
顔認証技術は今後も進化が期待される分野ですので、ぜひこの機会に試してみてください。
インターネット上に公開して本格的に運用したい場合、信頼性の高いドメインとサーバーの選定が非常に重要です。そこでおすすめなのが、バリュードメインとコアサーバーの2つのサービスです。
バリュードメイン
国内最大級の登録実績を誇る信頼性の高いドメイン取得サービス。
ダイナミックDNSの無料提供もあり、自宅サーバーでの運用にも便利です。
テスト用や学習用のサーバー公開にも最適です。
コアサーバー(CORE SERVER)V2プラン
月額390円から利用可能な高コスパのレンタルサーバー。
ドメインと同時申込でドメインが永久無料になる特典付き!
さらに、WordPress自動インストール機能搭載で、最短1分半でWebサイト構築が可能。
顔認証ログの可視化や運用画面の作成などにも活用できます。
ぜひチェックしてみてください。
ドメイン・サーバー同時契約でドメイン更新費用永久無料(年間最大3,858円お得)
是非、お得なこの機会にご利用ください。最新のキャンペーンはこちらから
ドメインが実質0円(年間最大3,882円お得)になるサーバーセット割特典、
V2プランが初期費用無料・20%OFF(月額390円→312円)春のネットスタート応援SALEを展開中です。
最新のキャンペーンはこちらから
※ユーザーノートの記事は、弊社サービスをご利用のお客様に執筆いただいております。
医療メーカーで新素材研究開発後、電機メーカーで制御器系システム開発を経てIT系マルチエンジニアをしています。またデザイン思考を実践し、アート思考などのいろんな思考方法に興味があります。