OpenCVによる顔検知
カテゴリ:Pythonの話
こんにちは!前回の記事でOpenCVによる画像認識(正確には画像検知)についての解説をしたのですが、今回は人間の顔を検知する顔検出の原理について説明して、最後に簡単なopenCVによる検出器の使い方を紹介しようと思います!
顔検出の原理
顔の検出機能は、最近ではスマートフォンでさえ使える基本的な機能ですが、実用化されるまではすごい困難な技術でした。2001年のViola&Johnsの論文(Paul Viola and Michael J. Jones. Rapid Object Detection using a Boosted Cascade of Simple Features. IEEE CVPR, 2001)で超高速&超正確な検出アルゴリズムが発表されてからは、そこまで高性能な機器でなくともリアルタイムで顔を検出できるようになりました。この論文のポイントは3点で、
- Integral-ImageによるHaar-like検出器の高速演算
- AdaBoostによる検出能力の強化
- 多段フィルタ(cascade)による非顔領域の高速排除
です!詳しく解説されている動画がありましたので、1.5時間と長い動画ですが、詳しく知りたい方は参考にしてみてください!
何も判断力を持たないコンピュータに計算のみで画像の中から顔の領域を見つけさせたい、、、、どうすれば良いのか?
一番簡単な原始的な方法として、ある領域をくり抜いて、それが顔かどうかを逐一判断して、それを全ての領域で、全ての枠の大きさで実践する方法があると思うが、これは計算コストが非常に大きく、スマホでは到底実現できないですね。。。
Haar-like検出器(Haar-like feature)
人の顔の写真を目の回りをぼかして見ると、そのすぐ下の頬のあたりよりは暗いことがわかります。
画像の中から目の辺りになる位置の、上下に隣接する横長の長方形領域を切り出して、それぞれの領域の明度の平均をとり、上の領域が明るくて下の領域が暗かったら顔画像の候補にします。また、鼻筋の天辺よりは鼻筋の両脇の明るさの平均のほうが小さいことが多いです。
これだけの判断基準で顔候補が一気に半分に減ることにViolaらは気づき、integral-imageを使うと、この計算がたった数回の加減算でできてしまいます!
この話を聞いて候補数がたった半分になっただけ?と思う方いるかもしれませんが、あとはこれを繰り返すだけで候補数は急速に減っていき、10回目には1000分の一、20回目には100万分の1にまで減ります。
簡単に説明をするとこれが多段フィルタ(cascade)による非顔領域の高速排除です。
adaBoost
人が何かを認識するときに、いくつかの特徴を一瞬で感じて認知しているように、できるだけ異なった視点から対象を選択する分類器を組み合わせることで誤認知する確率を下げることができます。
簡単な例をあげると、トマトを検知するとき、赤い、丸いようなものという情報ではりんごも認識してしまうが、そこに、中身も赤い、という情報が入ることによりりんごははじくことができるようになります。
その分類器の選択は、赤い、と分類された対象を集めると、もちろん、トマトではない物がたくさん混じってきますが、その間違えた対象の中からトマトを分けるのに、より良い分類器を選べば、「異なった視点」の分類器を選べるはずです。
具体的には、たくさんのりんごの画像とそうでない画像を用意して、たくさんの分類器候補に分類させ、その成績を調べ、一番成績のいいものを最初の分類器にします。また、点数の低い分類器は判定を逆にすることで良い分類器として扱うことができます。
こうして選ばれた分類器に、正解確率をもとに重みづけ(それぞれの分類器が最終決断にどれほど寄与するかのパラメータ)を決定して最終決断を下します。実際に画像検知する検出器を作るためにはこのような機械学習が必要になるということですね。これは前回紹介した機械学習の中でも教師あり機械学習と呼ばれる分類です!
openCVのカスケード型検出器
カスケード型検出器
カスケード型検出器は、多段階フィルタというタイプでいくつもの評価条件から多段階で評価し、最終的にすべての評価から検出対象だと判断する検出器です。
本来は機械学習によって、顔検出の検出器を作成しなければならないのですが、膨大な画像データを使用して、長時間の学習時間を要する必要があるため、今回はOpenCVに同梱されている検出器「Haar-likeカスケード型検出器」を紹介したいと思います。
同梱されている検出器は目の検出器、鼻の検出器、顔の検出器などが用意されています。
detectMultiScaleメソッドのパラメータ
Haar-likeカスケード型検出器の画像に対する実行メソッドのdetectMultiScaleについて軽く紹介します。
scaleFactor :
画像スケールにおける縮小量のことで、detectMultiScaleでは画像のスケールを何度も変化させて探索するため、その際の縮小量を設定します。大きいほど誤検知が多く、小さいほど未検出となってしまう率が高くなります。
minNeighbors:
信頼性のパラメータで、検出器が検出する箇所が重複するので、より重複が多い部分が信頼性が高いこととなり、その閾値を設定します。値が大きくなるにつれて信頼性が上がりますが、顔を見逃してしまう率も高くなります。
minSize :
物体が取り得る最小サイズで、これよりも小さい物体は無視されます。
これらのパラメータを変更することで、顔の可能性が少しでもあるものは全て表示させたり、どこまでの大きさの顔まで検知する必要があるのかを設定することができます。
最後に
最近、機械学習についての話題がホットなので、OpenCVのHaar-likeカスケード型検出器のように、学習済みの用意されたものを利用することで簡単に誰でも利用することができるので、是非試してみてください!