Python + OpenCVで顔検出を行う
この記事のまとめ:
- OpenCV 3をインストールする。
- OpenCV 3に標準実装されているHaar Cascade分類器による顔検出を試す。
背景:
かなり寄り道してばっかりですが、機械学習を勉強中です。なんとなく写真から人物認識をしたくなりまして、その実現準備として写真の中から顔の部分だけを切り出すことが必要かと思い、顔検出ができるツールを探していたところ、とりあえずOpen CVが見つかったので試したいと思います。
OpenCV 3のインストール:
最新のOpenCV 3だとPython 3.6以上に完全対応していないとの情報があったので、今回はPython 3.5を前提に話をしていきます。 (参考:AnacondaディストリビューションでPythonの仮想環境を整える)
私はAnaconda環境でPythonの開発をしておりますのでcondaを使って、Open CVのインストールをします。
なお、インストール手順についてはこちらの記事を参考にさせていただきました。
Haar Cascade分類器について
OpenCVに実装されている顔検出は、Haar Cascade分類器というものを使って人の顔かどうか判断します。詳細の理解まではしていませんが、幾つかの単純な特徴を捉える分類器によって構成されるためカスケード分類器と呼ばれるようです。その単純な特徴を捉える分類器をどのように組み合わせて構成するかで写真の中のオブジェクトを検出させるもののようです。OpenCVには予めいくつかのオブジェクトを検出するための構成情報がXMLファイルとして用意されております。その中で人間の正面の顔を検出するXMLファイルは下記の4つがあります。
- haarcascade_frontalface_default.xml
- haarcascade_frontalface_alt.xml
- haarcascade_frontalface_alt2.xml
- haarcascade_frontalface_alt_tree.xml
これらのファイルは、OpenCVをインストールしている方は、PythonのインストールディレクトリからLibrary\etc\haarcascades
で見つかられるのではないかと思います。
文献を詳しく読んでいないため、これらのファイルがどのような違いがあるのか、どのように学習させたものなのか全く分かっておりませんが、とりあえず試してみてから考えたいと思います。
OpenCVのHaar Cascade分類器を使ってみる
上記の4つのXMLファイルで写真の中の顔検出を試すサンプルコードを以下に示します。
Cascade分類器を実行する際に、パラメーターが3つあります。
上記のサンプルコードでは(gray, 1.03, 5)
となっているところです。
それぞれ次のようなパラメーターを入力する必要がります。
- image: CV_8U型、つまりグレースケールの行列で表される画像ファイル
- scaleFactor: (詳しい説明があまりなかったので私の認識です)様々なサイズのオブジェクトを検出するために元の画像情報をスケールさせて分類器にかける際にどの程度の係数でスケールさせるかのパラメーターです。設定範囲は1.01以上で0.01 (=1%)単位で変更でき、値が小さいほど細かいスケーリングの粒度で検索できますが、その分時間がかかります。
- minNeighbors: 画像検出する手段として画像内の検索対象とする矩形を少しずつずらしてその矩形内の画像情報をCascade分類器に通して検出をさせているようなのですが、若干のズレを伴って複数の位置で画像を検出できるかどうかのパラメーターです。値が大きいほどズレを伴っても検出できるということなので検出精度は上がりますが、大きすぎると逆に下る可能性があります。値が小さすぎると検出誤りが発生しやすくなります。
- flags/ minSize/ mazSize(省略可能): 省略可能パラメーターなので説明も省略します。
説明を読んでいただければある程度精度が高くなるようにパラメーターを設定したつもりです。
なお、サンプルコードは下記の記事を参考にさせていただきました。
- Python OpenCVの基礎 ついに顔検出してみます
- Python + OpenCV で顔切り出し
- Object Detection : Face Detection using Haar Cascade Classfiers
結果
今回は6枚の写真を使って評価してみました。
1枚目
defalt: 検出精度が悪く、余計なものまで検出していますね。alt: defaultより改善。
alt2: altとは違うところを誤って検出。
alt_tree: 誤りはなくなりましたが人も検出されなくなりました。
2枚目
default: 先程と同様に余計なものまで検出しています。alt: 顔のみをうまく検出できています。
alt2: 一箇所だけ余計なものを検出しています。
alt_tree: 先程の写真と同様に顔のみを検出できています。
3枚目
default: 黒人の方が顔の上半分のみを検出するというわけのわからないことに。alt: 誤ってはいませんが検出数が少ないです。
alt2: まあまあいい感じですが正面の顔用のXMLファイルなので横顔は検出できませんね。
alt_tree: altと同様に誤ってはいませんが判定基準は厳しめな感じですね。
4枚目
default: ネクタイとか、手とかを検出しまっていますのでやはり判定基準は緩めですね。alt: おしい!
alt2: やはりaltよりも誤りが多いですね。
alt_tree: 顔だけしか検出していませんがやはり検出基準が厳しいようです。
5枚目
default: もはや顔以外しか検出していません。alt: 横顔は検出できませんね。
alt2: 同上、横顔は検出できませんね。
alt_tree: もちろん検出できませんね。
6枚目
default: そこまで悪くはないですが誤りはあります。alt: うまく顔だけ検出しています。
alt2: やはりaltより誤りは多そうです。
alt_tree: これまでと同様誤りはありませんが、検出数が少ないです。
最後に
結果的には以下のような感じでしょうか。
- 顔検出精度(顔以外を検出しない): alt_tree > alt > alt2 > default
- 顔検出能力(多くの顔を検出する): default > alt2 > alt > alt_tree
一長一短の結果と、横顔になると検出できないのはどれも違いないのでいまいちの結果でした。
別のアルゴリズムを試してみようと思って、Dlibを使ってHOGアルゴリズムによる顔検出を試してみたところ、断然精度が高かったのでもしご興味あれば下記の記事に使い方や差分がわかる結果を載せていますのでご覧ください。
今回は以上です。 最後まで読んでいただき、ありがとうございます。
コメント
コメントを投稿