OpenCV2.4.0でHAAR分類器を学習させるときの問題と対策

こんにちは、ちきん(@mokemokechicken)です。
今回は、OpenCV2.4でHAAR-Like分類器などを新たに自分で構築する際に発生することがある問題と対策についてです。

前置き

HAAR分類器って?

OpenCVには有名な顔検出器があります。これはHAAR分類器で大量の画像データを学習することで作られたものです。
OpenCVでは、同じような手法で「何かの特定の画像を検出する機能」を自分で作ることができます。
この辺りの説明は、SlideShareの
第10回CV勉強会 OpenCV祭り 物体検出徹底解説!
がとてもわかりやすいのではないかと思います。

問題って?

このような「物体検出」をする分類器を自分で作るときのコマンドとして、

  • opencv_haartraining
  • opencv_traincascade

の2つがあります。
新しいのは後者の opencv_traincascade で、TBBを使ってマルチスレッドで動作したり、HAAR特徴だけでなくLBP特徴を使った分類器を作ることができるようになっています。そう、時代は opencv_traincascade なのです!(笑)

ただ、このopencv_traincascade関連の学習や性能評価のツールがちょっとバグっぽかったり、そもそも対応していなかったりします。
今回色々と対応する必要があったので、その辺を共有したいと思います。

本題

とりあえず、下記のような感じでLinuxにOpenCV2.4.0をInstallしてあるとして、話を進めます。
Install OpenCV2.4 Into AWS

opencv_traincascade が途中で落ちることがある

本家でも報告されている(opencv_traincascade crash)ようですが、
以下のような、エラーが表示されて学習中にcrashすることがあります。

===== TRAINING 1-stage =====
<BEGIN
OpenCV Error: Assertion failed (elements_read == 1) in get, file /home/peter/Desktop/opencv/apps/traincascade/imagestorage.cpp, line 154
terminate called after throwing an instance of 'cv::Exception'
what():  /home/peter/Desktop/opencv/apps/traincascade/imagestorage.cpp:154: error: (-215) elements_read == 1 in function get
Aborted (core dumped)

見た感じどうも、

  • POS画像リスト(-vec で指定するファイル)を読み込む部分の終端判定がおかしいようで、2.4.0から加えられたAssertionの部分でエラーが発生する
  • 学習の途中のstageでHRが下がると発生するようだ
  • opencv_traincascade の -numPosを 実際の含まれている画像数より(5〜10%分くらい)減らしたりすると発生しないようだ(POS画像リストの終端までいかないようにする)

という感じで、とりあえず面倒なら -vecで指定したファイルに1000枚画像があるなら、 -numPos を 950 くらいにしておくと防げます。

しかし、それもちょっと嫌だという場合は、このPATCHファイルを当てると一応落ちなくなります。
使い方は以下のようにします。

# cd [OpenCV-2.4.0.tar.bz2を展開しているDIR]
cd /usr/local/src/OpenCV-2.4.0
cd apps/traincascade
wget https://gist.github.com/raw/2766974/5acd3b92921fda46f1e4ce5d09c1d814c4b29af4/imagestorage.cpp.20100522.diff
patch < imagestorage.cpp.20100522.diff
# cd [cmake の build dir]
cd /usr/local/src/opencv
make opencv_traincascade
# bin/opencv_traincascade ができるので、適当なDIRにコピーして使う か sudo make install 等する

まだ少し表示がおかしい(実際のPOS画像数より1件くらい多く表示されたりする)んですが、大きな問題はないので本家で修正がされるまではこれで凌ごうかと思っています。

opencv_performance が 新しい形式のXMLを読み込まない

opencv_traincascadeで作られた分類器は最終的には1つのXMLファイル(cascade.xml)になります。
この分類機がどの程度の識別性能を持っているか評価するためのツールが opencv_performance なのですが、
opencv_traincascade で作られた新しい形式である cascade.xml を読み込んでくれません。。

自作できなくもないですが面倒な話なので、誰かが作って公開されているものをちょっと修正(多少バグがある)して使わせてもらっています
(このリンクのページの中段辺り)。
ただ、ご本人のコメントにもあるように、まだちょっと不十分な部分があるようです。

ちょっと修正したプログラム: performance.cpp

次のようにするとbuildできます。

# cd [OpenCV-2.4.0.tar.bz2を展開しているDIR]
cd /usr/local/src/OpenCV-2.4.0
cd apps/haartraining
# 一応 オリジナルを退避(旧型の分類器ファイルを読むにはオリジナルが必要)
mv performance.cpp performance.cpp.orig
wget https://raw.github.com/gist/2766934/87421082ce87f59c63676732f60d7013fadcbf7a/performance.cpp
# cd [cmake の build dir]
cd /usr/local/src/opencv
make opencv_performance
# bin/opencv_performance ができるので、適当なDIRにコピーして使う か sudo make install 等する

おわりに

自分でこういう画像認識機能を作るのはとても楽しいですが、動かないと急激にヤル気がなくなってしまいますよね。
本エントリーが何かのお役に立てれば幸いです。


Comments are closed.