Labellioを利用して自分のプロダクトに画像認識機能を簡単に追加する方法
皆様、こんにちは。
Labellio(ラベリオ, URL:https://www.labell.io/ja/)で頑張って画像認識モデルを作成したら、それをスマートフォンアプリやWebアプリなどの自分のプロダクトで利用してみたいと思いますよね。本エントリでは、Labellioで作成した画像認識モデルを自分のプロダクトで活用するために、画像認識Web APIサーバを構築する方法について説明したいとおもいます。
前提と想定するユースケース
本エントリでは、具体的なユースケースとして、すでに開発済みのWebアプリやスマートフォンアプリにLabellioで作成した画像認識モデルを利用して何かしらの付加価値を付けたい場合を考えます。この場合、すでにアプリは存在しますから、画像認識機能は別のサーバにREST APIを提供するマイクロサービス型の単一機能として実装するのが、保守やスケーラビリティの観点からも優れています。
Web APIサーバを開発する上では、もちろん様々な要件、ユースケースが想定されますが、本エントリではそのなかでも極めてシンプルなWeb APIサーバを開発します。サーバの仕様は、”http://[your domain]/classifyにHTTP POSTメソッドで画像を転送すると、認識結果のスコアの情報と、最も高いスコアの高いラベルの情報がJSON形式で返ってくるものとします。
実際のプロダクトでは、nginxやSupervisorなどの他のツールの活用、APIキーの設定や認証処理、画像のフォーマットチェック、よりわかりやすいエラーメッセージなどさまざまな要素を考慮する必要がありますが、本エントリーではサンプルのソースコードの可読性を向上させるため、これらの処理は含めていません。
動作環境
このようなWeb APIのマイクロサービスを提供するには、GPUインスタンスが提供されているAmazon Web Services(AWS)を利用するのが最適です。本blogでも以前に解説していますので参照して下さい。画像認識は比較的負荷の高い処理ですが、AWSであれば容易に負荷に応じてサーバ数を調整することもできます。
本エントリでも上記エントリと同様の手段で、Alpacaが提供するAMI(ami-9fe512db)をAWSの北カルフォルニアリージョンに作成したものとします。
実装言語はPython 2.7を利用します。これはCaffeのインターフェースやLabellioのライブラリはすべてPythonで提供されており、Pythonを利用するのが最もコストが低く実装できるからです。
実行するサンプルのソースコード
サンプルのソースコードは下記の通りです。
本サンプルではUPLOAD_FOLDERに指定したディレクトリに送られてきた画像を格納します。LabellioからダウンロードしたCaffe Modelは解凍したディレクトリをMODEL_FOLDERに指定します。サポートする画像形式はJPEGとPNGです。エラーチェックは送られてきた画像のファイル名の拡張子のみチェックします。”/classify”にPOSTメソッドで送られてきた画像は一旦UPLOAD_FOLDERに格納され、labellio_cliを用いてラベルの結果を取得、その結果をJSON形式で返します。
ソースコードの実行
1.作成したAWSのGPUインスタンスにSSHでログインします。
2.Flaskをインストールします。
$ sudo pip install flask
3.下記コマンドを呼び出します。これでlabellio_cliの各種機能が利用可能となります(本番稼働の際は.bashrcなどに登録しておくとよいでしょう)。
$ source /opt/caffe/caffe.bashrc
4.Labellioから取得したCaffe modelを解凍しmodelというディレクトリ名に変更します。画像を置くディレクトリtmpを作成します。
$ tar xzf [モデルのファイル名] $ mv [解凍後に作成されたディレクトリ] model $ mkdir tmp
5.上記サンプルコードをapp.pyとして保存し、以下のコマンドを実行します。これでWebサーバが起動されます。
$ python app.py
動作確認テスト
サンプルコードはFlaskのデフォルトのポート番号である5000番ポートで起動します。テスト実行時は、手元に認識対象の画像(ここではtest.png)を用意し、imageパラメータに画像を含め、curlなどのコマンドを利用してPOSTメソッドを設置したサーバの5000番ポートに対して発行してください。
$ curl -F "image=@test.png" http://[your domain]:5000/classify
AWSはデフォルトではポート5000へのアクセスはできないためそのための設定が必要となります。詳細は、「Linux インスタンスの Amazon EC2 セキュリティグループ」(http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-network-security.html)の「セキュリティグループへのルールの追加」章を参照してください。
JSON形式で認識結果、スコア、認識するラベル名が送られてきます。
{"0": {"score": [0.7100653052330017, 0.07795180380344391, 0.21198289096355438], "label": "alpaca"}, "label_name": {"sheep": 2, "gorilla": 1, "alpaca": 0}}
今回の結果では、sheep/gorilla/alpacaのラベルの中では、alpacaに最も一致している結果になります。
これで準備が整いました。同じようにあなたのアプリからHTTP POSTでURLにアクセスすれば、同様の画像認識を行うことが可能です。実際のアプリでは、一定スコアに達しない場合はそのラベルを利用しない(一致するラベルがなかった)などの目的に合わせたチューニングも検討する必要があります。