21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

リアルタイム物体検出システムdarknetをpythonでサーバ化

Last updated at Posted at 2017-10-09

やりたいこと

darknet というリアルタイムで物体検出できるオープンソースがあって、
これがけっこうすごい!
これをpythonでサーバ化して、イメージファイルを送ったら、
とりあえず、オブジェクトの名前とスコアが返ってくるようにしたい

https://pjreddie.com/darknet/yolo/

上記にチュートリアルとかあるので、まずはそちらをごらんください

前提

  1. darknetが動作すること
  2. python 2系統であること -> python3系統であること(18/08/11)

動作環境

  • Ubuntu 14.04 -> Ubuntu 16.04.4(18/08/11)

  • python 2.7.13 -> python 3.5.2

  • darknetのリビジョン 1b001a7f58aacc7f8b751332d3a9d6d6d0200a2d
    -> 9a4b19c4158b064a164e34a83ec8a16401580850

    最新のソースではバグが出る可能性はあります

ソースおよび動作方法

ソース

  1. https://github.com/komorin0521/darknet_server

動作方法

  1. darknetのチュートリアルを動作させれるようgit cloneしてmakeする
    できれば、darknet単独で予測が動くようにしてください
    (チュートリアルで利用する~~yolo.weights~~ yolov3.weightsを利用します)

  2. ソースって書いてあるソース一式をdarknet/pythonのフォルダにコピーしてください
    (libdarknet.soと同階層にdarknet_server.pyなど全てのファイル・フォルダをおいてください

  3. 必要なモジュールをpipでインストールしてください
    (sudo) pip install -r requirements.txt
    著者はpyenv + pyenv-virtualenv環境を利用してます。
    sudo権限が必要な場合は、つけてください

  4. PYTHONPATH=${darknetPATH}/python python3 darknet_server.py -cf ./cfg/yolov3.cfg -df ./cfg/coco.data -wf ./yolov3.weights -ud ./upload を実行してください
    うまくいけけばdarknetを単独で動作させた場合と同様にネットワークがロードされます

確認方法

curlで以下のように画像ファイルをアップロードしてください

curl -XPOST -F file=@./data/person.jpg http://localhost:8080/detect

jsonで下記のように結果が返ってこればOKです!

{
  "result": [
    {
      "name": "dog",
      "score": 0.8622361421585083
    },
    {
      "name": "person",
      "score": 0.8603283762931824
    },
    {
      "name": "horse",
      "score": 0.8156660199165344
    }
  ],
  "status": "200"
}

いろいろと補足

githubのdarknetのところに、python/darknet.pyがあったので、それを参考にしました。
この中身を見てみると、configファイルとweightload_netでロードしていて、load_metaにてメタ情報(といってもこの場合は、クラス名に一致するオブジェクト名(cfg/coco.datanames)を引っ張ってきているようでした。

さらに、ネットワークをロードしておいた上で、detectしている

また、結果を見てみると、N個の物体検出結果の配列で、
個々の検出結果はどうやら名前、スコア、バウンディングボックスの位置になっているっぽい

上記を前提に~~yolo.py~~のdarknet.pyの中に定義したYoloクラスの初期化メソッドで
ネットワークをロードしておいて、
/detectが呼ばれたらdetectを呼ぶようにすればよいのかと思い、そのようにしています。

なお、サーバからのレスポンスについては、記事を書いた当初(2017年10月9日)では、名前とyoloのスコアを返していましたが、2017年10月11日にバウンディングボックスの値も返すようにしました。

また、記事を書いた当初はHOSTやポートをハードコーディングしていましたが
引数で受け取れるように変更してます。

Flaskも(無駄に?)class化したら、
ちょっとはまったけど、stackoverflowにて解決!
はまったポイントは、FlaskではURIの定義を@app.route('/hoge')で定義するけれど、@self.app.route('/detect')ってしたら、エラーになった。
解決策を探してみると、どうやら'add_url_rule`(初めて知った!)にてURIを定義すればよいとのこと。
めでたしめでたし。

2017/11/1 APIの仕様追加

yolo本家では、確信度はdetectionを行う際に指定していたので、
APIでも指定できるように変更しました。
なお、デフォルト値は、(本家と同様なはずの)0.25にしてます。

curl -XPOST -F thresh=0.1 -F file=@./data/person.jpg http://localhost:8080/detect

と、-Fオプションで指定可能で、値を小さくするとより多くの物体検出結果が帰ってきますが、その分ご認識も多くなるので、ご注意ください。

# 2018/08/11 更新

  1. python3対応しました。python2とpython3で、ctypesの定義が変わっていたことに気づきました。参考:darknet yolo v3をpython3(.5.2)で試す
  2. yolov3対応.darknet側が更新されたので、現時点で最新版で動作することを確認しました。
  3. 予測埋め込み画像の更新しました。完璧ではないですが、予測結果画像を少しyolo本家に似せるように修正しました。
    20180811_180947_person_pred.jpg

参考

21
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?