本記事はMacで顔認識を試行した記事のRaspberry Pi版で、顔認識環境Dlibを応用した工作の作り方を紹介します。
カメラの画角の中央付近に顔が映っているとLEDが点灯し、さらにLEDが点灯中に顔を右に傾けるとサーボモーターが動いて旗を立てるという内容です。
また、Raspberry Pi(以降、ラズパイ)を使ってOpenCVとDlibそれぞれをC++/Python両言語で動かす方法についても紹介します。
入力として、画像、動画、カメラ(リアルタイム)それぞれの場合の記述例を用意しました。
Dlibは顔以外の部分を顔と誤認識することはほとんど無いので、使いやすいです。
下の動画で工作の実演やコードの解説をしていますので、よろしければご覧ください。
使用環境
以下の構成で本記事の内容を実施しました。
項目 | 内容 |
---|---|
Raspberry Pi | Raspberry Pi 4B |
カメラ | 1. Pi Camera V2.1 2. USB Webカメラ |
サーボモーター | SG90 |
LED | 抵抗なしLED |
抵抗 | LED用抵抗150Ω |
ブレッドボード | ミニブレッドボード |
配線 | ジャンパーワイヤー |
安定化電源 | 自作(参考ページ) |
ソースコード(GitHub)
GitHubからソースコードをダウンロードします。(使用するソースコードはMac版の記事と同じです)
git clone https://github.com/tak6uch1/face_recognition cd face_recognition
ディレクトリ構造は以下のようになっています。
face_recognition/ cv_cpp/ : OpenCV C++ cv_py/ : OpenCV Python dlib_cpp/ : Dlib C++ dlib_py/ : Dlib Python RPi_dlib_py_sample/ : Dlib Python sample for Raspberry Pi
画像と動画のダウンロード
以下、私が試行に使用したファイルを紹介しますが、人の顔が写っていれば他のファイルで構いません。
以下のフリー画像をダウンロードします。
以下のフリー動画をダウンロードします。
サイズは一番小さいFull HDが良いです。
カスケード分類の種類
本記事で紹介するOpenCVとDlibはいずれもカスケード分類という技術を使って顔認識を行います。
カスケード分類器についてはこちらのサイトがわかりやすく、以下の3つの手法があり、OpenCVには1. Haar-Likeと2. LBPの顔認識モデルが最初から入っていました。
- Haar-Like特徴量
物体の局所的な明暗差の組み合わせにより、画像を判別する - LBP(Local Binary Pattern)特徴量
物体の局所的な輝度の分布の組み合わせにより、画像を判別する - HOG(Histogram of Oriented Gradients)特徴量
物体の局所的な輝度の勾配方向の分布の組み合わせにより、画像を判別する
Dlibは3. HOGとSVM(サポートベクタマシン)が使われているとのことです。
環境構築
ラズパイの初期化は以下の記事にしたがって実施してください。
次に、必要なツールのインストールについて説明します。
環境構築を実行するファイルを用意していますので、順に実行します。
./install_linux1.sh ./install_linux2.sh ./install_linux3.sh
以降でOpenCVとDlibを試していきますが、すぐに工作を試したい方は、「Dlib Pythonを応用した電子工作」の章から試すことも可能です。
OpenCV C++で顔認識
cv_cppディレクトリに移動します。
cd cv_cpp
ビルドディレクトリを作ってその下でcmake
を使ってビルドします。
mkdir build cd build cmake .. cmake --build .
これでbuildディレクトリにimage
, video
, webcam
ができれば成功です。
あらかじめダウンロードした画像ファイルを与えてimage
を実行します。
./image ~/Downloads/TC9V9A4577_TP_V4.jpg
以下のように顔に四角い枠が付けば成功です。
qを押すと終了します。
実行結果の画像は、output.jpg
として保存されます。
次に動画の顔認識を実行します。
./video ~/Downloads/video.mp4
以下のように顔に四角い枠が付けば成功です。
顔ではない部分にマークが付くこともありますね。
ほぼ正面を向いている場合の認識率は良いですが、顔の一部が隠れたり、横向きや顔を傾けた場合に認識できないようです。
実行結果の動画はoutput.mp4
として保存されます。
qを押すか、動画が終了するのを待ちます。
次ににパソコンのカメラ入力で顔認識を実行します。
./webcam
自分の顔に四角い枠が付けば成功です。
うまくいきましたでしょうか?
qを押して終了すると最後に以下のようにFPSを表示します。
FPS=10
10は私の実行結果で、1秒間に10フレームの処理ができたという意味です。
C++版はビルドに失敗することもあると思いますので、このページの下の方にあるトラブルシューティングも参考にしてください。
また、C++版がうまくいかなくても次のPython版は試せますので、あきらめずに挑戦してみてください。
OpenCV Pythonで顔認識
cv_pyディレクトリに移動します。(cv_cpp/buildにいる状態を想定しています)
cd ../../cv_py
以下のコマンドで画像入力の顔認識を実行します。
python3 image.py --image ~/Downloads/TC9V9A4577_TP_V4.jpg
以下のように顔に四角い枠が付けば成功です。
qを押すと終了します。
実行結果の画像は、output.jpg
として保存されます。
次に以下のコマンドで動画の顔認識を実行します。
python3 video.py --video ~/Downloads/video.mp4
以下のように顔に四角い枠が付けば成功です。
qを押すか、動画が終了するのを待ちます。
実行結果の動画は、output.mp4
として保存されます。
次にパソコンのカメラ入力で顔認識位を実行します。
python3 webcam.py
自分の顔に四角い枠が付けば成功です。
うまく実行できましたでしょうか?
qを押して終了すると、C++版と同様にFPSを表示します。
FPS=10.0
Pythonはnumpyなど、C++で記述されたコンパイル済みのモジュールを呼び出して実行しているため、C++版と同程度の処理速度だったと思われます。
ビルド等の前処理が不要で同程度の処理速度であれば、通常はPython版を使うことで良いでしょう。
Dlib C++で顔認識
dlib_cppディレクトリに移動します。(cv_pyにいる状態を想定しています)
cd ../dlib_cpp
buildディレクトリを作ってその下でcmakeを使ってビルドします。
mkdir build cd build cmake .. cmake --build .
学習済みモデルデータへのシンボリックリンクを作成します。
ln -s ../../shape_predictor_68_face_landmarks.dat
以下のコマンドで画像ファイル入力の顔認識を実行します。
./image_dlib ~/Downloads/TC9V9A4577_TP_V4.jpg
以下のように顔に対する赤い枠と目、鼻、口など顔のパーツに緑のマークが付きます。
ウィンドウの✕印またはターミナル上でCtrl+cで終了します。
実行結果の画像はoutput.jpg
に保存されます。(顔のパーツ認識結果は保存していません)
次に動画の顔認識を実行します。
./video_dlib ~/Downloads/video.mp4
以下のように顔に対する赤い枠と目、鼻、口など顔のパーツに緑のマークが付きます。
OpenCVの顔認識と比べると顔ではない場所にマークが付くことはなく、認識精度は良いですね。
ウィンドウの✕印またはターミナル上でCtrl+cで終了します。
実行結果の動画はoutput.mp4に保存されます。(顔のパーツ認識結果は保存していません)
次にパソコンのカメラ入力で顔認識を実行します。
./webcam_dlib
以下のように顔に対する赤い枠と目、鼻、口など顔のパーツに緑のマークが付きます。(下図のGIF動画だとわかりづらいですが)
うまくいきましたでしょうか?
顔を傾けたり、かなり横を向いたり、マスクをしても顔と認識してくれていて、OpenCVの場合よりも認識してくれる範囲が広いようです。
ウィンドウの✕印を押すと終了し、FPSを表示します。
FPS=3.2
Dlibでは顔のパーツを見つけてそこに顔があるという認識をしているようで、処理が複雑なだけOpenCVよりは遅くなったのかと予想します。
もし、C++版がうまくいかなくても次のPython版は試せますので、あきらめずに挑戦してみてください。
Dlib Pythonで顔認識
dlib_pyディレクトリに移動します。(dlib_cpp/builldにいる状態を想定しています)
cd ../../dlib_py
学習済みモデルデータへのシンボリックリンクを作成します。
ln -s ../shape_predictor_68_face_landmarks.dat
以下のコマンドで画像入力の顔認識を実行します。
python3 image_dlib.py --image ~/Downloads/TC9V9A4577_TP_V4.jpg
以下のように顔に対する赤い枠と目、鼻、口など顔のパーツに緑のマークが付きます。
qを押して終了します。
次に以下のコマンドで動画入力の顔認識を実行します。
python3 video_dlib.py --video ~/Downloads/video.mp4
以下のように顔に対する赤い枠と目、鼻、口など顔のパーツに緑のマークが付きます。
※この記事に貼り付けるために動画のサイズを小さくしてから顔認識を行いGIF動画化したので、緑のマークは相対的に大きく表現されています。
qを押して終了します。
次にパソコンのカメラ入力で顔認識を実行します。
python3 webcam_dlib.py
以下のように顔に対する赤い枠と目、鼻、口など顔のパーツに緑のマークが付きます。
qを押して終了すると、FPSを表示します。
FPS=3.5
上記は私の実行例で、Dlib C++版より少し高速でした。
Dlib Python版がnumpyなどのC++で記述されたPython用モジュールに適したアルゴリズムだったために、このような結果になったと推測します。
Dlib Pythonを応用した電子工作
ラズパイを使った電子工作の回路図は以下となっています。
なお、ラズパイの電源、キーボード、マウス等は省略しています。
ラズパイ用サンプルを格納したディレクトリに移動し、学習済みモデルデータへのシンボリックリンクを作成します。
cd ../RPi_dlib_sample ln -s ../shape_predictor_68_face_landmarks.dat
以下のコマンドでサンプルプログラムを実行します。
python3 webcam_sample.py
画角の中央付近に顔があるときにLEDが点灯し、さらにLED点灯中に顔を右に傾けるとサーボモーターが動いて旗が立つという仕掛けです。
ちょっとした工作ですが、動きがあるのは楽しいですよね。
プログラムの仕組みを解説します。
顔ランドマークの27番〜30番が鼻の上の点であることがわかったので、これらの座標を利用しています。
30番が鼻の頭の方なので、画角の中心付近かどうかの判定に使っています。
そして、27番と30番を結ぶ線の傾きが一定以上になると旗を立てるという処理にしてあります。
前の章のwebcam_dlib.py
との差分を見ると工作用に追記した部分がわかると思います。
まとめ
ラズパイを使ってDlib顔認識を応用した工作を作りました。
内容としては、Pi Cameraの画角中心付近に顔があるときにLEDが点灯し、さらに顔を右に傾けるとサーボモーターが動いて旗が立つというものです。
ちょっとした工作ですし、完成度も低いですが、動きのある工作は見ていて楽しいですよね。
単なる顔認識でなく、顔認識結果によって何かさせることはいろいろな応用が考えられます。
みなさま独自のアイディアで楽しい工作にトライして頂けたらと思います。
トラブルシューティング
Pi Cameraを認識しない
環境構築の章のraspi-configの設定ができているかご確認ください。
また、端子の向きに間違いないかご確認ください。端子はHDMI端子がある方に向け、黒い部分を下に押し込むことで固定します。
OpenCV PythonでdetectMultiScaleのエラー
以下のエラーが出る場合の対処方法を説明します。
OpenCV(4.5.2) /tmp/opencv-20210402-71941-1bhz1nv/opencv-4.5.2/modules/objdetect/src/cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'detectMultiScale'
原因は、下記カスケードファイルの場所がお使いの環境と合っていないためと思われます。
C++の場合:
// Cascade file for face detection const std::string cascade_name = "/usr/local/share/opencv4/lbpcascades/lbpcascade_frontalface.xml";
Pythonの場合:
# Cascade file for face detection cascade_path = "/usr/local/share/opencv4/lbpcascades/lbpcascade_frontalface.xml"
以下のコマンドで見つけられると思いますので、見つかったファイルパスで上記”〜”の内容を置き換えてください。
find /usr/local -name lbpcascade_frontalface.xml
推奨機器
Raspberry Pi 4 Model B(8GB RAM)
書籍紹介
Python、画像認識に関するおすすめの書籍を紹介します。
基礎から応用までわかりやすい説明でコード例も多数載っていて、初学者の入門書としては必要十分と感じています。
さらにPythonらしいコードの書き方も言及されていて、スマートなコードが書けるようになります。
詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識
最新のOpenCV4には対応していないのですが、やはりオライリー、基礎を学ぶには十分な情報があり、この本から入ることをおすすめします。
ゼロからよくわかる! ラズベリー・パイで電子工作入門ガイド Raspberry Pi 4 Model B対応[改訂2版]
ラズパイで電子工作するための入門書です。ラズパイや電子工作に興味はあるけれど、何から手を付けたらよいかわからない方におすすめします。
参考文献
- 【Mac】OpenCV, Dlibカスケード分類による顔認識いろいろ(C++, Python)(https://take6shin-tech-diary.com/mac-facerecognition/)
- RaspberryPiへのOpenCVインストール手順(https://qiita.com/wk_/items/8db529a6b24a955888db)
- OpenCV, dlibなどでのカスケード分類器まとめ(https://qiita.com/kenmaro/items/1b5f23187cc46b4f28c0)
- PythonでOpenCV DNNを利用して物体検知(Object Detection)する方法(https://www.haneca.net/python-opencv-dnn-object-detection/)
- Dlibの高性能な顔器官検出をMacでさくっと試す(https://qiita.com/naoyu822/items/7cce2f2dbad24931cc87)
- OpenCVとdlibの顔検出機能の比較(https://blog.chowagiken.co.jp/entry/2019/06/28/OpenCV%E3%81%A8dlib%E3%81%AE%E9%A1%94%E6%A4%9C%E5%87%BA%E6%A9%9F%E8%83%BD%E3%81%AE%E6%AF%94%E8%BC%83)