OpenCV で機械学習を試してみる…とまだ終わらず

テンプレートマッチングで画像から取り出すには無理がありそうなので、やはり、独自なオブジェクト検出器を作ってみないとだめか、と思い、

OpenCVで学ぶ画像認識:第4回 オブジェクト検出器の作成方法|gihyo.jp … 技術評論社
http://gihyo.jp/dev/feature/01/opencv/0004

を読んで、試しに、AdaBoost を使ってカスケードを作ろうと思ったのだが、いやあ、ちょっと時間が掛かりすぎる。

■学習用の正解ファイルの作成

1
2
3
4
5
6
7
C:\OpenCV2.3\build\bin\opencv_createsamples.exe ^
 -img images\koma01.png ^
 -vec koma01.vec ^
 -num 1000 ^
 -bg NG.txt ^
 -w 45 -h 45 ^
 -show

■オブジェクトの学習

1
2
3
4
5
6
7
8
C:\OpenCV2.3\build\bin\opencv_haartraining.exe ^
 -data koma01 ^
 -vec  koma01.vec ^
 -bg NG.txt ^
 -npos 1000 ^
 -nneg 467 ^
 -w 45 -h 45 ^
 -mem 200 ^

な感じで動かしていますが、4時間ほど経っても終わらず。

駒を検出したいので、今回の場合は正解画像は1つ(ゲーム中に出てくる画像)になるのですが、光の関係や画面を映す関係からいくつかの正解画像を用意します。そのあたりは、opencv_createsamples を使って、1000 枚の画像に水増しします。ファイルは別々にできずに、koma01.vec のように1つのファイルにまとめられます。

最初は、駒の画像が 90×90 だったので、そのまま指定したのですが、あえなくメモリーオーバーしてしまい opencv_haartraining がダウン。サイズを 45×45 にすると動くようになったので、対象画像はそこそこ小さいサイズにしないと駄目なのかも。

不正解の画像をどのように集めるのか?とも思ったのですが、マッチングしなければ何でもいいわけで、

Caltech101
http://www.vision.caltech.edu/Image_Datasets/Caltech101/Caltech101.html

にある適当なフォルダ(BACKGROUND_Google というランダムっぽい画像フォルダがある)を使っています。

うまく実行できると、下記のように、(多分)テンプレート画像を切り替えながら、閾値を切り替えながら学習し始めるわけですが…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
D:\work\OpenCV\src\PiyoDetect\PiyoML\data>opencv_haartraining.exe  -d
xml  -vec  koma01.vec  -bg NG.txt  -npos 1000  -nneg 467  -w 45 -h 45
 
Data dir name: koma01.xml
Vec file name: koma01.vec
BG  file name: NG.txt, is a vecfile: no
Num pos: 1000
Num neg: 467
Num stages: 14
Num splits: 1 (stump as weak classifier)
Mem: 200 MB
Symmetric: TRUE
Min hit rate: 0.995000
Max false alarm rate: 0.500000
Weight trimming: 0.950000
Equal weights: FALSE
Mode: BASIC
Width: 45
Height: 45
Applied boosting algorithm: GAB
Error (valid only for Discrete and Real AdaBoost): misclass
Max number of splits in tree cascade: 0
Min number of positive samples per cluster: 500
Required leaf false alarm rate: 6.10352e-005
 
Tree Classifier
Stage
+---+
|  0|
+---+
 
Number of features used : 1007032
 
Parent node: NULL
 
*** 1 cluster ***
POS: 1000 1000 1.000000
NEG: 467 1
BACKGROUND PROCESSING TIME: 0.22
Precalculation time: 0.05
+----+----+-+---------+---------+---------+---------+
|  N |%SMP|F|  ST.THR |    HR   |    FA   | EXP. ERR|
+----+----+-+---------+---------+---------+---------+
|   1|100%|-|-0.763750| 1.000000| 1.000000| 0.123381|
+----+----+-+---------+---------+---------+---------+
|   2|100%|+|-0.660565| 0.999000| 0.837259| 0.123381|
+----+----+-+---------+---------+---------+---------+
|   3| 94%|-|-1.246627| 0.996000| 0.490364| 0.104294|
+----+----+-+---------+---------+---------+---------+
Stage training time: 889.36
Number of used features: 3
 
Parent node: NULL
Chosen number of splits: 0
 
Total number of splits: 0
 
Tree Classifier
Stage
+---+
|  0|
+---+
 
   0
 
Parent node: 0
 
