OpenCV 物体検出、分類器作成と検出テスト その2

その1で分類器によって物体検出ができることがわかりましたので、その分類器を作成してみます。

分類器作成にはポジティブ画像(正解画像)とネガティブ画像(不正解画像)が必要です。実用的な精度にはポジティブ画像7000枚、ネガティブ画像3000枚が必要とか言われていますが、実際その枚数揃えるのは結構大変です。特にポジティブ画像。
そこで、OpenCVでは1枚の正解画像から複数枚の画像を生成する機能ががあります(角度や大きさを変えて生成してくれます)。これを使えば、例えば50枚の正解画像を用意してそれぞれから128枚を自動生成それば6400枚に増やすことができますね。

ではさっそく、家紋の分類器を作成してみます。

家紋は非常にたくさんの種類があります。全部集めるのは大変なので適当に60種類ほど正解画像を作成してみました。
あまり小さいと検出精度が上がらなかったので、今回は87×87のサイズで用意しました。
輪郭より外側は白で塗りつぶしています。自動生成で枚数を増やす時にネガティブ画像上に貼り合わせるのですが、その時にこの白色が透過色となります。

ネガティブ画像はなんでも良いのですが、正解画像が含まれていない画像を用意します。風景、室内、建物、PC、動物など適当な画像です。

白黒画像になっていますがカラーで良いです。
画像サイズは640×480、320×240、1280×700などさまざまです。これを3000枚用意しました。

フォルダを3つ用意し「OpenCV」フォルダにOpenCVのコマンド、「Positives」フォルダにポジティブ画像、「Negatives」フォルダにネガティブ画像を格納しました。全部同一の階層に作成しています。

OpenCVTest
+ OpenCV
+ Positives
+ Negatives

ネガティブ画像は画像リストが必要となるので事前に作成しておきます。
コマンドプロンプト画面を表示し、Negativesフォルダに移動して次のコマンドで画像リストを作成します。

dir /B > negatives.txt


これでネガティブ画像のリストができました。

つづいてポジティブ画像を増やしていきます。
OpenCVフォルダに移動して、コマンドプロンプトで次のコマンドを入力します。ポジティブ画像はPositive001.jpgからPositive060.jpgまで連番で用意しました。

opencv_createsamples.exe -img ..¥Positives¥Positive001.jpg -bg ..¥Negatives¥negatives.txt -info ..¥Positives¥cropp001.txt -num 128 -maxxangle 0.5 -maxyangle 0.5 -maxzangle 0.3 -bgcolor 255 -bgthresh 8 -w 48 -h 48

-imgには用意したポジティブ画像を。-infoには生成した画像の一覧の出力先ファイル名を。-bgはネガティブ画像のリストファイル。-numは生成する画像の枚数。-maxxangleと-maxyangleと-maxzangle生成時にどの程度回転させるかを。-bgcolorはポジティブ画像の背景色で、255が白、0が黒。-bgthreshは透過度です。0が100%透過。
成功すると、ネガティブ画像上にポジティブ画像の角度や大きさを変えた画像が生成されます。

また、その画像の一覧のファイルも作成されます。

生成されたポジティブ画像の一覧ファイルはネガティブ画像のと違い、スペース区切りのCSVファイルとなります。ファイル名の後ろは正解画像部分の数、その開始位置X、開始位置Y、幅、高さ、です。この部分は自動で生成されるので特に修正などする必要はないです。

用意したポジティブ画像ぶん、-imgと-infoのファイル名部分を変えながら全て行います。

たまにですが、ポジティブ画像の自動生成を行うと次のエラーが出る場合があります。

OpenCV Error: Incorrect size of input array () in cvGetSubRect, file C:\Tools\opencv3.2\sources\modules\core\src\array.cpp, line 1275

その際は、このコマンドを実行するときだけネガティブ画像のリスト件数を作成する画像数(ここでは128)に減らして実行するとエラーが出にくくなります。

全てのポジティブ画像を増やし終わったら、作成されたポジティブ画像の一覧ファイルを結合します。この手順ではcropp001.txt からcropp060.txtまで作成されているので、コマンドプロンプトでポジティブ画像のフォルダ(Positives)に移動して次のコマンドで結合します。

