お久しぶりです。私事でなかなか執筆の時間がとれず、前回の掲載から長く時間が空いてしまい申し訳ありませんでした。皆さんから寄せられたコメントには非常に励まされました。
というわけで、今回はいよいよ最終回です。前回はオブジェクト検出器を使って顔を検出するところまで行いました。今回は、オリジナルオブジェクト検出器を作成してみます。
今回作成するプログラムのソースコードは、こちらから一括してダウンロードすることができます。
学習の流れと仕組み
学習の流れ
前回のおさらいになりますが、オブジェクト検出器は機械学習という方法を通して作成されます。つまり、コンピュータプログラムに検出したいオブジェクトの画像(正解画像)とそうでない画像(非正解画像)を与えることで、オブジェクトが含まれている画像の傾向というのをコンピュータに覚えさせていきます。
学習の流れを簡単にまとめると以下の通りです。
- 正解サンプル画像と非正解サンプル画像を用意する
- サンプル画像のリストファイルをそれぞれ作成する
- 正解サンプル画像を元に、学習用正解ファイルを生成する
- 学習用正解ファイルと非正解リストファイルを元に、学習を行う
ここで解説する学習方法の詳細については、インストールディレクトリ下の"apps/HaarTraining/doc/haartraining.htm"を参照して下さい。
今回は、画像の中から下図のような技術評論社のロゴを抽出するプログラムを作成します。
学習の仕組み
第3回で解説したとおり、OpenCVのオブジェクト検出はAdaBoostで学習させた強識別器を複数連結(カスケード)したものになっています。
検出器の学習は、この1番目の強識別器から順番に進めていきます。
各ステージ(強識別器の学習)には、目標とする認識率(正解画像を正解と判断した率)及び許容できる誤認識率(非正解画像を正解と誤って判断した率)があり、それを達成するまで繰り返し矩形特徴(弱識別器)を追加しながらAdaBoostによる学習を行っていきます。
全体が目標とする認識率、及び誤認識率を達成した時点で学習は終了です。
このように、学習は多くの繰り返し処理を必要とするため、非常に時間がかかります(早くて数時間、長いと数日から数週間)。
学習時間は、全学習ステージ数(標準で14)、目標とする認識率、学習データの数などによって左右されますので、必要に応じて調整してください。
オブジェクト検出器の学習
画像の収集
まず、正解画像と非正解画像をそれぞれ収集します。
OpenCVのドキュメントによると、学習に用いる上で効率的なサンプル数は、正解画像7000枚、非正解画像3000枚とのことですが、ここでは正解画像4000枚、非正解画像1700枚程度で行います。
それだけ大量の画像をどこから集めるかですが、インターネット上には様々な画像素材提供サイトがあるので、そこから探すというのも一つの手です。またコンピュータ・ビジョンの研究分野では、実験用に顔画像やオブジェクト画像を提供している研究室がたくさんあるので、そういったデータを利用するのも良いかもしれません。
いくつか例としては、
- MITの顔画像データ
- カリフォルニア工科大学のオブジェクト画像データ
-
などがあります。
なお、正解画像を集める方法には2通りあります。一つは頑張って例えば自分でデジカメで撮影したり、インターネットから学習画像を集めること。もう一つは、1枚の画像に対して回転や変形などを加えることで、学習画像を増やす方法です。前者は顔や自動車など、個人差(車種)や表情などで形が変形するものに対して有効な方法で、後者はロゴなど形が一定のものを見つけたい時に適用します。
ここでは、後者の方法を用いて技術評論社のロゴを検出するプログラムを作成する予定ですが、前者についても解説します。
画像を収集したら、それを記述するリストファイルを作成します。
例として、下の図のようなディレクトリに非正解画像が入っている時、非正解画像のリストファイルは以下のような形式で書かれたテキストファイルになります。
一行一行に、作業ディレクトリからの画像ファイルへの相対パスが記述してあります。
同様の要領で、正解画像のリストファイルを作成します。ただし、ロゴ等の1枚の画像からツールで複数の正解画像を作成したい場合は、リストファイルの作成は必要ありません。
非正解画像のリストと違うのは、相対パスのファイル名の後に、数字が並んでいることです。
これは、画像中のオブジェクトの位置を表しています。OpenCVのオブジェクト検出では、検出窓で画像中をスキャンして、その窓の中にオブジェクトがあるかどうかを判定していくアルゴリズムで、学習もまたこの窓の単位で行われます(第3回参照)。そのため、学習の際には正確なオブジェクトの位置をプログラムに教えてやる必要があります。
ファイル名の後ろにある数字は、その画像中に何個オブジェクトが含まれているかを示しています。その後、4つの数字がオブジェクトの座標を表し、最初の2つがオブジェクトを囲む矩形の左上の座標値(x,y)、次の二つがそれぞれ幅と高さを表します。
では、次に収集した画像とリストファイルを用いて、学習用の正解ファイルを作成します。
学習用正解ファイルの作成
1枚の画像から大量の正解画像を作成するために、OpenCVでは"createsamples"というツールが用意されています。このツールを使って、ある一枚の正解画像から、ランダムに回転させたり、色を変えたり、任意の背景にオブジェクトを置くなどの処理を行った学習画像を作成することができます。
まず、OpenCVインストールディレクトリのbinの下にある以下のファイルを作業用ディレクトリへコピーして下さい。
- createsamples.exe
- haartraining.exe
- cv100.dll
- cxcore100.dll
- libguide40.dll
- highgui100.dll
次に、コマンドプロンプトを立ち上げて、作業用ディレクトリに移動し、以下のコマンドを実行します。
createsamples.exeが1枚の正解画像から、たくさんの学習用サンプルを作るためのコマンドです。以下の各オプションを使っています。
- -img
学習の元画像を示します。
1枚の画像からではなく、集めたたくさんの学習画像から学習用正解ファイルを生成する場合、-imgの引数を-infoに変えて正解画像リストファイルを指定します。
- -vec
出力ファイル名です。学習用画像データは全てこの1つのファイルにまとめられます。
- -num
作成する学習サンプル画像の数です。ここでは4000を指定しました。
- -bgcolor
背景色を示します。ただし単純にグレースケール画像の0から255までの濃度であらわします。この例ですと背景色は白なので255を指定します。
- -bg
この例ではロゴの背景は一様である場合がほとんどなので使用していませんが、もし検出したいオブジェクトが、複雑な背景の中にある場合が予想されるなら、このオプションで前節で作成した非オブジェクト画像リストを記したテキストファイルを指定します。
- -w
学習サンプル画像の横幅(ピクセル)を指定します。ここでは元画像の1/4のピクセルサイズを指定しました。
- -h
学習サンプル画像の縦幅(ピクセル)を指定します。学習サンプル画像では、元の画像を回転させたものが生成されるため、その遊びを持たせるために元画像の1/2のサイズを指定しました。
- -show
このオプションを指定すると、実際にどのようなサンプル画像が生成されたかを見ることができます。Windowが開いたらスペースキーを押すことで、次のサンプル画像を見ることができます。画像の閲覧をやめる場合はESCキーを押すか、ウィンドウを閉じてください。
事前にどのような画像が生成されるかを見ることで、その他のオプションのパラメータを最適化することをお勧めします。
他にも様々なオプションが用意されてますが、詳細はマニュアルを見て、対象に合わせてそれらのオプションを調整して下さい。
これで、正解ファイルが作成できました。いよいよ次は学習に映ります。
オブジェクトの学習
オブジェクトの学習には、"haartraining"というツールを使用します。なお、以下の作業を行った際に、突然PCが落ちるなど、うまくいかない場合があるかもしれませんが、その際はソースからhaartrainingを再コンパイルするようにして下さい。
学習を行うにはコマンドプロンプトから、次のように実行します。
- -data
出力したい学習結果xmlファイル名です。同名の作業用フォルダが自動的に作成されます。
- -vec
学習サンプルデータを指定します。
- -bg
非オブジェクト画像リストを記したテキストファイルを指定します。
- -npos, -nneg
それぞれ学習させる正解画像、非正解画像の枚数を指定します。
- -w, -h
createsamplesで指定したものをそのまま使用して下さい。
- -mode
使用するオブジェクト検出特徴の種類を指定します(第3回参照)。ここでは全ての種類の特徴を用いています。
これにより学習がスタートします。このコマンドを実行すると、最終的にgihyo.xmlというxmlファイルが生成されます。これが、オブジェクトパターンを表したデータになります。
学習の進捗は以下のように、画面上に表示されます。
上記の表の"node"または"stage"が一つの強識別器にあたります。この画面の例では2つの強識別器まで学習が終わっており、stage 2を親ノードとする3番目の強識別器が、3つの矩形特徴(弱識別器)を用いて学習が終わったところです。
もし計算時間がかかりすぎて途中で止めたいときは、Ctrl-Cなどで強制終了して下さい。再度haartraining.exeを同じオプションで実行すれば、学習が終わったステージから学習が再開されます。
表のNというのは、そのステージの強識別器の学習に要している弱識別器の数で、一つ一つ増やしながら目標となる認識率や許容できる誤認識率を達成するように調整を繰り返していきます。学習によっては、このNの回数が増え続けていつまでたっても終わらないという場合があります。これは、現在の学習データではどのようにパラメータを調整しても、なかなか目標値を達成できないということであり、その場合は学習画像の数やcreatesamplesのパラメータを調整するなどして、再度チャレンジした方が良いかもしれません。
オブジェクト検出プログラムの実行
では、本連載の第2回を参考にオブジェクト検出プログラムを作成して下さい。顔学習データ"haarcascade_frontalface_default.xml"の代わりに、今回学習させたxmlファイルを指定するだけで、実行が可能です。
このように、オリジナルのオブジェクト検出機を作成することができました。現時点で若干の誤認識がありますが、学習パラメータや学習画像を増やすなどして色々と試してみて下さい。
連載の終りに
これで4回にわたって行われた連載は終了です。この連載ではOpenCVのオブジェクト検出アルゴリズムを通して、皆さんに画像認識技術とはどういうものか、実感として少しでも伝えることを目的に始めました。
そして一方で、画像認識技術が人間の認識能力と比べて非常に見劣りするものであることも感じたのではないかと思います。
この分野はまだまだ発展途上の分野です。世界中の優れた研究者がしのぎを削って研究を行っており、次々と新しい手法が考案されています。認知科学や脳科学、数学、物理など他の分野からもどんどん新しい知見を取り入れています。この連載で扱ったアルゴリズムは画像認識の、さらにはコンピュータ・ビジョンという枠組みの中のごく一部でしかありません。
今、IT技術はどんどんコモディティ化が進み、アイデアさえあれば誰でもサービスが作れるような時代がきつつあります。少なくとも一昔前に比べれば、開発のハードルは圧倒的に下がりました。
それと比べると、画像認識の分野は誰もが簡単に開発できるほど技術が成熟してはいません。しかし、今後少しずつ一般の技術者でも使える画像認識技術が世の中に出てくると思います。OpenCVはそのための大事な一歩であることは確かです。
そして僕は、成熟していない分野だからこそインターネットの黎明期のように、技術者にとって非常に魅力的なフロンティアが広がっていると思っています。
この連載を通して、少しでも皆さんにこの魅力が伝わったなら、とても嬉しく思います。
最後までお読みいただき、ありがとうございました。