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

User Note

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

近年、セキュリティ対策や入退室管理など、様々な分野で顔認証技術の活用が進んでいます。

しかし、顔認証システムを自社や個人で導入するには、専門的な知識や高価な機器が必要となる場合が多く、導入のハードルが高いと感じている方も多いのではないでしょうか。

今回は、オープンソースのPyTorchの顔認証ライブラリであるfacenet-pytorchを利用して、簡易的な顔認証サーバーを構築する方法をご紹介します。

顔認証とは

顔認証(Face Recognition)とは、カメラなどで撮影した画像から顔の特徴を抽出し、データベースに登録された顔画像と照合することで個人を識別する技術です。顔認証は、主に以下のステップで構成されます。

  1. 顔検出(Face Detection): 画像の中から顔の位置を特定します。
  2. 特徴抽出(Feature Extraction): 特定された顔領域から、目や鼻、口などの位置関係や形状などの特徴を抽出します。顔の形状やパーツの配置などを数値化したものです。
  3. 照合(Matching): 抽出された特徴とデータベースに登録された顔の特徴を比較し、一致度を算出します。
  4. 認証(Authentication): 一致度が閾値を超えた場合、本人と認証します。

顔認証は、セキュリティシステム、スマートフォンのロック解除、入退室管理など、さまざまな場面で利用されています。

顔認証ライブラリ関連について

facenet-pytorchライブラリ

facenet-pytorchライブラリは、事前学習済みのInceptionResNetV1モデルを提供しており、これによりユーザーはすぐに高精度の顔認識を利用できます。

またInceptionResNetV1のアーキテクチャは、PyTorchで容易に実装できるため、多くの研究者や開発者が独自の用途に合わせてモデルを構築しています。

Faissライブラリ

Faiss(Facebook AI Similarity Search)は、Facebook AIが開発した、大規模なベクトルデータの中から「類似したベクトル」を高速に検索するためのライブラリです。

Faissは、以下の特徴を持っています。InceptionResNetV1で抽出した特徴量の登録データを検索するのに使用します。

Faissの特徴
  1. 高い認識精度
  2. 高速な処理速度:大量の画像データを高速に処理できます。
  3. シンプルなAPI:RESTful APIを提供しており、簡単に統合できます。
  4. 軽量: リソース消費が少なく小規模なサーバーでも動作します。
  5. オープンソース

顔認証サーバーの構築方法

ここでは、顔認証ライブラリ関連の他に必要なフレームワーク、ライブラリを使用して全体で顔認証WEBサーバーとして稼働するものを構築します。

利用するアプリケーションはhttps://github.com/masayay/maifaceで公開されているものを使用します。これを利用して簡易的な顔認証サーバーを構築する手順をご紹介します。

環境構築

  1. Python3およびpipのインストール
  2. 顔認証ライブラリ関連および必要なライブラリのインストール
  3. WEBサーバー関連のインストール

全体構成のイメージ

インストールの実際

言語はpython3が必要です。筆者がインストールしたOSはAlmaLinux9.5でRHEL9系ディストリビューションであれば、Python3.9が利用できます。

# python --version
Python 3.9.21
機能 ライブラリ、アプリケーション

概略

認証の探索部分の根幹

PyTorch

開発元はMeta (旧Facebook)社深層学習で広く使われているオープンソースのフレームワーク。
以前にAI画像推論に利用した時はTensorFlowを使いました。
研究開発や柔軟性を重視するならPyTorchが良いです。大規模なシステムやプロダクション環境での利用を考えているならTensorFlowを選択します。

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が無料で使用できますので、自宅サーバーからの自動設定に便利です。

国内最大級!登録実績680万件

バリュードメイン公式サイトをみる

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サイト構築が可能。
 顔認証ログの可視化や運用画面の作成などにも活用できます。

ぜひチェックしてみてください。

バリュードメインでは、
【 .com : 790(1個目) /.co.jp : 2,000】のドメイン割引SALE、
ドメイン・サーバー同時契約でドメイン更新費用永久無料(年間最大3,858円お得)
などお得な特典やキャンペーンが盛りだくさん!
是非、お得なこの機会にご利用ください。最新のキャンペーンはこちらから

ドメイン取得ならValue Domain

▽キャンペーン開催中!
コアサーバーでは、V2プランとドメインの同時申し込みで
ドメインが実質0円(年間最大3,882円お得)になるサーバーセット割特典、
V2プランが初期費用無料20%OFF(月額390円→312円)春のネットスタート応援SALE
を展開中です。
是非、お得なこの機会にご利用ください!
最新のキャンペーンは
こちらから

超高速化を実現するレンタルサーバー CORESERVER

ユーザーノートの記事は、弊社サービスをご利用のお客様に執筆いただいております。

執筆者:苗場 翔様

医療メーカーで新素材研究開発後、電機メーカーで制御器系システム開発を経てIT系マルチエンジニアをしています。またデザイン思考を実践し、アート思考などのいろんな思考方法に興味があります。

Posted by admin-dev


おすすめ関連記事

service

Value Domain
ドメイン取得&レンタルサーバーなら
Value Domain
ドメイン登録実績600万件を誇るドメイン取得・管理サービスと、高速・高機能・高品質なレンタルサーバーや、SSL証明書などを提供するドメイン・ホスティング総合サービスです。
目次へ目次へ