Pythonでカスケードファイルを使って顔認識をしてみました。この記事では、その手順とやってみてわかったことをまとめていきます。
結論からいうと、今回やってみた顔認識は簡単な仕組みです。
顔認識って言葉自体に難しい印象を受けていたのですが、やっていることは、強力な先人の知恵を使って顔を判定しているだけです。
実際にどのように動くかを知ることで、顔認識を応用してなにかつくれたらなと思います。誰かのお役に立てたら幸いです。
■顔認識の手順・仕組み
顔認識する手順、仕組みをまとめていきます。今回の顔認識ではカスケードファイルとよばれるものを使って行いました。
今回使ったサンプル画像は以下に載せます。かっこいいからこれにしました。
ではさっそく詳しく見ていきましょう!
・カスケードファイルから認識器(認識する仕組み)を作成
初めにやったのは、カスケードファイルから顔を認識する認識器をつくることです。
カスケードファイルとは、顔パーツを明暗で識別したデータのことを指します。例えば、鼻は顔のパーツの中で最も明るいので、「周りは黒いけど真ん中が白い部分」のような認識です。ほかにも、目はまぶたよりも涙袋の方が明るいため、「上は暗くて、下は明るい部分」のような認識がされます。
カスケードファイルは、GitHubから手に入れられるので以下のリンクからダウンロードできます。
リンクへ飛んでもらえばわかるのですが、ファイルがたくさんあります。今回使うのは、haarcascade_frontalface_alt.xmlという名前のファイルです。ほかにも目だけのカスケードファイルや、猫の顔のカスケードファイルもあります。興味のある方はそちらのファイルを使ってみてもおもしろいかもしれません。
認識器といっても、ようは調べたい画像をカスケードファイルと照らし合わせて顔があるか?という判定をするだけの仕組みです。
中身がわかってない私でも扱えたので、大丈夫。うん。。。
・画像を読み込んでグレイスケールに変換
認識器をつくったら、今度は調べたい画像を読み込んで、グレイスケールに変換します。
グレイスケールとは、色を明暗により表現する形式のことです。白黒写真を思い浮かべてみて下さい。色は白黒だけど色の違いは明暗でわかりますよね?
以下の画像がグレイスケールに変換した後の写真です。
グレイスケールに変換=白黒に変換って解釈でよさそうですね。とりあえずは白黒画像になりました。
・顔認識
ここから本題の顔認識をしていきます。
やることは単純、初めにつくった認識器にグレイスケールに変換した画像を与え、顔を認識させます。
注意しておきたいのが、今回使ったカスケードファイルは顔を正面から見た時のデータということ。つまり、顔のパーツを正面から見たときの明暗でしか顔を認識できないということです。
横顔だったり、表情がある場合は、精度が下がってしまい、認識できない場合もあるので注意しましょう。
・認識された範囲を視覚化
顔認識が行えたら認識した顔の座標をコンソール上に表示し、顔にマークをつけて視覚化します。
顔認識が行えても、確認できるようにしないとできたかわかんないので視覚化も重要なことです。
顔の座標をコンソール上に表示するにはprint文、マークをつけるためにOpenCVのrectangleを使いました。
顔認識した画像が以下のものです。
ちゃんと顔認識できてますね。にしてもこの人かっこいい。。。
顔認識の手順、仕組みがだいたいわかったでしょうか。次にコードを載せているので、実際の流れをまとめていきます。
■顔認識のPythonコード
今回使ったコードを載せていきます。
・使用したコード
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 |
#(1)モジュールをインポート import matplotlib.pyplot as plt import cv2 #(2)カスケードファイルを使って認識器を作成 cascade_file= "haarcascade_frontalface_alt.xml" cascade = cv2.CascadeClassifier(cascade_file) #(3)画像を読み込みグレイスケールに変換 img = cv2.imread("woman.jpg") img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) cv2.imwrite("woman-grayscale.jpg", img_gray) #(4)顔認識 face_list = cascade.detectMultiScale(img_gray, minSize=(150,150)) #認識失敗時の処理 if len(face_list) == 0: print("失敗") quit() #(5)認識した顔の座標、位置を視覚化 for (x,y,w,h) in face_list: print("顔の座標(x,y,w,h):", x, y, w, h) red=(0,0,255) cv2.rectangle(img, (x,y), (x+w, y+h), red, thickness=20) #(6)顔認識した画像を表示、出力 cv2.imwrite("face-recognition.jpg", img) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.show() |
コメントとして簡単な説明を書きましたが、もすこしだけ詳しく書きますね。
コメント#(1):使用したモジュールは以下の2つです。
・cv2
matplotlibは、画像を表示するためのモジュールです。cv2はOpenCVを使うためのモジュールですね。
コンソール上で以下のコマンドでインストールできます。
1 2 |
$ pip install matplotlib $ pip install opencv-python |
コメント#(2):1行目でカスケードファイル(顔パーツデータ)を読み込み、2行目で、カスケードファイルと比較するための機能を書いています。
コメント#(3):cv2.COLOR_BGR2GRAYの部分で、グレイスケールに変換してますね。BGR→GRAYへの変換を行っています。
コメント#(4):グレイスケールに変換した画像から顔を認識しています。minSizeで認識する最小のサイズを指定できるので覚えておきましょう。
コメント#(5):print文で顔座標を表示。rectangle(表示する画像, 始点, (始点+幅,始点+高さ), 色, 線の太さ)で顔座標を□で囲んでいます。
コメント#(6):顔認識した画像を表示、保存
次に私が以上のコードを書いていたときに発生したエラーをまとめておきます。反面教師として使ってください。
・発生したエラー
1 2 |
img_gray = cv2.cvtColor(img. cv2.COLOR_BGR2GRAY) AttributeError: 'numpy.ndarray' object has no attribute 'cv2' |
()内のimgとcv2.COLOR_BGR2GRAYの間の「,(カンマ)」が「.(ピリオド)」になってた。同じエラーが起きた場合はエラーが起きた文の「,(カンマ)」と「.(ピリオド)」を見直してみてください。
1 2 |
return _show(*args, **kw) TypeError: __call__() takes 1 positional argument but 2 were given |
この文をググると、モジュールの定義時に引数としてselfをいれることが関係しているらしいことがわかってちょっと沼にはまりかけてしまった。
インポートしたモジュールにエラーはないはずなので、これもまた、エラーがでた部分を見直してみてください。私の場合は、〇imshow()→×show()になっていて別の関数が呼ばれてしまった結果エラーが発生していました。
■まとめ
顔認識の手順をまとめると、以下の通りです。
・カスケードファイルから認識器(認識する仕組み)を作成
・画像を読み込んでグレイスケールに変換
・顔認識
・認識された範囲を視覚化
復習&発展として、今回使ったコードは、複数の人の顔も同時に識別できます。試しに以下の画像を顔認識してみました。
お父さんと寄り添っている男の子の顔が認識されませんでした。
傾いていてもだめみたいですね。顔認識難しい。。。
男の子以外の人は真正面を向いているので正しく認識されていますね。
参考に読んでいる本です。実践的なコードが多いのでおすすめ。
最後まで読んでいただきありがとうございました。