takminの書きっぱなし備忘録 @はてなブログ

主にコンピュータビジョンなど技術について、たまに自分自身のことや思いついたことなど

OpenCVのtraincascadeのnumPos引数はvecファイル内のサンプル数より少ない数を設定すること

OpenCVの物体検出器を学習する際の注意点。


物体検出器の原理や学習方法については、ここを読んで下さい。


で、たとえば

opencv_createsamples -info positive.txt -num 1000 -vec hoge.vec -w 30 -h 30

みたいな感じで1000枚の正例画像からvecファイルを作ったとします。


次に

opencv_traincascade -data hoge -vec hoge.vec -bg negative.txt -numPos 1000 -numNeg 3000 -numStages 5 -w 30 -h 30 -minHitRate 0.995 -maxFalseAlarmRate 0.4

という感じで学習をさせると、以下のようなエラーが出ます。

OpenCV Error: Bad argument (Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.) in get, file /home/user/opencv/apps/traincascade/imagestorage.cpp, line 159
terminate called after throwing an instance of 'cv::Exception'


この原因と対処法は、ここらへんに書いてあります。

http://answers.opencv.org/question/776/error-in-parameter-of-traincascade/?answer=792#post-id-792
http://answers.opencv.org/question/4368/traincascade-error-bad-argument-can-not-get-new/


で、要約すると対処法は以下の式にしたがってnumPos引数の値を決めればOKです。


numPos =< (N-S) / (numStage + minHitRate - minHitRate * numStage)


ここで、Nはvecファイル内のサンプル数、Sは適当なバッファです。
またnumPos、minHitRate、numStageは、それぞれopencv_traincascadeの引数で

  • minHitRateは各ステージで満たすべき最小認識率
  • numPosは1つのステージで使用する正例の数
  • numStagesはステージ数

です。


以下、なぜそういうことになるのか興味のある人だけ読んで下さい。


学習の各ステージではvecファイル内のサンプルのうち、numPosだけが使用されます。
そして各ステージの最悪のケースでは、


numPos * (1-minHitRate)


の数だけの学習サンプル(正例)が背景と誤認識される可能性があります。
ここで背景と判断されたサンプルは、以後のステージでは使用されません。


したがって、棄却された分のサンプルを新たにvecファイルから継ぎ足してやる必要があります。
vecファイル内のサンプル数をNとすると、


N >= numPos + numPos * (1 - minHitRate) * (numStages - 1)


を満たす必要があります。さらに、各ステージでvecファイルから新たに追加されたサンプルが、現在のステージの識別器で(次のステージで使用される前に)即座に背景として棄却される場合もあり得るので、その数を仮にSとすると、


N >= numPos + numPos * (1 - minHitRate) * (numStages - 1) + S


となります。
したがって、numPosは以下の式にしたがって求めれば良いことになります。


numPos =< (N-S) / (numStage + minHitRate - minHitRate * numStage)