みらいテックラボ

音声・画像認識や機械学習など, 週末プログラマである管理人が興味のある技術の紹介や実際にトライしてみた様子などメモしていく.

YOLOv3を試してみる(3)

オリジナルデータで物体検出を試してみたくなり, 久々にYOLOを触ってみることに...
YOLOは, 昨年少し触っていたYOLOv2からYOLOv3にバージョンアップしており, 今回はYOLOv3をPythonから利用する方法について, 少しまとめておく.


関連記事:
YOLOv2を試してみる(1)
YOLOv3を試してみる(2)
・YOLOv3を試してみる(3)


YOLOv3をPythonから利用する方法として, 二通り試してみた.
1) ctypesを使う. (darknet/python/darknet.py)
2) keras-yolo3を使う.

1. ctypes[1]
ctypesとは, pythonC言語のライブラリを操作するためのライブラリである.
darknetのインストールディレクトリ下には, python/darknet.pyなるサンプルコードがあるので, これを使って物体検出を行ってみる.

今回初めてctypesを使うので, darknet.pyを参考に使い方を学ぶ.

1.1 ライブラリのロード
ライブラリをロードするには,
  ctypes.CDLL(libname)
を使用する.

from ctypes import *

lib = CDLL("libdarknet.so", RTLD_GLOBAL)


1.2 構造体の定義
Cの構造体に対応するクラスをpython側で定義するようだ.

# 矩形の定義
class BOX(Structure):
    _fields_ = [("x", c_float),
                ("y", c_float),
                ("w", c_float),
                ("h", c_float)]

# 画像データの定義
class IMAGE(Structure):
    _fields_ = [("w", c_int),
                ("h", c_int),
                ("c", c_int),
                ("data", POINTER(c_float))]


1.3 関数の定義
引数や戻り値のない関数はそのまま利用することができるが, 引数や戻り値がある場合はPython側でデータ型を明記する必要があるようだ.

# network *load_network(char *cfg, char *weights, int clear)
load_net = lib.load_network
load_net.argtypes = [c_char_p, c_char_p, c_int]
load_net.restype = c_void_p

# image load_image_color(char *filename, int w, int h)
load_image = lib.load_image_color
load_image.argtypes = [c_char_p, c_int, c_int]
load_image.restype = IMAGE


1.4 動作確認[2]
darknet.pyは, python 3系で動かすには若干の修正が必要である.
C関数の引数に文字列を渡す際に, c_char_pに対してstr型の"cfg/yolov3-test.cfg"を渡すようで, これをバイト列にしてやる必要がある.
ここで少しハマった!

if __name__ == "__main__":
    net = load_net(b"cfg/yolov3-test.cfg", b"backup/yolov3-test_final.weights", 0)
    meta = load_meta(b"cfg/test.data")
    r = detect(net, meta, b"test.jpg")
    for r0 in r:
        print(r0)

[画像]
f:id:moonlight-aska:20181231234632j:plain:w400
[実行結果]

(b'Car', 0.998721182346344, (175.69290161132812, 230.9979248046875, 107.79170227050781, 69.38579559326172))
(b'Car', 0.955277144908905, (44.639244079589844, 235.98455810546875, 94.31153869628906, 41.028072357177734))
(b'Signs', 0.9252675175666809, (570.2070922851562, 146.4308624267578, 19.322128295898438, 16.191734313964844))
(b'Car', 0.8757637739181519, (439.9433898925781, 297.7780456542969, 431.86517333984375, 205.927001953125))
(b'Car', 0.7671501636505127, (108.61651611328125, 230.19583129882812, 78.11087799072266, 39.77518844604492))
(b'Signs', 0.7385135293006897, (349.7156066894531, 123.2014389038086, 22.234079360961914, 22.38388442993164))
(b'Signs', 0.5390903353691101, (610.5639038085938, 145.1051483154297, 18.0130672454834, 17.494369506835938))

f:id:moonlight-aska:20181231234807j:plain:w400


2. keras-yoko3[3]
YOLOv3をkerasで動かそうという試みがいくつかある.
https://github.com/qqwweee/keras-yolo3
今回は, 上記を使って, YOLOv3の学習済モデルを試してみた.

2.1 モデル変換
YOLOv3の学習済モデルを利用するにあたり, モデルの重みを変換する必要がある.

python convert.py cfg/yolov3-test.cfg backup/yolov3-test_final.weights model_data/yolov3-test.h5


2.2 動作確認
yolo_video.pyに引数でモデル等のパスを渡せるようになっているが, どうもうまく処理されてないようなので, yolo.py内で定義されているデフォルトを修正する.

class YOLO(object):
    _defaults = {
        "model_path": 'model_data/yolov3-test.h5',
        "anchors_path": 'model_data/yolo_anchors.txt',
        "classes_path": 'model_data/test.names',
        "score" : 0.3,
        "iou" : 0.45,
        "model_image_size" : (416, 416),
        "gpu_num" : 1,
    }

[実行結果]

Input image filename:test.jpg
(416, 416, 3)
Found 9 boxes for img
Signs 0.39 (602, 136) (620, 155)
Signs 0.60 (339, 112) (361, 134)
Signs 0.64 (561, 138) (580, 155)
Truck 0.56 (149, 173) (314, 273)
Car 0.78 (183, 188) (316, 278)
Car 0.84 (69, 210) (147, 250)
Car 0.93 (213, 191) (663, 402)
Car 0.96 (0, 216) (92, 256)
Car 1.00 (122, 196) (230, 266)
2.0341595780000716

f:id:moonlight-aska:20190101091859p:plain:w400

YOLOv3をいろいろと試すためには, pythonから使えた方が便利と思い二通りの方法を試してみたが, 物体検出の結果が若干異なるようだ.
画像の前処理とか何か少し異なるのかな?
keras-yolo3も一応学習を行う仕組みもあるようなので, keras-yolo3で学習すればそういったズレもなくなるかも...

細かいことはさておき, まずはいろいろと試してみよう!!

----
[1] 16.16. ctypes — Pythonのための外部関数ライブラリ — Python 3.6.5ドキュメント
[2] darknet yolo v3をpython3(.5.2)で試す
[3] qqwweee/keras-yolo3: A Keras implementation of YOLOv3 (Tensorflow backend)




画像認識 (機械学習プロフェッショナルシリーズ)

画像認識 (機械学習プロフェッショナルシリーズ)


画像処理アルゴリズム入門 (I・O BOOKS)

画像処理アルゴリズム入門 (I・O BOOKS)


Pythonで学ぶ実践画像・音声処理入門

Pythonで学ぶ実践画像・音声処理入門


増補改訂版 図解でわかる はじめてのデジタル画像処理

増補改訂版 図解でわかる はじめてのデジタル画像処理