チョコボール統計

チョコボールの秘密を統計解析で明らかにしていく。おもちゃのカンヅメ欲しい。

チョコボール画像からチョコボールの個数を自動計測してみる

【update:2021/03/31】 ソースコードの全面的な更新に伴って、解説記事も書き直しました。本記事は記述に不足がありますので、改訂版を参照ください。

chocolate-ball.hatenablog.com

【update:2021/03/25】 本記事で掲載しているソースコードに一部不足がありました。修正して整理したソースコードを以下のGithubリポジトリにupしています。

github.com

概要

  • 当ブログではこれまで、チョコボールを手動で計測してきました
  • しかし、毎回チョコボールの数を数えるのはめんどくさい
  • そこで、画像から自動でカウントさせよう(チョコボールに特化した一般物体認識のモデルを使ってカウント)
  • Faster R-CNNをfine tuneしたところ、粒が密集した画像でもそれぞれの粒を認識できていそう!すごい!

【トップに戻る】

はじめに

当ブログのメインコンテンツは、ピーナツ味のチョコボールの計測です。 重さを測ったり、個数を数えたりしているのですが、従来、それらは全て手動で行われています。

一方、画像処理分野を発端として、深層学習(Deep Learning)の多方面での有効性が知られています。 (深層学習技術の進展はついていくことすら難しいレベルでどんどん進んでいますね。。。)
特に、一般物体認識(Faster R-CNN, YOLO等)は、専門に調査・研究していない人でもテレビ等で見たことがあるのでは無いでしょうか?

この一般物体認識ですが、ザクっと言うと、特定の物体が画像内のどこにいくつ存在するのかを認識するものです。 この技術を使えばチョコボールの個数をわざわざ数える必要がなくなるのでは無いでしょうか?! 毎回毎回数える時間コストを考えると、かなりの効率化が図れるような図れないような気がしてきました。

【トップに戻る】

問題設定

ということで今回は、 チョコボール画像からチョコボールの個数を自動で計測する仕組みを作ります。

データ

毎回の計測で、以下のような画像を撮影しています。

f:id:hippy-hikky:20180520000645j:plain:w300

スマートフォンのカメラを使って手動で撮影しています。 そのため、影(照明環境)や距離が一定ではありません。

アプローチ

深層学習の適用事例として有名なものの一つに「一般物体認識」というタスクがあります。 これは、画像の中に写っている複数の物体を個別に認識する技術です(下図参照)。

f:id:hippy-hikky:20180523000337p:plain:w300
一般物体認識の事例。この例では、人、車、馬を個別に認識している。犬は馬と誤認識しているが

この技術を応用し、画像内に写っているチョコボールを個別に認識することで、個数が計量できるというアプローチを取ります。

ただし、一般物体認識と言っても全ての物体を認識できるわけではなく、 予め学習した物体のみを認識できます。 当然、公開されている学習済みモデルではチョコボールを認識してはくれません。 そのため、独自の学習データセットを作成し、チョコボールが認識できるように追加学習(fine tune)することが必要です。

【トップに戻る】

前処理

ということで、まずは学習データセットを作ります。

アノテーションデータ作成

一般物体認識モデルを学習するためには、 学習データとして画像にチョコボールの位置を示す情報を付与したデータセットを作成する必要があります。 このデータセットのことをアノテーションデータセットと呼びます(下図参照)。

例えば、このような画像ファイルに対して

f:id:hippy-hikky:20180521231701j:plain:w300

この図のように、「どこ」に「何」があるのかを示すデータを作ります。

f:id:hippy-hikky:20180521225642p:plain:w300

アノテーションデータセットは、画像データ、物体位置座標(長方形の対角位置座標)のリスト、物体カテゴリのリストがセットで必要になります。 このデータを作るために、LabelImgというツールを利用しました。
使い方はgithubのページを見ればわかると思います。

なお今回は、上図のように、認識対象の物体カテゴリとして、 choco-ball(チョコボールの粒)とchoco-package(パッケージ画像)の2つの物体を認識するものとしました。

PascalVOC形式xmlデータのパース

LabelImgというツールでは、 アノテーションデータをPascalVOC形式のxmlファイルで出力できます。

このままでは学習用データセットにはならないので、xmlファイルを読みこんで必要な情報を抜き出す必要があります。 PascalVOC形式のxmlをパースする便利なライブラリは私がちょっと探したところ見当たらなかったので、 以下のように作りました。

xmltodictというxmlファイルをdict形式でパースするライブラリを使い、 画像データ(imgs)、バウンディングボックスの座標リスト(bboxs)、物体カテゴリIDのリスト(obj_ids)をnumpyオブジェクトで書きだしています。

