はじめに

画像から、人物を検出してみます。
様々な方法があるようですが、理論はちょっと置いておいて、以下3つの方法を試してみました。

  • openCV(HOG特徴量+SVM)
  • openCV(Haar-like特徴量分類器)
  • keras (SSD)

環境

  • windows7 home(64bit)
  • openCV 3.3.1
  • tensorflow 1.2.1
  • keras 2.1.3

テスト用画像

フリー画像のサイトはいくつもありますが、スポーツ系の画像はあまりありませんでした。
その中でAdobeの画像がオシャレだったので、いくつかダウンロード(1ヶ月の無料期間あり。ユーザ登録要)

https://stock.adobe.com/jp/

openCV(HOG特徴量+SVM)

OpenCVの「cv2.HOGDescriptor」を使って人物を検出します。

ソースコード

複数画像を対象に人物を検出するソースはこちら→GitHub

openCV-hog-SVM.py
import numpy as np
import cv2

#入出力ファイル
input_file = './image/test.jpg'
output_file = './image_out/test.jpg'

# ファイル読込
image = cv2.imread(input_file ,cv2.IMREAD_COLOR)

hog = cv2.HOGDescriptor()
hog = cv2.HOGDescriptor((48,96), (16,16), (8,8), (8,8), 9)

# SVMによる人検出
hog.setSVMDetector(cv2.HOGDescriptor_getDaimlerPeopleDetector())

# リサイズした方が精度がよかった
finalHeight = 800.0
scale = finalHeight / image.shape[0]
image = cv2.resize(image, None, fx=scale, fy=scale)

# 人を検出した座標
human, r = hog.detectMultiScale(image, hitThreshold = 0.6, winStride = (8,8), padding = (32, 32), scale = 1.05, finalThreshold=2)

# 全員のバウンディングボックスを作成
for (x, y, w, h) in human:
    cv2.rectangle(image, (x, y),(x+w, y+h),(0,255,0), 2)

# ファイルを保存
cv2.imwrite(output_file , image)


実行結果

うーん、、あまり上手くいっていない様子。。。
openCV-hog.PNG

openCV(Haar-like特徴量分類器)

事前準備

人物用の特徴量分類器(haarcascade_fullbody.xml)を以下からダウンロードしておく

https://github.com/opencv/opencv/tree/master/data/haarcascades

ソースコード

複数画像を対象に人物を検出するソースはこちら→GitHub

openCV-Haar-like.py
import numpy as np
import cv2

# 入出力フォルダ
input_file = './image/test.jpg'
output_file = './image_out/test.jpg'

# 分類器の特徴量を取得する
faceCascade = cv2.CascadeClassifier('./haarcascade_fullbody.xml')

# ファイル読み込み
image = cv2.imread(input_file,cv2.IMREAD_COLOR)

# リサイズ
finalHeight = 800.0
scale = finalHeight / image.shape[0]
image = cv2.resize(image, None, fx=scale, fy=scale)

# 物体認識(人)の実行
facerect = faceCascade.detectMultiScale(image, scaleFactor=1.01, minNeighbors=1, minSize=(30, 30))

#検出した人を囲む矩形の作成
for x, y, w, h in facerect:    
    cv2.rectangle(image, (x, y),(x+w, y+h),(0,255,0), 2)

# ファイルを保存
cv2.imwrite(output_file, image)

実行結果

うーん、、、こちらもあまり上手くいっていない様子。。
openCV-like.PNG

keras (SSD:Single Shot MultiBox Detector)

事前準備

SSD: Single Shot MultiBox Detector 高速リアルタイム物体検出デモをKerasで試すを参考に、ssd_kerasのモデルと、学習済モデルをダウンロードします。

補足

リポジトリには、

This code was tested with Keras v1.2.2, Tensorflow v1.0.0, OpenCV v3.1.0-dev

とありますが、tensorflow 1.2.1で動きました。
tensorflow 1.4.1はダメでした。

ソースコード

上記サイトの方も記載されているとおり、
私もジュピターノートブックを開いて、SSD.ipynbをコピペしながら試してみました。
一部、指定したフォルダにある画像を一括して処理してくれるよう、少しだけ書き換えました。

例のごとく、複数画像を対象に人物を検出するソースはこちらに→GitHub

修正前
inputs = []
images = []
img_path = './pics/fish-bike.jpg'
img = image.load_img(img_path, target_size=(300, 300))
img = image.img_to_array(img)
images.append(imread(img_path))
inputs.append(img.copy())

#~複数ファイルある場合は繰り返し記述~

inputs = preprocess_input(np.array(inputs))
修正後
import os
input_data_path = './pics/'
inputs = []
images = []

file_list = os.listdir(input_data_path)
for file_name in file_list:
    img_path = input_data_path + file_name
    img = image.load_img(img_path, target_size=(300, 300))
    img = image.img_to_array(img)
    images.append(imread(img_path))
    inputs.append(img.copy())

inputs = preprocess_input(np.array(inputs))

実行結果

オォォォォ!!!なんてこったい。
水中の人をDogかも、と間違っている以外はほぼ完ぺきです。すごーい。
my-SSD.PNG

リアルタイム人物検出

まだやってません。次にリアルタイム検出や、転移学習もやってみたいです。

まとめ

openCVでは画像のサイズが小さい、背景が単色で人物がはっきり映っているものだとそれなりの精度で検出できていました。
ただ、複雑な画像にになると誤認識が多くなってしまうようでした。
比べて、SSDはすごかった。やってみた感想は、ほぼ完璧と言ってしまいたくなるくらいでした。

参考サイト

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.