プログラミング備忘録

初級プログラマ。python、DL勉強中

pythonでOpenCVを使った顔検出

OpenCVを使って顔検出をしてみる
今回はサッカー選手メッシの画像でトライしてみた

参考

bing image search APIを使ってみた - ヘビ夫のプログラミング備忘録

OpenCVを使った顔検出(番外編) - ヘビ夫のプログラミング備忘録

サッカー選手の顔画像を分類してみた - ヘビ夫のプログラミング備忘録

OpenCVで顔認識など特徴ある領域の検出

事前準備

ひとつひとつ画像を保存して収集することも可能だが、あまりに面倒くさいので
bingAPIを使ってメッシの画像を一括で収集する。
なお画像は採番して./save/messiディレクトリに保存しておく f:id:programdl:20171125182425p:plain
bingAPIを使った画像の収集方法は以下参照 programdl.hatenablog.com


ソース

実行

python obj_detect.py  ./save/messi/

第2引数には画像の格納されるディレクトリを指定 カレントディレクトリにはhaarcascadesディレクトリを格納すること(後述)

実装

検出の実装以下のとおり
obj_detect.py

import cv2
import numpy as np
import sys
import os

def make_dir(path):
    if not os.path.isdir(path):
        os.mkdir(path)


input_data_path = sys.argv[1]
save_dir_path = sys.argv[1]+"face/"
detect_dir_path = sys.argv[1]+"detect/"
make_dir(save_dir_path)
make_dir(detect_dir_path)

cascade_path = './haarcascades/haarcascade_frontalface_default.xml'
cascade = cv2.CascadeClassifier(cascade_path)

image_count = 30
detect_count = 0

for i in range(image_count):
    img = cv2.imread(input_data_path + '{0:03d}'.format(i) + '.jpg', cv2.IMREAD_COLOR)
    try:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    except:
        #ファイルがなければ次のファイルへ
        print("Not found:"+input_data_path + '{0:03d}'.format(i) + '.jpg')
        continue

    #scaleFactor  – 各画像スケールにおける縮小量
    #minNeighbors – 信頼度に関するパラメーター
    target = cascade.detectMultiScale(gray, scaleFactor=1.1,minNeighbors= 40)

    if len(target) > 0:
        for rect in target:
            #対象区間を赤線で囲み保存
            cv2.rectangle(img, tuple(rect[0:2]), tuple(rect[0:2]+rect[2:4]), (0, 0,255), thickness=1)
            cv2.imwrite(detect_dir_path + '{0:03d}'.format(i)  +'.jpg', img)

            #対象区間を切り取り保存
            x = rect[0]
            y = rect[1]
            w = rect[2]
            h = rect[3]
            cv2.imwrite(save_dir_path + '{0:03d}'.format(i)  + '.jpg', img[y:y+h, x:x+w])
            print(save_dir_path + '{0:03d}'.format(i)  + '.jpg')
            detect_count = detect_count + 1
    else:
        print('image' + '{0:03d}'.format(i)  + ':No Target')

./save/messi/detect
./save/messi/face
にそれぞれ画像を出力

注意1 分類器

cascade_path = './haarcascades/haarcascade_frontalface_default.xml'
cascade = cv2.CascadeClassifier(cascade_path)

検出について、CascadeClassifierで設定を行う
何を検出したいかによって指定すべきxmlファイルが違うので注意
今回自作は避け、opencvで提供されるxmlファイルhaarcascade_frontalface_default.xmlを使用した


入手方法は以下の通り

$ wget https://github.com/Itseez/opencv/archive/3.1.0.zip

解凍後、opencv-3.1.0/data/haarcascadesを作業ディレクトリにコピー なおhaarcascadesディレクトリ配下にはxmlファイルが複数格納されている

$ cd opencv-3.1.0/data/haarcascades
$ ls
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

haarcascade_eye.xmlは目の検出
haarcascade_fullbody.xmlは体の検出
と言った感じで、何を検出したいかによって、ファイルの指定を変更する必要がある
opencv以外にも各個人がxmlファイルを公開していたりするので是非利用したい


注意2 認識精度のチューニング

    #scaleFactor  – 各画像スケールにおける縮小量
    #minNeighbors – 信頼度に関するパラメーター
    target = cascade.detectMultiScale(gray, scaleFactor=1.1,minNeighbors=40)

minNeighborsの値をいくつにするかで、検出結果が異なってくるので注意
対象とする画像セットごとに随時変更する必要がある。

minNeighbors=3

f:id:programdl:20171125190602j:plain
少しわかりにくいが、メッシの顔の他、胸中央のエンブレム、背景の顔の3つを検出している

minNeighbors=40

f:id:programdl:20171125190713j:plain
メッシのみを検出している
よって今回は minNeighbors=40を採用した

結果

メッシの顔の検出に成功
ただし、一部ご認識があるため今後どのように扱うか検討
f:id:programdl:20171125191706p:plain

その他

programdl.hatenablog.com