石仏用顔検出器の作成

この記事は1年以上前に書かれました。
内容が古くなっている可能性がありますのでご注意下さい。


OpenCV に付属する顔検出器(haarcascade_frontalface_*.xml)を用いた石仏の顔検出実験では、98枚のテスト画像のうち、(誤検出を含まず)正しく顔検出できたのは11枚という残念な結果でした。そこで、より高い精度で石仏の顔を検出できるよう、石仏の画像を用いてオリジナルの検出器を作成します。

OpenCV には、オリジナルの検出器作成を支援する opencv_createsamples と opencv_traincascade というユーティリティが付属しています。はじめに opencv_createsamples を用いて学習用の画像データファイルを作成し、次に opencv_traincascade を用いて学習を実行して検出器を生成します。

学習に用いる石仏の画像はブログ等から収集しました。著作権法第四七条の七において、情報解析のための複製は認められています。

(情報解析のための複製等)
第四七条の七 著作物は、電子計算機による情報解析(多数の著作物その他の大量の情報から、当該情報を構成する言語、音、影像その他の要素に係る情報を抽出し、比較、分類その他の統計的な解析を行うことをいう。以下この条において同じ。)を行うことを目的とする場合には、必要と認められる限度において、記録媒体への記録又は翻案(これにより創作した二次的著作物の記録を含む。)を行うことができる。

収集した画像は306枚でした。
つぎに、各画像ファイルにおける顔の位置とサイズを記したリストファイルを作成します。
画像ファイルを開いて顔の領域を矩形で選択し、矩形の左上の座標と、矩形の幅と高さを調べます。XnView という画像処理ソフトを使用すると、以下のようにウィンドウの下部に選択領域の情報が表示されます(この例で使用した画像は学習用に収集したものではなく、私が撮影したテスト用の画像です)。

選択した矩形の左上の座標が (378 163)、矩形の幅と高さが 127×156 です。そこで、正解画像のリストファイル(OK.txt)には以下のように記述します。

OK¥DHpLbucUIAEvUGT.jpg 1 378 163 127 156

最初の列に画像ファイル名、次に顔の領域の数、X座標、Y座標、幅、高さと続きます。画像ファイルは「OK」というフォルダに入っているものとします。画像に2つの顔が含まれる場合は、ファイル名の次の数字は2となり、X座標、Y座標、幅、高さの並びが2セット続くことになります。区切り文字はスペースです。

学習には、石仏の顔の写っていない非正解画像とそのリストファイルも必要になります。今回は、「月待ビンゴ」参加者のツイートに添付された画像のうち、文字塔と呼ばれる、像ではなく文字のみが刻まれた石塔の画像100枚を使用しました。非正解画像のリストファイル(NG.txt)には、ファイル名のみを列挙します。

以下のコマンドを実行し、学習用の画像データファイルを作成します。

opencv_createsamples.exe -info OK.txt -vec stone_statue.vec -num 306 -bg NG.txt -w 48 -h 48

-info で正解画像のリストファイル、-bg で非正解画像のリストファイルを指定します。出力する学習用データファイル名を -vec で指定します。-num は正解画像ファイルの数を、-w と -h で生成する学習用画像の幅と高さを指定します。
-show オプションを付けると、生成した学習用画像を見ることができます。座標指定が誤っていると、顔でない領域が表示されたり、場合によっては opencv_createsamples がエラーを出力して途中で終了しますので、最初は確認しながら処理した方が良いでしょう。

学習用の画像データファイルができたら、opencv_traincascade を用いて学習を実行して検出器を生成します。

opencv_traincascade.exe -data stone_statue -vec stone_statue.vec -bg NG.txt -numPos 250 -numNeg 100 -w 48 -h 48 -numStages 35

-data で出力ファイルを格納するフォルダ名を指定します。このフォルダはあらかじめ作成しておく必要があります。opencv_createsamples で作成した学習用の画像データファイルを -vec で指定し、-bg で非正解画像のリストファイルを指定します。-w と -h は必ず opencv_createsamples で指定した値と同じにします。
-numPos は正解画像の数、-numNeg は非正解画像の数を指定します。
正解画像の数は、opencv_createsamples で作成した数よりも少ない数を指定します。なぜなら、学習中に正解画像が非正解画像として誤認識されると、以降使用されなくなるためです。そのようなことになると、

Can not get new positive sample. The most possible reason is insufficient count of samples in given vec-file.

というエラーを出力して opencv_traincascade の処理が停止してしまいます。
-numStages は学習ステージの数を指定します。ステージ数を増やすと学習時間は増加しますが、検出器の精度は上がります。ただし、多ければ多いほど良いという訳ではなく、今回は35辺りで最も良好な結果が得られました。

学習が完了すると、-data で指定したフォルダに cascade.xml ファイルが出力されます。
これを OpenCV に付属する検出器(haarcascade_frontalface_*.xml)の代わりに使用したところ、98枚のテスト画像のうち、(誤検出を含まず)正しく顔検出できたのは38枚になりました。
その中には、2基並んだ月待塔の両方の顔を正しく認識できた例もありました。

同じ画像で、前回は右側の塔の顔しか検出できませんでした。
最後に、今回作成した石仏用顔検出器による検出例から、よくぞ検出できたものだと感心した画像を1枚示します。

OpenCVによる石仏の顔検出 12