ラズパイとpythonで簡単に顔認証!

5月 5, 2021

チップの性能向上によって高負荷な顔認証がエッジデバイス(Nvidia Jetson, Google Edge TPU)で実現可能になってきています. Raspberry Piは以前のバージョンだとOpenCVも実行させただけでメモリ不足に陥っていましたが, バージョン4ではメモリが8GBに拡張され, 比較的高負荷な処理を実行することができます. 今回はラズパイだけで顔認証をテストします. ぜひお試しを!

こんな人におすすめ!
  • 安価なWEBカメラとラズパイを使って、顔認証システムを作りたい
  • 人間というカテゴライズのレベルではなく、誰かと誰かの判別をしたい
  • 本人と別人を分ける閾値設定の仕方を知りたい
  • カメラ映像上の顔の座標位置を取得したい

準備したもの

顔認証のような負荷の高いプログラムを動作させるために, メモリが8GBあるRaspberryPi4を選択しました.

ただしRaspberryPi4は消費電力が大きく, 自然放熱だけでは発熱を抑えきれなくなり, パフォーマンスが低下するので, ファンを付けるのが良く, 50℃程度にCPU温度を抑えられます. またファン付きケースを選べばスマートにパッケージングできるでしょう.

顔のキャプチャにはラズパイ純正のカメラではなく, USBカメラを活用しました. 純正でなくともラズパイで動作し, ケーブルの強度も純正のものよりあり, 安価です.

ACアダプターには通電のON/OFFスイッチがついているものにしました.

MicroSDは容量32GB, UHSスピードクラス3のものを使用しました.

セットアップ

Raspberry Pi

まずはRapberry Pi自身のセットアップをしましょう.

Rapberry Piのセットアップが完了したら, カメラの使用許可とGPUの設定をし, 再起動します.

# enable camera
sudo raspi-config
  • Enable the Raspberry Pi camera (if you have one attached)
  • Save changes and reboot.

顔認証に必要なライブラリをインストールします.

# install necessary library
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install build-essential \
    cmake \
    gfortran \
    git \
    wget \
    curl \
    graphicsmagick \
    libgraphicsmagick1-dev \
    libatlas-base-dev \
    libavcodec-dev \
    libavformat-dev \
    libboost-all-dev \
    libgtk2.0-dev \
    libjpeg-dev \
    liblapack-dev \
    libswscale-dev \
    pkg-config \
    python3-dev \
    python3-numpy \
    python3-pip \
    zip
sudo apt-get clean

OpenCVのインストール

インストール時にメモリ不足を防ぐため, 一時的にスワップ領域を拡張します.

sudo nano /etc/dphys-swapfile

< change CONF_SWAPSIZE=100 to CONF_SWAPSIZE=1024 and save / exit nano >

sudo /etc/init.d/dphys-swapfile restart

opencvをインストールします.

# install opencv
pip3 install opencv-contrib-python opencv-python

face_recognitionのインストール

Raspberry Pi用にdlibをカスタマイズしてインストールします.

# install dlib
cd
mkdir -p dlib
git clone -b 'v19.9' --single-branch https://github.com/davisking/dlib.git dlib/
cd ./dlib
sudo python3 setup.py install --compiler-flags "-mfpu=neon"

次にface_recognitionをインストールします.

# install face_recognition
pip3 install face_recognition

拡張したスワップ領域を戻します.

sudo nano /etc/dphys-swapfile

< change CONF_SWAPSIZE=1024 to CONF_SWAPSIZE=100 and save / exit nano >

sudo /etc/init.d/dphys-swapfile restart

サンプルを実行して, face_recognitionが正常にインストールできたか確認します.

顔認証用に自分の写真を撮影し, それをface_recognition/examplesフォルダにme.jpgという名前で保存します.

その後下記の通りにサンプルを実行していきます.

# OpenCVのセットアップで一度Downloadされていたら実行する必要はありません.
git clone https://github.com/tech-life-hacking/face_recognition.git

# execute samples
cd ./face_recognition/examples
python3 facerec_from_webcam_faster.py

自分の顔が四角く囲われて, meとラベル付されたらセットアップ成功です.

性能検証

サンプルのfacerec_from_webcam_faster.pyを実行すると, 左上にCPU温度, CPUメモリ消費量, GPUメモリ消費量, 右上にFPSが表示され, 顔認証のRaspberryPiへの負荷や性能を検証することができます. またそれらを時間当たりのデータでcsvdata.csvに保存するようになっています.

これらのデータを用いてRaspberryPiの顔認証性能を検証していきます.

顔認証率

大量の顔写真データであるFFHQデータセットを用いて, 自分か, そうでないかの顔認証率を出してみます.

私の画像としては下図を使用しました.

大量の顔写真データであるFFHQデータセットは以下のリンクからアクセスできます.

FFHQデータセットには僕の顔写真が含まれていないので, 僕と認証した場合, それは誤認証となります.

(顔認識率) = 1 – (誤認証数) / (顔写真総数)

下のグラフが52000枚の写真に対し, 僕かどうかの顔認証をした結果です.

縦軸は顔認証率で, 横軸は写真内の人物が僕かどうか線引きする閾値です.
その閾値が低ければ, 厳しめな判定で, 僕に似ていても僕と判別しづらいです.
一方でその閾値が高ければ, ゆるめな判定で, 僕にそんなに似ていなくても僕と判定します.

face_recognition/examples/TestAccuracy.pyで上のグラフが得られます.

ゆるめな判定閾値(FaceDistance:0.6)だと, 顔認証の精度が95.3%と比較的低くなることをグラフは示しています. 20人に1人は誤って判定してしまっています.

厳しめな判定閾値(FaceDistance:0.4)だと, 完全に誤判定しなくなっています.
サンプルのfacerec_from_webcam_faster.pyも厳しめな判定にしています.

実際の画像を例にして説明します.

FaceDistance:0.8付近の判定閾値だと下図の画像も私だと判定します.

判定閾値としては緩めなので, アジア人以外の方も検出されます.

FaceDistance:0.4付近だと下図が私と判別されます.

厳しめの判定閾値なので, アジア人かつ割と似た顔の人が検出されています.

本人だとFaceDistance:0.3くらいの判定閾値でも検出されます.

FPS

1秒間に何回顔認証しているか確かめるために, FPSを計測します.

1時間程度顔認証し続けて, FPSがどのように変化していくか計測しています.

2-4FPS(1秒間に2-4回顔認証を実行している)出ていると思います. 1秒間に2-4回顔認証を実行できれば, カメラの前に人が立って認証を行うということが十分スムーズにできると考えられます.

CPU温度

負荷の高い処理をしているので, CPU温度を計測します.

1時間程度顔認証し続けて, CPU温度がどのように変化していくか計測しています.

一定時間経過したとき, CPU温度は50.8℃で安定しました.

この値はRaspberry Piの限界温度である85℃より低く, 時間経過しても, 性能低下につながらないことがわかります.

おわりに

高性能なGPUのついていないラズパイだけでも顔認証を行うことができるということがわかりました. 皆さんも気軽に顔認証をしてみてください!