Python

OpenCV物体検出入門 1.画像から顔を検出しよう (Python)

投稿者 : OSCA

概要

「OpenCV物体検出入門」と題し、何度かに分けて画像処理ライブラリ OpenCV を用いて、画像から物体検出をする方法について解説していきます。 初回の本稿では、静止画像から人の顔を検出するチュートリアルを提示し、「物体検出」とはどういうことかのイメージを掴んでみようと思います。

OpenCVを利用した物体検出

 OpenCVを利用して画像から物体を検出する方法はいくつかあります。 「テンプレートマッチング」「特徴点抽出による比較」「カスケード分類器による検出」などです。 いきなりそれぞれについて詳しく理解しようとすると難しいので詳細は省くとして、今回は「カスケード分類器」を利用して人の顔を検出することをやってみようと思います。

画像から人の顔を検出するチュートリアル

 ここでは「カスケード分類器」という仕組みを使って、画像から人の顔を検出するチュートリアルを実施してみます。 「人の顔を判定するなんて、難しくないか?」と思うかもしれませんが、OpenCV がサンプルとして物体を検出できるいくつかのデータを提供してくれていますので、これを利用します。

 「カスケード分類器」は、画像の中から特定のものを検出する機能を持つものだとここでは理解してください。 検出したい対象の特徴を保存してあるXMLを引数にして初期化することで、特定の物を検出できる「カスケード分類器」を作り出せます。 上記の通り、OpenCVではサンプルとしていくつかの「対象の特徴を保存してあるXML」を提供してくれており、その中に顔を検出できるカスケード分類器を作成できるXMLも提供してくれています。

cascade = cv2.CascadeClassifier('XMLファイル名')

 OpenCV が提供しているカスケード分類器用のXMLファイルは次の通りです。

XMLファイル名 説明
haarcascade_eye.xml
haarcascade_eye_tree_eyeglasses.xml メガネ
haarcascade_frontalcatface.xml 猫の正面の顔
haarcascade_frontalcatface_extended.xml 猫の正面の顔
haarcascade_frontalface_alt.xml 正面の顔
haarcascade_frontalface_alt2.xml 正面の顔
haarcascade_frontalface_alt_tree.xml 正面の顔
haarcascade_frontalface_default.xml 正面の顔
haarcascade_fullbody.xml 全身
haarcascade_lefteye_2splits.xml 左目
haarcascade_licence_plate_rus_16stages.xml ロシアのナンバープレート
haarcascade_lowerbody.xml 下半身
haarcascade_profileface.xml 証明写真の顔
haarcascade_righteye_2splits.xml 右目
haarcascade_russian_plate_number.xml ロシアのナンバープレートの数字
haarcascade_smile.xml 笑顔
haarcascade_upperbody.xml 上半身

 XMLファイルのインストール先は、各自の環境でファイルを検索してください。 Anaconda で Python 環境を作っている筆者の場合は、次のようなパスにXMLファイルがありました。

  • ~/anaconda3/envs/opencv/share/OpenCV/haarcascades/

 それでは具体的なチュートリアルのソースコードを見ていきましょう。 なお、あらかじめ用意した画像から顔を検出するため、OpenCV を利用した画像の読込みの知識が必要です。 画像の読込みについては、別項「OpenCVで画像ファイルの読み書きをしよう (Python)」で詳しく解説していますので、必要であればそちらを参考にしてください。

import cv2

# カスケード分類器を生成する
cascade = cv2.CascadeClassifier('~/anaconda3/envs/opencv/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml')

# 顔を検出するための画像を読込む
img = cv2.imread("picture.jpg")

# 顔を検出する
facerect = cascade.detectMultiScale(img)

#検出した顔を四角い枠線で囲む (検出した顔の数だけ for で繰り返す)
for rect in facerect:
    cv2.rectangle(img, tuple(rect[0:2]),tuple(rect[0:2] + rect[2:4]), (255, 255, 255), thickness=2)

# 画像を表示する
cv2.imshow("image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

 今回は素材として wikipedia から中解像度のモナリザの画像を拝借して実験してみました。 モナリザの画像を picture.jpg として保存して上のプログラムを実行してみると、次のように顔が白い枠で囲まれました。 (超高解像度の画像で処理すると、それなりに処理が重くなるので気をつけてください)

モナリザ

 上記のサンプルプログラムで重要なのは、cv2.CascadeClassifier() 関数と cascade.detectMultiScale() 関数です。

 cv2.CascadeClassifier() は、上述の通り物体を認識するカスケード分類器を生成しています。 引数で与えたXMLに物体の特徴データが保存されています。 ここではXMLの中身は一旦気にしませんが、重要なのは物体の特徴データが準備できれば、どんな物体でも検出できるカスケード分類器を生成できるということです。

 cascade.detectMultiScale() で顔を検出しています。 戻り値としては検出した画像の座標情報が返却されますので、あとはその座標情報に沿って枠線を引いているというわけです。

おわりに

 初回の本稿はこれにて終了です。 チュートリアルを試して、画像から顔が検出できたことを確認してください。 また、カスケード分類器を生成する際のXMLを違うものにしてみて、別の物体が検出できることを試してみても楽しいでしょう。

著者 : OSCA

OSCA

Java, PHP 系のWEBエンジニア。 WEBエンジニア向けコミュニティ「WEBエンジニア勉強会」を主催。
個人として何か一つでも世の中の多くの人に使ってもらえるものを作ろうと日々奮闘中。
@engineer_osca