近年の顔認識は、パソコンはもとより小型のマイコンボードなどの機器で実現できるようになってきており、顔認識を利用したアプリケーションは一般的になりました。
C++やPythonで簡単に試せる顔認識環境としてOpenCVとDlibが有名です。
本記事ではMacを使ってOpenCVとDlibそれぞれをC++/Python両言語で動かす方法と処理性能の比較結果を紹介します。
入力として、画像、動画、カメラ(リアルタイム)それぞれの場合の記述例を用意しました。
カメラ入力でリアルタイム処理を実行した際のOpenCV, Dlibとそれぞれの使用言語(C++, Python)との組み合わせの処理速度(FPS値)の比較結果は以下でした。(数値が大きいほど高速)
OpenCV | Dlib | |||
---|---|---|---|---|
Machine 1 | Machine 2 | Machine 1 | Machine 2 | |
C++ | 7.1 | 14.0 | 5.4 | 9.3 |
Python | 7.0 | 14.5 | 9.1 | 9.8 |
※ Machine 1:MacBook Pro 13-inch Early 2015 / Dual Core i7 3.1GHz
Machine 2:MacBook Pro 13-inch 2018 / Quad Core i7 2.7GHz
試行前はC++の方が速いだろうと予想していたのでPythonでも同程度かむしろ高速なのが意外でした。
OpenCVはQuad Coreの場合にDual Coreの2倍程度速くなっているので、CPUコア数に応じた並列化がなされている実装と推測できます。
DlibのPython版は、CPUコア数によらず比較的高速で、顔以外の部分を顔と誤認識することはほぼ無いので、この中ではDlib Python版がもっとも使いやすいです。
下の動画で、クリーンインストール直後のまっさらなMacで本記事の内容を試していますので、よろしければご覧ください。
使用環境
項目 | バージョン |
---|---|
macOS | Catalina 10.15.7 Big Sur 11.2 |
OpenCV | 4.5.2 |
Dlib | 19.21 |
ソースコード(GitHub)
GitHubからソースコードをダウンロードします。
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
画像と動画のダウンロード
以下、私が試行に使用したファイルを紹介しますが、人の顔が写っていれば他のファイルで構いません。
以下のフリー画像をダウンロードします。
以下のフリー動画をダウンロードします。
サイズは一番小さい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_mac.sh
で、全実行することができますが、途中でエラーが発生する場合もあるかもしれませんので、1つずつ実行する方が安全だと思います。
HomeBrewをインストールしていない場合はインストールします。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
HomeBrewを使って必要となるツールをインストールします。
brew install wget brew install boost brew install boost-python3 brew install opencv brew install cmake brew install xquartz
xquartzのインストールでできたX11のシンボリックリンクを作成します。
ln -s /opt/X11/include/X11 /usr/local/include/X11
これを実施しないと画面表示がうまくいきませんでした。
次に/usr/local/bin/python3
が/usr/bin/python3
よりも優先して使われるように~/.zshrc
または~/.bash_profile
にvi等のテキストエディタでPATH設定を追記します。
viの使い方に慣れていない方は、こちらの動画を参考にしてください。
vi ~/.zshrc
~/.zshrcの中身に以下を記述して保存します。
export PATH=/usr/local/bin:$PATH
現在起動しているターミナルで上記設定を有効にするためにsourceし、which python3で優先するpython3を確認し、以下のように/usr/local/bin/python3と表示されれば大丈夫です。
source ~/.zshrc which python3 /usr/local/bin/python3
pip3を使ってimutilsをインストールします。
pip3 install imutils
Dlibをインストールします。
wget http://dlib.net/files/dlib-19.21.tar.bz2 tar zxf dlib-19.21.tar.bz2 cd dlib-19.21 sudo python3 setup.py install
Dlibで使用する顔のランドマークデータをダウンロードして展開します。
cd .. wget http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2 bunzip2 shape_predictor_68_face_landmarks.dat.bz2
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=7.1
7.1は私の実行結果で、1秒間に7.1フレームの処理ができたという意味です。
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=7
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
Xquartzを起動します。
Xquartzを起動しても何も表示されないため心配になるかもしれませんが、問題ないので次に進みます。
以下のコマンドで画像ファイル入力の顔認識を実行します。
./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=5.4
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=9.1
上記は私の実行例ですが、驚きの結果ではないでしょうか。
Dlib C++版より高速で、OpenCVよりも速いです。
Dlib Python版がnumpyなどのC++で記述されたPython用モジュールに適したアルゴリズムだったために、このような結果になったと推測します。
まとめ
MacでOpenCV、Dlibを利用し、画像/動画/カメラそれぞれの入力に対する顔認識を実施しました。
プログラム言語はC++とPythonを使いましたが、下表に示すFPS値のとおりPythonは同程度または高速でした。(数値が大きいほど高速)
OpenCV | Dlib | |||
---|---|---|---|---|
Machine 1 | Machine 2 | Machine 1 | Machine 2 | |
C++ | 7.1 | 14.0 | 5.4 | 9.3 |
Python | 7.0 | 14.5 | 9.1 | 9.8 |
OpenCVはQuad Coreの場合に2倍程度速くなっているので、CPUコア数に応じた並列化がなされている実装なのかと推測できます。
DlibのPython版は、CPUコア数によらず比較的高速で、顔以外の部分を顔と誤認識することはほぼ無いので、この中ではDlib Python版がもっとも使いやすいです。
トラブルシューティング
cmakeでOpenCVにリンクできない
本記事の内容を実行する前にOpenCVをインストール済みであったり、以前はうまく実行できていたのに何らかの環境更新などで、cmakeに失敗する場合がありましたので、回避策を紹介します。
Mac$ cmake .. CMake Error at CMakeLists.txt:6 (find_package): By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "OpenCV", but CMake did not find one. Could not find a package configuration file provided by "OpenCV" with any of the following names: OpenCVConfig.cmake opencv-config.cmake Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set "OpenCV_DIR" to a directory containing one of the above files. If "OpenCV" provides a separate development package or SDK, be sure it has been installed. -- Configuring incomplete, errors occurred! See also "/Users/user/work/face_recognition/cv_cpp/build/CMakeFiles/CMakeOutput.log".
上記エラーが出た場合、このサイトの内容に従い、まずopencvのインストールを再度試すと以下のメッセージが出ます。
Mac$ brew install opencv Warning: opencv 4.5.2 is already installed, it's just not linked. To link this version, run: brew link opencv
brew link opencv
を実行せよ、とのことなので、実行すると以下のようにエラーになります。
Mac$ brew link opencv Linking /usr/local/Cellar/opencv/4.5.2... Error: Could not symlink lib/python3.9/site-packages/cv2/__init__.py Target /usr/local/lib/python3.9/site-packages/cv2/__init__.py already exists. You may want to remove it: rm '/usr/local/lib/python3.9/site-packages/cv2/__init__.py' To force the link and overwrite all conflicting files: brew link --overwrite opencv To list all files that would be deleted: brew link --overwrite --dry-run opencv
--overwrite
を追加して以下のように実行すると無事リンクでき、cmakeも正常に動作するようになりました。
Mac$ brew link --overwrite opencv Linking /usr/local/Cellar/opencv/4.5.2... 249 symlinks created.
dlibの画面表示に失敗する
初回のdlib実行時に画面が表示できない場合は、Xquartzを起動してから再度実行するとうまくいきました。
Input file: /Users/user/Downloads/TC9V9A4577_TP_V4.jpg 5 FATAL [1] dlib.gui_core: Unable to connect to the X display. Failed to initialize X11 resources
Pythonでimport cv2に失敗する
Pythonで以下のようにimport cv2ができないことがありました。
Traceback (most recent call last): File "image.py", line3, in <module> import cv2 ImportError: No module named cv2
/usr/local/bin/python3
を優先する設定をせずにOpenCVのPythonプログラムを実行しようとした際にこのエラーが出ました。
~/.zshrc
にexport PATH=/usr/local/bin:$PATH
を追加してsource ~/.zshrc
をした後に実行することでエラーが出なくなりました。
Pythonでimport dlibに失敗する
Pythonで以下のようにimport dlibができないことがありました。
Traceback (most recent call last): File "/Users/user/face_recognition/dlib_py/image_dlib.py", line 1, in <module> import dlib ModuleNotFoundError: No module named 'dlib'
環境構築の章で/usr/local/bin/python3
を優先する設定をする前にsudo python3 setup.py install
を実行すると上記のエラーが出ました。
~/.zshrc
にexport PATH=/usr/local/bin:$PATH
を追加してsource ~/.zshrc
をした後、再度sudo python3 setup.py install
を実行するとエラーが出なくなりました。
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
Anaconda環境をお使いの場合は以下のコマンドで見つかると思います。
find /Users/user/opt/anaconda3 -name lbpcascade_frontalface.xml
書籍紹介
Python、画像認識に関するおすすめの書籍を紹介します。
基礎から応用までわかりやすい説明でコード例も多数載っていて、初学者の入門書としては必要十分と感じています。
さらにPythonらしいコードの書き方も言及されていて、スマートなコードが書けるようになります。
詳解 OpenCV 3 ―コンピュータビジョンライブラリを使った画像処理・認識
最新のOpenCV4には対応していないのですが、やはりオライリー、基礎を学ぶには十分な情報があり、この本から入ることをおすすめします。
参考文献
- 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)
- MacでOpenCVがインストールされているのにcmake出来ない問題(https://qiita.com/ysuzuki19/items/e1d14a29d78529eab51a)