type cropp*.txt > positives.txt

結合されたpositives.txtには60×128で7680行のポジティブ画像のデータが記録されているはずです。

 

続いて、ベクトルファイルを生成します。

が、その前に作成するベクトルファイルと分類器を格納するフォルダを作成しておきます。OpenCVフォルダに「vector」フォルダと「cascade」フォルダを作成します。

ベクトルファイルの作成もopencv_createsamplesコマンドを使用します。コマンドプロンプトからOpenCVのフォルダに戻って次のコマンドを入力します。

opencv_createsamples.exe -info ..¥Positives¥positives.txt -bg ..¥Negatives¥negatives.txt -vec .¥vector¥croppkamon.vec -num 7680 -w 48 -h 48

-numにはポジティブ画像の枚数を指定しますので、Positives.txtのデータ数を設定します。

成功すると次が表示されます。このコマンドは数分でおわります。
Done. Created 7680 samples

 

最後に分類器の作成です。
ここまでの手順が長かったですが、このコマンドは実行時間はさらに長いです。

opencv_traincascade.exe -data .\cascade -vec .\vector\croppkamon.vec -bg ..\Release\Wrong\negatives.txt -numPos 6500 -numNeg 3019 -numStages 20 -precalcValBufSize 1024 -precalcIdxBufSize 1024 -featureType LBP -minHitRate 0.995 -maxFalseAlarmRate 0.5 -w 48 -h 48

-numPosはポジティブ画像の枚数を指定しますが、用意した数の80%から90%程度を指定してください。ポジティブ画像として妥当ではないと判断された時に除外されるようです。-numNegはネガティブ画像の枚数です。-featureTypeはHAARかLBPかHOGを指定します。それぞれ特徴の抽出の仕方が異なります。

実行した際に次のエラーが出てしまった場合、
Train dataset for temp stage can not be filled. Branch training terminated.
Cascade classifier can’t be trained. Check the used training parameters.
ネガティブ画像のリストを修正します。いまはファイル名だけのリストになっていますので、これを全てフルパスにします。

正しくコマンドが開始されると、次のような感じで学習が始まります。

PARAMETERS:
cascadeDirName: .\cascade
vecFileName: .\vector\croppkamon.vec
bgFileName: ..\Negatives\negatives.txt
numPos: 6500
numNeg: 3019
numStages: 20
precalcValBufSize[Mb] : 1024
precalcIdxBufSize[Mb] : 1024
acceptanceRatioBreakValue : -1
stageType: BOOST
featureType: LBP
sampleWidth: 48
sampleHeight: 48
boostType: GAB
minHitRate: 0.995
maxFalseAlarmRate: 0.5
weightTrimRate: 0.95
maxDepth: 1
maxWeakCount: 100
Number of unique features given windowSize [48,48] : 141376

===== TRAINING 0-stage =====
<BEGIN
POS count : consumed 6500 : 6500
NEG count : acceptanceRatio 3019 : 1
Precalculation time: 30.424
+—-+———+———+
|  N |    HR |     FA |
+—-+———+———+
|  1 |       1 |       1 |
+—-+———+———+
|  2 |       1 |       1 |
+—-+———+———+

0ステージ目の学習が開始ししました。これが19ステージまで完了するとカスケード分類器がcascadeフォルダに作成されています。ファイル名は「cascade.xml」です。
このコマンドは途中で中止しても、同じコマンドを実行すれば続きから学習させることができます。もし、最初からやり直したい場合は、cascaseフォルダに作成されたXMLファイルを全て削除してから行って下さい。

 

ちなみに私のチープな環境でコマンドが終了した時の最後の出力内容。

+—-+———+———+
| 16| 0.995143| 0.501491|
+—-+———+———+
| 17| 0.995286| 0.480623|
+—-+———+———+
END>
Training until now has taken 0 days 14 hours 23 minutes 2 seconds.

14時間30分ほどかかりました。。

次回は作成された家紋のカスケード分類器を使用して検出確認をしてみます。

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です