OpenCVでの物体検出器作成
OpenCVのオブジェクト検出器作成方法についての解説です。
学習データの作成
まず最初にオブジェクト検出器の学習に使う教師データを用意する必要があります。そのためにまずGUIでオブジェクトの位置を指定するGUIツールを作りました。
PythonのOpenCVを使います。
#!/usr/bin/env python #! -*- coding: utf-8 -*- import cv2 import numpy as np import sys drawing = False sx, sy = 0, 0 gx, gy = 0, 0 rectangles = [] ok = False def draw_circle(event,x,y,flags,param): global sx, sy, gx, gy, drawing if event == cv2.EVENT_LBUTTONDOWN: drawing = True sx,sy = x,y elif event == cv2.EVENT_MOUSEMOVE: if x > 0 and x < img.shape[1]: gx = x if y > 0 and y < img.shape[0]: gy = y elif event == cv2.EVENT_LBUTTONUP: drawing = False w = abs(sx-x) h = abs(sy-y) if w < h * 1.1 and h < w * 1.1: rectangles.append([(sx, sy), (x, y)]) img = np.zeros((512, 512, 3), np.uint8) cv2.namedWindow('image') cv2.setMouseCallback('image',draw_circle) i = 0 while i < len(sys.argv): rectangles = [] while True: img = cv2.imread(sys.argv[i]) for r in rectangles: cv2.rectangle(img, r[0], r[1], (255,255,255), 2) if drawing: w = abs(sx-gx) h = abs(sy-gy) if w < h*1.1 and h < w*1.1: color = (0, 255, 0) else: color = (0, 0, 255) cv2.rectangle(img, (sx,sy), (gx,gy), color, 2) cv2.imshow('image', img) k = cv2.waitKey(1) & 0xFF if k == ord('d'): if rectangles: rectangles.pop() elif k == ord('n'): if len(rectangles) > 0: print sys.argv[i], len(rectangles), for r in rectangles: x = min(r[0][0], r[1][0]) y = min(r[0][1], r[1][1]) w = abs(r[0][0] - r[1][0]) h = abs(r[0][1] - r[1][1]) print x, y, w, h, print i += 1 break elif k == ord('b'): print 'delete previous line!' if i > 1: i -= 2 break elif k == ord('q'): sys.exit()
引数にオブジェクトの写ったファイル一覧を与えて起動します。 (追記: python hoge.py *.png
みたいに実行することを想定しています)
マウスで左上から右下にドラッグすると範囲が選択されます。縦横比が正方形に近い時は枠が緑になりこの状態でボタンを離すと選択が確定します。dボタンを押すと一つ前の選択が消去されます。
nボタンで次の画像へ移動し、bボタンで戻ります。この時出力にdelete previous lineと出るので後で削除してください。(手抜き実装です……)qボタンで終了します。
結果を標準出力に吐くので、これをtrain.txtという名前で保存します。
コメントアウト部を元にもどすと既存の顔検出器での結果を使って多少ラクができます。実行ファイルを同じディレクトリにlbpcascade_frontalface.xmlを置くようにしてください。
オブジェクト検出器の学習(OpenCV)
OpenCV 2.4.2で分類器を作るを参考にしました。
opencv_createsamples -info train.dat -vec train.vec -num 1000 opencv_traincascade -data cascade/ -vec train.vec -bg bg.dat -numPos 900 -numNeg 1000 -featureType LBP -mode ALL
opencv_createsamplesの-numオプションには訓練画像の個数を指定します。
opencv_traincascadeの-bgオプションにはオブジェクトの写っていない背景画像の名前をリストにしたbg.datを与えています。
実行する前にcascade/ディレクトリを作っておく必要があります。
こうするとcascade/以下にcascade.xmlが出来上がるのでOpenCVでアニメ顔検出をやってみた - kivantium活動日記と同じ要領で物体を検出します。
出来たもの
オブジェクト検出器の学習(dlib)
ここで説明していたC++実装は精度が低いので削除しました。
Python実装を説明した
kivantium.hateblo.jp
を参照してください。