Chainerを使って☆を検出

  • 12
    いいね
  • 0
    コメント

はじめに

 以前、Chainer Meetup #03の方でお話したネタになりますが、クリスマスということもありまして☆飾りの「角」の検出についてご紹介します。また、今回は最近話題となっているpix2pixのようなことも試してみました。

準備

  • データの作成

星の飾りを紙の上にばらまいて、デジカメで写真(画像A)を1枚とり、その後、手でシャッフルして、もう1枚写真(画像B)を撮影しています。画像Aは学習用に使い、画像Bはテスト用に使います。

  • 教師画像の作り方

星の角の位置を教える画像を作るため、まず、星の角をクリックして、位置を取得するUIを作成しました。javascriptの描画用のライブラリであるfabric.jsをjupyter上で動かして、クリックした位置をpython側に受け渡して保存してます。(jupyterでhtml-javascript側の値を取得するメモ)

◎クリックするUIの動画


このクリックした位置に「球」のようなもの描画して、教師画像としています。

20161210_教師説明 (1).png

  • 学習方法

<学習時>
画像Aからランダムな位置で画像を切り出し100枚のバッチを作成します。
生成画像が教師画像に近くなるようにネットワークを学習(後述)させます。

<テスト時>
学習したネットワークに画像Bを入力させ、生成画像をつくり、生成画像に対し極大値を抽出することで、それぞれの特徴点の位置を抽出(固定した閾値を使用)させています。その位置を使って、元の画像Bに円を重ね書きしています。

直接誤差での学習

20161207_直接誤差学習.png

生成器のネットークはconvolutionとdeconvolutionで作ってあります。学習には生成画像と教師画像の個々のピクセルに対し平均二乗誤差をとり、それを逆伝播させて生成器を学習しています。

◎直接誤差で学習の動画(動画は32倍速で再生)
描画にはbokehを使ってjupyter上に表示させ、それを動画でキャプチャしました。学習に使う画像Aではなく、テスト用の画像Bでの出力結果になります。

最初にドーナッツ状に学習した後、個々の角に球状の模様を作って学習している様子がみられます。

pix2pixでの学習

20161207_pix2pix.png
原論文はほぼ読めてないので、pix2pixと呼べるかわかりませんが、それっぽく学習させています。生成器Gのネットワークは同じconvolutionとdeconvolutionの形にしました。
生成器Gの学習時は判別機Dの出力が本物となるよう誤差を伝播させ、判別機Dの学習時は判別機Dが正しく判別できるように誤差を伝播させています。当然直接位置を教えてなく、正解か不正解でしか誤差は伝わらないため、学習しづらくなるはずです。今回の場合はあまり意味はありませんが、位置が重要でなく数だけ数えたい場合に便利な可能性があったので試してみました。

◎pix2pixで学習の動画(動画は96倍速で再生)


学習には「直接誤差での学習」よりも学習が進むのが遅くなっています。
途中で真っ黒になってだめかと思いきや、N train=180000枚くらいから復活しています。
「直接誤差での学習」の場合は星の周りにドーナッツ状になっていた過程がありましたが、こちらでは判別器だますことが重要なので、位置はともかく球ができることを優先してそうです。
成功率は50%以下で永遠に学習しない状態に陥ることがあります。

おわりに

今回、角の検出を行いましたが、中心を教えれば中心が検出できるはずです。
コードは読みにくいかもしれませんが、GitHubに公開してみましたので、よかったら試してみてください。

この投稿は Chainer Advent Calendar 201613日目の記事です。