前回なんとかPython3+OpenCV3の環境を用意しました。
さっそく顔認識のテストを行います。果たしてどれだけの精度か?
顔認識の仕組み
まずは、顔認識の仕組みをおおざっぱに理解したいと思います。
顔を認識するには、顔かどうか分類する特徴データが必要となります。この特徴データを「分類器」と呼ぶようです。
分類器と照らし合わせて、顔かどうか判断します。
分類器を作るために、人間の顔の特徴を機械に学習させないといけません。
これを機械学習と呼びますが、顔のようなメジャーなものは、学習済みデータが手に入ります。
使用する分類器
今回テストで使う分類器は、OpenCVデフォルトの2つです。
- haarcascade_frontalface_default.xml・・・正面顔
- haarcascade_eye.xml・・・目
PCで「haarcascade_frontalface_default.xml」を検索すると、どこかで見つかるかと思います。
分類器は他にも、全身や笑顔などが用意されています。
感情取得は面白そうです。精度次第ですが・・・。
ディレクトリ構成
顔認識のテストを始めます。
前回用意した「C:\FACE」内に下記の構成でフォルダとファイルを用意します。
- haarcascades・・・分類器のフォルダ
- img・・・テスト用の画像フォルダ
- rectangle.py・・・顔認識して四角で囲うプログラム
分かりやすいので、分類器のフォルダ「haarcascades」を、C:\FACEにコピーしてきました。
使用するのは、顔正面と目の分類器だけです。
テスト画像の用意
imgフォルダには、テストする画像を6枚いれました。
GATAGフリー画像・写真素材集より、パブリックドメインのものを使わせて頂きます。
顔認識のPythonプログラム
rectangle.pyは、「OpenCVを使った顔認識」で紹介されているコードを使わせて頂きました。
私のディレクトリ構成に書き換えただけですが、分かりやすいように掲載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import cv2 # Haar-like特徴分類器の読み込み face_cascade = cv2.CascadeClassifier( 'haarcascades/haarcascade_frontalface_default.xml' ) eye_cascade = cv2.CascadeClassifier( 'haarcascades/haarcascade_eye.xml' ) # イメージファイルの読み込み img = cv2.imread( 'img/test6.jpg' ) # グレースケール変換 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 顔を検知 faces = face_cascade.detectMultiScale(gray) for (x,y,w,h) in faces: # 検知した顔を矩形で囲む cv2.rectangle(img,(x,y),(x + w,y + h),( 255 , 0 , 0 ), 2 ) # 顔画像(グレースケール) roi_gray = gray[y:y + h, x:x + w] # 顔画像(カラースケール) roi_color = img[y:y + h, x:x + w] # 顔の中から目を検知 eyes = eye_cascade.detectMultiScale(roi_gray) for (ex,ey,ew,eh) in eyes: # 検知した目を矩形で囲む cv2.rectangle(roi_color,(ex,ey),(ex + ew,ey + eh),( 0 , 255 , 0 ), 2 ) # 画像表示 cv2.imshow( 'img' ,img) # 何かキーを押したら終了 cv2.waitKey( 0 ) cv2.destroyAllWindows() |
4行目、5行目で分類器の読み込み。相対パスで読み込んでいます。
8行目でテスト画像の読み込み。ここのファイル名を書き換えながら、テストをしていきます。
テスト1 正面を向いた西洋人
まずは、顔認識が容易そうな画像から。
私の仮説(思い込み)では、西洋人の機械学習量の方が多く、認識されやすいのではと考えています。
さらに背景も白単色。服もシンプルな画像で実行。
おお!お?
顔も目も、すべて認識しています。
しかし、3か所顔ではないところを誤認しています。
けっこう判定がゆるいのか?
テスト2 赤ちゃん
続いて、顔の特徴が違う赤ちゃんを認識できるかテストです。
認識できれば、赤ちゃんが寝返りで窒息しないよう、見守りで使えそうです。
お、認識できました。・・・あれ?
緑の四角は目なのですが、赤ちゃんに4か所目が認識されてます。
お母さんも3か所。
通常は1つの顔に、目は2つしかないことを、機械に教えてあげないといけないようです。
テスト3 東洋人
次に、日本では実用的な、東洋人の顔認識テストです。
顔はだいたい認識されています。目は、けっこう開いていないと認識されないようです。
右手前の男の子の顔が認識されていません。
正面の女の子の手が邪魔で、首を傾けていますが、これくらいで認識精度は落ちるようです。
また、真ん中後ろの女性と、一番右の女性は、顔が2回認識されています。
テスト4 背景ごちゃごちゃ+犬
機械に厳しくしていきます。
今までと違い、背景がごちゃごちゃした画像で試します。
さらに犬までいるので、誤認だらけになってしまいそうですが・・・
あれ?予測の逆。
判定がシビアになり、認識された顔の数が減り、誤認はゼロ。
目は一つも認識されない事態に。
顔一つあたりの解像度が低すぎたかな?
テスト5 横顔
今度は横顔をどれだけ判断できるかテストします。
いつでも正確に正面を向いてくれるほど、人間は甘くありません。
おっ!正面顔の分類器を使っているのに、意外といけます。
お母さんはさすがに無理ですが、女の子はこの角度でも認識されました。
男の子も目をつむっているのに、一つは目として認識されています。
テスト6 見上げた横顔
先ほどの女の子と同じくらいの横顔で、見上げた状態の顔認識テストです。
心霊写真検出!?
正面顔の分類器に、この画像の認識は酷だったのでしょう。
横顔分類器に変更します。
rectangle.pyの4行目を「haarcascade_profileface.xml」に変更。
あれ?
何も認識しない。プログラムの問題?
検証のため、再びテスト5の女の子で確認。
認識します。盛大に誤認もします。
ということで、見上げた顔が認識されにくいことになります。
テスト3でも感じましたが、傾いた顔の認識が弱いです。
精度を求めるのは簡単ではない
遊びでは良いですが、OpenCVデフォルトの分別器をそのまま使って顔認識は厳しい印象です。
精度を求める場合、深層学習(ディープラーニング)の分野まで進む必要があるかもしれません。
人間ってすごい
小学生みたいな感想ですが、今回のテストで感じたことは、人間ってすごい!
視覚情報をリアルタイムで処理して、人の顔を認識するというのは、途方もなく高度な処理なんだと思います。
人間のようなリアルタイム高精度処理はできませんが、次回、Webカメラを使った動画の顔認識を試してみます。
やっぱり分類器自作を試みます。
Webカメラによるリアルタイム顔認識は、他サイトのコードを持ってきただけで終わってしまったので。