OpenCVでSVMとHOG特徴量を使って人を検出するのを試みてみる。【part2】
part2では、ダウンロードしたデータセットをSVMの学習に使うための準備をしたいと思います。
part1はこちら。
originfall.hatenablog.com
さて、part1の最後の部分でデータセットを用意しましたが、このデータセットをそのままSVMに学習させるのではありません。人検出用のSVMを作りたいので、人の部分を切り出して学習させます。
では、どうやって切り出すか。画像編集ソフトで1枚1枚切り出すのはダメです。めんどくさすぎます。プログラムにやらせましょう。今回、人検出の画像データとしては、
USC Pedestrian Detection Test Set
を使います。(もう一つのデータセットは、失敗例の学習に使います。)
このデータセット、ダウンロードするとわかるのですが、画像と対応するxmlファイルがあって、xmlファイルに画像中のどこに人がいるのかが書かれてます。これをプログラムで読み込んで、画像中から人部分を切り出して、画像として保存します。そのプログラムのソースコードが以下です。
# load xml import cv2 import sys from xml.etree import ElementTree i = 0 x = [] y = [] width = [] height = [] args = sys.argv filenumber = int(args[3]) tree = ElementTree.parse(args[2]) root = tree.getroot() for Rect in root.iter("Rect"): print(Rect.attrib) x.append(int(Rect.get('x'))) y.append(int(Rect.get('y'))) width.append(int(Rect.get('width'))) height.append(int(Rect.get('height'))) i+=1 srcimage = cv2.imread(args[1], 0) for j in range(0, i): manimg = srcimage[y[j]:y[j]+height[j], x[j]:x[j]+width[j]] path = ('image/man%04d.bmp' %filenumber) cv2.imwrite(path, manimg) filenumber+=1 print("If you proceed to next image, enter 3rd agrument as:"+str(filenumber))
このプログラムを簡単に説明すると、xmlファイル内の木構造を読んで、人のいる部分のx,y座標及び幅と高さを取り出して、それをもとに画像を切り出して保存してます。第1引数に画像ファイルパス、第2引数にxmlファイルパス、第3引数に数字を入力して実行します。(第3引数の数字は保存する画像の通し番号に関わります。)
ここで作成したのは人が入っている例で、人が入っていない例も作成しなければいけません。これは、
INRIA Person dataset
からダウンロードした中に、negというフォルダがあります。この中に、人が入っていない画像があるので、これを用いました。この画像は、先ほどの人が入っている例の画像と比べて大きいので、適当なサイズ(私は先ほどの人が入っている例の画像サイズの平均をとりました)でカットします。これも面倒なのでプログラムで。
import cv2 for i in range(1, 100): path0 = ('image/negative/neg%04d.png' %i) path1 = ('image/negative/cut/neg%04d.png' %(i-1)) img_src = cv2.imread(path0, 0) cut_height, cut_width = img_src.shape[:2] img_dst = img_src[int(cut_height/2):(int(cut_height/2)+124), int(cut_width/2):(int(cut_width/2)+44)] cv2.imwrite(path1, img_dst)
適当にやりすぎて、画像の真ん中をカットしようとしてたのに中心からズレてますが、問題ないでしょう。
part3はこちら。
originfall.hatenablog.com