【トップに戻る】

認識モデル

一般物体認識モデルは複数提案されていますが、今回はFaster R-CNNを使います。 Faster R-CNNについては、日本語での解説記事も多数あるのでここでは言及しません。

認識する物体として今回は、choco-ballとchoco-packageの2つだけを認識するようにしました。 今回のタスクにおいては、一般物体を認識する必要など無いのです。

Faster-RCNNの実装はChianerCVを使いました。 ChainerCVとはChainerベースの画像処理ライブラリです。 後ろにコードを載せていますが、かなり簡潔に書けます。

【トップに戻る】

学習実験

いよいよ学習です。

実験設定&コード

今回の実験では、学習データとしてチョコボール画像22枚を用意しました。 (画像自体はもっとあるのですが、アノテーション作業が大変だったので。。。) このデータを8:2で分割し、学習データと評価データに分けました

  • 学習データ:17ファイル
  • 評価データ:5ファイル

学習係数などのパラメータはChainerCV公式exampleの設定をそのまま使いました。

コードは以下の通りです。 ChainerCVのexampleを ほぼほぼコピーさせてもらっています。

4セル目から6セル目でnumpyオブジェクトで保存した画像データ、バウンディングボックス座標リスト、物体カテゴリIDリストを 読み込んでいます。
読んだデータは、ChainerCVで扱いやすいようにTupleDatasetという形式のデータにしています(7セル目)。

9セル目でFasterRCNNのオブジェクトを作っています。 引数で今回認識対象とする物体(choco-ballとchoco-package)の指定をしています。 また、pretrainedmodelには、imagenetを指定します。 独自データで学習する際には、imagenetを指定する必要があるらしいです。

optimizerやiteratorはほぼexampleの通りです。

17〜21セル目でextentionの指定をしています。 公式exampleではiteration数でモデルの書き出し等設定していましたが、 epoch数で制御したほうが分かりやすかったのでepochで規準を作っています。

学習結果

上記のnotebookの23セル目に学習曲線(lossカーブ)がありますが、 20epoch学習させてみた結果です。 想定通りlossが落ちたように見えます。

f:id:hippy-hikky:20180523002647p:plain

もう少し学習させても良さそうですが、一旦これで評価してみます。 notebookの24セル以降が評価用のコードです。

評価用の5データのチョコボール数を算出したところ、 MSE(平均二乗誤差)が1なので、平均1個の誤認識があるようです。
これで十分な精度かどうかというと、、、ちょっと微妙かな。。。 (正確にはcross-validation必要)

試してみる

とにかく、学習したモデルを使ってチョコボールの認識をしてみましょう。 アノテーションをつけていない画像を入力して結果を見てみます。

うまく行った例

1枚目はそれぞれの粒がばらついているので簡単そうです。 2,3枚目はかなり密集していますが、それでもそれぞれの粒を認識できているようです。

f:id:hippy-hikky:20180523004801p:plain

f:id:hippy-hikky:20180523004831p:plain

f:id:hippy-hikky:20180523004850p:plain

検出ミスがあった例

やはり、密集していると見落としがちなようです。 3枚目の歪な形の物も見落としています。

f:id:hippy-hikky:20180523005156p:plain

f:id:hippy-hikky:20180523005233p:plain

f:id:hippy-hikky:20180523005127p:plain

【トップに戻る】

まとめ

22枚のデータを使ってFaster R-CNNをfine tuneしてみました。 結果としては、チョコボールの粒が密集した画像でも正しく粒を認識できているものがあるので、 この仕組みは有望だと感じます。 しかし、評価データで定量的に誤差を計算すると、平均1粒の計数ミスが生じるようで、まだ実用的というのは難しいかもしれません。

評価に関しては、評価データが5つしか無いのでcross-validationが必要です。 今回ざっくりと作ってみたところ有効そうな結果が見えてきたので、 データをもっと作り、また、cross-validationによって正確な評価をしてみようと思います。(今後の課題)

そういえば、粒のカウント工数を減らすことが目的だったんですが、、、 なかなか手間が減らなさそう(汗)

【トップに戻る】

参考資料

【トップに戻る】

広告

Amazonの欲しいものリスト作ってみました。 チョコボールのカンパ募集中です。
チョコボールをカンパする

森永製菓 チョコボール<ピーナッツ> 28g×20箱

森永製菓 チョコボール<ピーナッツ> 28g×20箱

  • 発売日: 2016/03/01
  • メディア: 食品&飲料