Python 備忘録

Python-ver: 3.6.3

Pythonで画像認識① 顔認識

久々の更新です。

本日は画像の顔認識をやっていきたいと思います。

顔認識は知っての通り、画像の中の人間の顔をプログラムで検知すること。
今回の目標は画像の中の人間の顔に四角い枠を出してみることをしたいと思います。
imagesフォルダの中にwoman.jpgというjpgファイルを入れています。こちらのファイル。
f:id:sh0122:20171030185446j:plain:h500

今回はHaar-like特徴分類器という手法を使って顔認識をしたいと思います。
Haar-like特徴分類器とは

「Haar-like特徴を用いたブースティングされた分類器のカスケード」とは、
Haar-likeとよばれる明暗で構成される矩形のパターンを検出に使う手法です。

https://qiita.com/hitomatagi/items/04b1b26c1bc2e8081427

です。そして、haarcascadeはopencvに搭載されているらしいです。

ソースコード

さっそくコード。

# -*- coding: utf-8 -*-

import cv2

#HAAR分類器の顔検出用の特徴量
cascade_path = "/usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml"

image_path = "../images/woman.jpg"

color = (255, 255, 255) #白
#color = (0, 0, 0) #黒

#ファイル読み込み
image = cv2.imread(image_path)
#グレースケール変換
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

#カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)

#物体認識(顔認識)の実行
facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))

print("face rectangle")
print(facerect)

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)

    #認識結果の保存
    cv2.imwrite("../images/detected.jpg", image)

コードはこちらを参考にさせていただきました。
python+OpenCVで顔認識をやってみる - Qiita

今回のエラー

だが、どうしてもエラーが出る。
まずシンタックスエラー。パスを指定している部分でエラーが出る。
どうも\の部分でencodeができていないらしい。このように直したらできました。

cascade_path = r"/usr/local/opt/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml"

"の前にrを足しました。こちらを直すとまたエラーが。

cv2.error: C:\projects\opencv-python\opencv\modules\objdetect\src\cascadedetect.cpp:1698: error: (-215) !empty() in function cv::CascadeClassifier::detectMultiScale

最初の数十文字で検索をかけるとStackOverFlowにあった。
python 2.7 - error: (-215) !empty() in function detectMultiScale - Stack Overflow
どうやら、パスが間違っていて、読み込むファイルが見つからないエラーらしい。

パスが違うのは考えてみれば当たり前のことでした・・・。なんで気づかなかったのだろう。

エクスプローラーでhaarcascadeなどと検索。インストールされていればどこかにxmlファイルがあるはず。
だが、見つかりそうにない・・・。haarcascadeはopenCVに同梱されているらしいが。


しょうがないので、GitHubからhaarcascade_frontalface_default.xmlをダウンロードしてどこかのフォルダに保存。
opencv/data/haarcascades at master · opencv/opencv · GitHub
こちらから拝借しました。

フォルダを保存したパスで、cascade_pathを変えてみるが・・・。今度は別のエラーが。

cv2.error: C:\projects\opencv-python\opencv\modules\core\src\persistence.cpp:448
4: error: (-49) Input file is empty in function cvOpenFileStorage

これがよくわからない。

解決策

色々調べていると、OpenCVの公式サイトがあるらしいので、そこからダウンロードする。
こちら
OpenCV library

  • 上のタブからRELEASESをクリック。
  • 一番上の3.3.1のSourcesをクリック
  • zipファイルがダウンロードされるので、任意の場所に保存
  • 任意の場所に解凍
解凍したファイルのdata\haarcascadesというフォルダの中にhaarcascade_frontalface_default.xmlというファイルがあるので、
それをパスに指定。

すると、できました。
やっぱり公式から持ってくるのが一番でした。

出来上がったコード

試行錯誤して、出来上がったのがこちら。

# -*- coding: utf-8 -*-

import cv2

#HAAR分類器の顔検出用の特徴量
cascade_path = r'C:\projects\opencv-3.3.1\data\haarcascades\haarcascade_frontalface_default.xml'


image_path = "../images/woman.jpg"
color = (255, 255, 255) #白

#ファイル読み込み
image = cv2.imread(image_path)
#グレースケール変換
image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

#カスケード分類器の特徴量を取得する
cascade = cv2.CascadeClassifier(cascade_path)

facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
print("face rectangle")
print(facerect)

if len(facerect) > 0:
    #検出した顔を囲む矩形の作成
    rect = facerect[1]
    cv2.rectangle(image, tuple(rect[0:2]),tuple(rect[0:2]+rect[2:4]), color, thickness=2)

    #認識結果の保存
    cv2.imwrite("../images/detected.jpg", image)

こちらが認識後の画像。
f:id:sh0122:20171031213510j:plain:h500