*** 1 cluster ***
POS: 996 1000 0.996000
NEG: 465 0.524831
BACKGROUND PROCESSING TIME: 0.03
Precalculation time: 0.05
+----+----+-+---------+---------+---------+---------+
|  N |%SMP|F|  ST.THR |    HR   |    FA   | EXP. ERR|
+----+----+-+---------+---------+---------+---------+
|   1|100%|-|-0.635385| 1.000000| 1.000000| 0.182752|
+----+----+-+---------+---------+---------+---------+
|   2|100%|+|-0.333012| 0.996988| 0.544086| 0.149213|
+----+----+-+---------+---------+---------+---------+
|   3|100%|-|-0.999921| 0.996988| 0.544086| 0.082820|
+----+----+-+---------+---------+---------+---------+
|   4|100%|+|-0.692312| 0.996988| 0.389247| 0.063655|
+----+----+-+---------+---------+---------+---------+
Stage training time: 1205.64
Number of used features: 4
 
Parent node: 0
Chosen number of splits: 0
 
Total number of splits: 0
 
Tree Classifier
Stage
+---+---+
|  0|  1|
+---+---+
 
   0---1
 
Parent node: 1
 
*** 1 cluster ***
POS: 993 1000 0.993000
NEG: 463 0.230923
BACKGROUND PROCESSING TIME: 0.13
Precalculation time: 0.05
+----+----+-+---------+---------+---------+---------+
|  N |%SMP|F|  ST.THR |    HR   |    FA   | EXP. ERR|
+----+----+-+---------+---------+---------+---------+
|   1|100%|-|-0.912574| 1.000000| 1.000000| 0.160027|
+----+----+-+---------+---------+---------+---------+
|   2|100%|+|-1.372380| 1.000000| 1.000000| 0.298077|
+----+----+-+---------+---------+---------+---------+
|   3|100%|-|-1.029186| 1.000000| 1.000000| 0.073489|
+----+----+-+---------+---------+---------+---------+
|   4|100%|+|-1.168364| 0.996979| 0.796976| 0.073489|
+----+----+-+---------+---------+---------+---------+
|   5| 98%|-|-0.856654| 0.996979| 0.455724| 0.049451|
+----+----+-+---------+---------+---------+---------+
Stage training time: 1487.86
Number of used features: 5
 
Parent node: 1
Chosen number of splits: 0
 
Total number of splits: 0
 
Tree Classifier
Stage
+---+---+---+
|  0|  1|  2|
+---+---+---+
 
   0---1---2
 
Parent node: 2
 
*** 1 cluster ***
POS: 990 1000 0.990000
NEG: 462 0.1232
BACKGROUND PROCESSING TIME: 0.53
Precalculation time: 0.05
+----+----+-+---------+---------+---------+---------+
|  N |%SMP|F|  ST.THR |    HR   |    FA   | EXP. ERR|
+----+----+-+---------+---------+---------+---------+
|   1|100%|-|-0.606609| 1.000000| 1.000000| 0.199036|
+----+----+-+---------+---------+---------+---------+
|   2|100%|+|-0.848618| 1.000000| 1.000000| 0.199036|
+----+----+-+---------+---------+---------+---------+
|   3|100%|-|-0.527684| 0.996970| 0.614719| 0.152204|
+----+----+-+---------+---------+---------+---------+
|   4|100%|+|-0.781167| 0.996970| 0.623377| 0.154959|
+----+----+-+---------+---------+---------+---------+
|   5| 79%|-|-1.579804| 0.997980| 0.632035| 0.112948|

そもそもの目的が、ゲーム画面から既知の駒(時には未知の駒?)を見つけ出したいわけで、顔認識ほど正確でなくてもよいし、ある程度の場所を確定してから再マッチさせるという方式がやっぱりよさそうか、と思い直している次第です。

OpenCVで学ぶ画像認識:第3回 オブジェクト検出してみよう|gihyo.jp … 技術評論社
http://gihyo.jp/dev/feature/01/opencv/0003?page=2

にあるように、何もないところから特定のものを見つける(検出する率が低い)場合には、このような学習がよいのかもしれませんが、あらかじめ駒があるとわかっているゲームの盤上から探すには、もっと前処理をして絞り込んでもよいかなと。オブジェクト検出器の中で Ture/False の判断をするよりも、その前処理として Ture/False を大雑把に判断するロジックを挟む必要がありそうです。いちいち、駒の形状が変わるたびに、学習をさせるわけにはいかないし、学習自体にそれほど時間を掛ける意味はなさそうだし。

なので、決定木あたりかクラスタリングを使って、駒のツリー(今回は8種類程度だけど)を作るのがよいのでしょう。

のように、色味で分割で大雑把に分割ができるのは明らかなので、なんらかの特徴量を元に背景画像から抜き出した後に、相互に駒を判断するために再び特徴量を使うという2段階になるのでしょう。

そんな訳でオライリーの OpenCV を再読。

カテゴリー: 開発, OpenCV パーマリンク