実験やめたった シマエナガ編

劇団「実験やめたった」の活動報告

OpenCV3.1のcv::dnnを使ってCaffeModelを使った画像分類をWindows上でやる

 

アブストラクト(概要)

Windows7 + Visual Studio 2013 Community + OpenCV3.1 + cv::dnn の環境を作りました。

・CaffeNet、GoogLeNetによる画像分類が動きました。

・自作学習データを使うにはどうしたらいいかという記述がネット上にありませんでしたので、苦労しましたが、がんばって調べた結果、一応動くようにはなりました。

・しかし、挙動がまだ完全に理解できていないので、 cv::dnnのユーザーが増えて誰か筆者にそこのところを教えてくれないかなあと思っています。

 

はじめに:いきさつ

 筆者はつねづねDeep Learningの定番ライブラリ:Caffeの画像分類を、Windows + OpenCVでもやりたいと思っておりました。筆者の職場の計算機はほぼすべてWindowsで、これまでは、(1)OpenCVで作った物体抽出器で画像中の候補箇所をトリミングし、(2)その画像をLinuxに転送してCaffeで画像分類・・・というまわりくどいことをしていました。もしCaffeの画像分類がOpenCVの枠組みで実現できるとしたら、工程が減るので使い勝手がよいわけです。そんな状況のなか苦戦の末、OpenCVのcv::dnn(ディープ・ニューラル・ネットワーク)モジュールの使い方がわかったので、その方法を紹介します。

 

OpenCV3.1+opencv_contribを自前でビルド

Q.えー、ビルドとかやったことないですー。いつもここからダウンロードしたものを展開して使っているのですが・・・。

A.いまのところ、プレビルト版にはdnnモジュールは入っていません。dnnモジュールを使いたかったらこれを含めた版を自前でビルドする必要があります。(探せば誰かがビルドしてくれたバイナリ版もなくはないですが、CPUとかライブラリの構成を最適にするには自前で設定してビルドするのが良いと思います。:20160412加筆)

 

というわけで若干ハードルが高いですがやってみましょう。なお、ビルドに関して筆者が参考にしたサイトはこちらです。

OpenCV3.1のビルド - AkiWiki

OpenCV 3.0がリリースされたので導入してみた - Qiita

OpenCV: Build opencv_contrib with dnn module

 

まずインストールすべきもの

・CMake。ビルドに関する諸設定をして、ビルドのためのVisual Studioのファイル(ソリューションと言う)を生成する。

Visual StudioVisual Studio Communityという版は個人用利用だったらフリーで使用できる。ちなみに筆者は2013を使った。

 

ビルドの手順の概要

Githubから、opencv本体、opencv_contribのソースコードをダウンロードし、適当な場所に配置。

・CMakeでビルドの設定をし、Visual Studioソリューションファイルを生成。

Visual Studioでビルド。

・できたバイナリファイル(*.libファイルなど)やincludeファイルなどを、適当なフォルダに配備してPATHを設定する。

 

うごかしてみよう

 こちら↓に詳しい解説の記事があります。実際に動かしてみたとき、caffenetがねこの識別結果を出してきたら成功です。ただし落とし穴があって、「"caffe.LayerParameter" has no field named "input_param"」というエラーが出てきた時はprototxtの記述が対応していないので変更する必要があります。

 

qiita.com

 

prototxtの記述の変更の方法:

OpenCVでニューラルネットワークのcaffeモデル読み込み | MOGINOメモ

 

こちらは公式のチュートリアルです。GoogLeNetスペースシャトルの識別結果を出してきたら成功です。

OpenCV: Load Caffe framework models

 入力画像を指定する際にnet.setBlob(".data", inputBlob)と記述します。このdataの前のドットは何を意味するのかが不思議だったのですが、このチュートリアルに書いてありました。この引数では"name_of_layer.name_of_layer_output"と記述します。ここで、最初レイヤーには名前がないので".data"とするそうです。

 

自作学習データで動かしてみよう

 筆者の手元にDIGITSで生成したAlexNetの学習データがあります。これを利用するには、cv::dnn::createCaffeImporter() の箇所やその他特定のファイル名を、自作学習データのファイル名に変えてやります。しかしまたここにも落とし穴があって、平均画像(mean.binaryproto)を差し引く処理を自分でやらないといけないようです。(本家Caffeだったらprototxtの中で、layer.transform_param.mean_file: "mean.binaryproto"・・・と指定できるのだが、現在は多分対応していない。)

 以下が筆者の書いた画像を差し引く処理です。このときMatの輝度値が負の値になることがあるので、データの型はCV_16S(符号付16bit整数)としています。(20160411一部修正)

 

 

 こうして一応はそれらしい識別結果が出るようになりました。しかし検証のためにこの結果とDIGITS経由で識別させた結果を比較してみると、softmaxの出す確率の値が違っています(要するにまだ完全に挙動が理解できていない。)。何が原因なのか、どなたか詳しい方、筆者に教えてやってください。筆者もひきつづき調査をすすめていきたいとおもいます。

 

DIGITS経由の識別の結果(A,B,T,Vの4カテゴリー)

00001.png Predictions
    81.77% A
    17.22% V
    0.93% T
    0.08% B

 

同じファイル、学習データをcv::dnnで識別させた結果

00001.png
V : 53.5173 %
A : 23.9567 %
T : 22.1351 %
B : 0.390848 %

_人人人人人人_
> なんか違う!<
 ̄Y^Y^Y^Y^Y^Y^ ̄

 

謝辞

 kibo35さん、いつも筆者の研究を応援してくださりありがとうございます。最近筆者はPETやSPECTなど、物理学が人々の健康に役立っているのを見ると物理屋としての誇りを感じます。DeepMindのハサビス氏は「人工知能技術を素粒子物理の分野などで科学をより発展させるのに使いたい」とコメントしておりますが、筆者も同感で、この技術を(AVの次に)物理学に生かすことが出来たら、と思っております。

www.theverge.com