Pythonで学ぶOpenCV②〜特徴抽出の理論、実装〜

Pythonで学ぶOpenCVの第2回目、特徴抽出についてご紹介します。

さて。今回はOpenCVの便利なパッケージを用いて、特徴抽出をしてみたいと思います。

OpenCVをインストールしたときに"haar-cascade"なるものがダウンロードされていると思います。今回はこれを使って簡単に顔認識をやってみたいと思います。このリンクを参考にしています。
まずは特徴抽出の理論についてです。

重要になるのはhaar-like特徴量と呼ばれるものです。

haar-like特徴量とは画像における特徴量として、「照明条件の変動やノイズの影響を受けやすい各画素の明度値をそのまま用いるのではなく、近接する2 つの矩形領域の明度差を求めることで得られる特徴量である」(http://manji602.hatenablog.com/entry/20111214/1323834770)だそうです。

OpenCVの公式ページには以下のような図がありました。

物体を認識するため、このように近くのピクセルとの関係を見るわけですね。

そしてたくさんの画像についてそこに顔が含まれるか、含まれていないかを学習させ、haar-cascadeという分類器を作るようです。

顔が含まれているか含まれていないか、というチェックの部分もすべての要素に対して同じ重みでチェックするわけではなく、38ものステージをふんでチェックが行われているようです。
次にこれをプログラムしていきます。第1回目と同じようにvimを使ってやっていきましょう!

まずは必要なパッケージをインポートします。
#coding UTF-8
import bumpy as np
import cv
import cv2
from PIL import Image
sample01.py
次に、get_face(picture_name)という関数を定義することにします。pictureの名前からその画像の中に入っている人の顔を識別するようにします。これは def get_face(picture_name):とすると関数を定義することが可能です。以下に関数を書きます。

def get_face(picture_name):
     cascade_path = "opt/local/share/OpenCV/haarcascade/haarcascade_frontalface_alt.xml"
     image = cv2.imread(str(picture_name))
     color = (255,0,0)
     gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
     facerect = cascade.detectMultiScale(gray, scaleFactor=1.1, 
                      minNeighbors =1,minSize=(1,1))
     if len(facerect) > 0:
         for rect in facerect:
               cv2.rectangle(image, 
                tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]),color,thickness=2)
     else:
             print("no face")
    cv2.mshow("detected.jpg",image)
    cv2.waitKey()
    cv2.destroyAllWindows()
sample02.py

補足

  • cascade_path:
  • 以下のようにFinderで"cascade"と検索すると、沢山の項目がでてくると思います。これをターミナルにドラッグ&ドロップするとそのPathがすぐ得られます。これをcascade_pathに記録してください。

  • color:
  • 囲う色を決めます。この場合青です。

  • facerect:
  • cascadeによって識別された情報が入る。変数についてはそこまで気にする必要ないようです。

これによって識別することが可能です。すべてのコードをまとめると以下のようになります。
import numpy as np
import cv
import cv2
from PIL import Image

def get_face(picture_name):
     cascade_path = "opt/local/share/OpenCV/haarcascade/haarcascade_frontalface_alt.xml"
     image = cv2.imread(str(picture_name))
     color = (255,0,0)
     gray = cv2.cvtColor(image, cv2.cv.CV_BGR2GRAY)
     facerect = cascade.detectMultiScale(gray, scaleFactor=1.1, 
                      minNeighbors =1,minSize=(1,1))
     if len(facerect) > 0:
         for rect in facerect:
               cv2.rectangle(image, 
                tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]),color,thickness=2)
     else:
             print("no face")
    cv2.mshow("detected.jpg",image)
    cv2.waitKey()
    cv2.destroyAllWindows()

if __name__="main"
      get_face("picture.jpg")
sample03.py
これを実行すると、以下のようになります。

ばっちり顔が識別されていることがわかりますね!!
こんな単純に顔の検出ができるなんて、OpenCVはすごいです。

他にもたくさんのhaar-cascadeがあります。いろいろ実行してみると面白いかもしれませんね。