概要
OpenCV のカスケード分類器 CascadeClassifier を使用して、画像から顔や目を検出する方法について解説します。
カスケード分類器
カスケード分類器は、複数の分類器を連結して行うアンサンブル学習の一種です。 画像が与えられたとき、まず特徴抽出器で画像から特徴量を抽出します。 その特徴量がカスケード分類器に入力され、分類結果 (positive または negative) が出力されます。
カスケード分類器は複数の分類器で構成されており、各分類器で positive または negative の判定が行われます。ある分類器で negative と判定された場合、その時点で棄却されます。positive と判定された場合は、分類器の出力結果が次の分類器に渡されます。
CascadeClassifier クラス
OpenCV では CascadeClassifier クラスでカスケード分類器が提供されています。
cv2.CascadeClassifier(filename)
- 引数
- filename: カスケード分類器の設定ファイル
XML ファイルの一覧
CascadeClassifier
は、特徴量の種類やカスケード分類器を構成している分類器の情報が記載された設定ファイルを読み込んで作成します。 OpenCV では、顔や目を検出するための設定ファイルが用意されています。 これらの設定ファイルは cv2.data.haarcascades
ディレクトリ以下にあるので、以下のようにファイルパスを指定するとよいでしょう。
cascade_path = os.path.join(
cv2.data.haarcascades, "<ファイル名>"
)
cascade = cv2.CascadeClassifier(cascade_path)
ファイル名 | 内容 | 特徴量 |
---|---|---|
haarcascade_eye.xml | 目 | Haar-like |
haarcascade_eye_tree_eyeglasses.xml | メガネ | Haar-like |
haarcascade_frontalcatface.xml | 猫の顔 (正面) | Haar-like |
haarcascade_frontalcatface_extended.xml | 猫の顔 (正面) | Haar-like |
haarcascade_frontalface_alt.xml | 顔 (正面) | Haar-like |
haarcascade_frontalface_alt2.xml | 顔 (正面) | Haar-like |
haarcascade_frontalface_alt_tree.xml | 顔 (正面) | Haar-like |
haarcascade_frontalface_default.xml | 顔 (正面) | Haar-like |
haarcascade_fullbody.xml | 全身 | Haar-like |
haarcascade_lefteye_2splits.xml | 左目 | Haar-like |
haarcascade_licence_plate_rus_16stages.xml | ロシアのナンバープレート | Haar-like |
haarcascade_lowerbody.xml | 下半身 | Haar-like |
haarcascade_profileface.xml | 顔 (正面) | Haar-like |
haarcascade_righteye_2splits.xml | 右目 | Haar-like |
haarcascade_russian_plate_number.xml | ロシアのナンバープレート | Haar-like |
haarcascade_smile.xml | 顔 (笑顔) | Haar-like |
haarcascade_upperbody.xml | 上半身 | Haar-like |
顔を検出する
今回は、haarcascade_frontalface_default.xml
で正面の顔の検出を試してみます。
from IPython.display import Image, display
def imshow(img):
"""ndarray 配列をインラインで Notebook 上に表示する。"""
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))
import os
import cv2
# 正面の顔を検出するカスケード分類器を作成する。
cascade_path = os.path.join(
cv2.data.haarcascades, "haarcascade_frontalface_default.xml"
)
face_cascade = cv2.CascadeClassifier(cascade_path)
CascadeClassifier.detectMultiScale()
はグレースケール画像を要求するので、cv2.cvtColor()
でグレースケールに変換してから渡します。
CascadeClassifier.detectMultiScale() で画像から対象物の検出を行います。
objects = CascadeClassifier.detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]])
- 引数
- image: グレースケール画像
- scaleFactor: 検索窓の拡大率 (1.0 より大きい値で指定、デフォルトは 1.1)
- minNeighbors: 近傍にこの値以上の検出矩形がない場合は、棄却する。値を大きくするほど、誤検出は減るが、未検出が増える可能性がある。(自然数で指定、デフォルトは 3)
- flags: 使用しない。
- minSize: 検出矩形の最小サイズ
- maxSize: 検出矩形の最大サイズ
- 返り値
- 検出矩形の一覧。各要素が (左上の x 座標、左上の y 座標、幅、高さ) のタプルで表されるリスト。
CascadeClassifier.detectMultiScale()
を使用して検出し、検出された矩形を cv2.rectangle()
で画像に描画します。
# 画像を読み込む。
img = cv2.imread("sample.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), color=(0, 255, 0), thickness=2)
imshow(img)
顔が検出できました。
!empty() in function 'detectMultiScale
というエラーが発生する場合
以下のエラーが発生した場合は、cv2.CascadeClassifier()
に指定した xml
ファイルが間違っています。名前が正しいかどうか確認してください。
error: OpenCV(4.2.0) /io/opencv/modules/objdetect/src/cascadedetect.cpp:1689: error: (-215:Assertion failed) !empty() in function 'detectMultiScale'
目を検出する
haarcascade_eye.xml
を使って、顔の領域にある目の検出も試してみます。
顔を検出するカスケード分類器で検出した各顔の領域を切り抜き、その領域に対して目の検出を行います。
デフォルトの minNeighbors=3
では誤検出が発生したため、minNeighbors=5
以上の値に設定しました。
# 目を検出するカスケード分類器を作成する。
cascade_path = os.path.join(cv2.data.haarcascades, "haarcascade_eye.xml")
eye_cascade = cv2.CascadeClassifier(cascade_path)
for x, y, w, h in faces:
# 顔の領域を切り取る。
roi = gray[y : y + h, x : x + w]
# 目を検出する。
eyes = eye_cascade.detectMultiScale(roi, minNeighbors=5)
# 矩形を画像に描画する。
for ex, ey, ew, eh in eyes:
cv2.rectangle(
img,
(x + ex, y + ey),
(x + ex + ew, y + ey + eh),
color=(255, 0, 0),
thickness=2,
)
imshow(img)
コメント