YOLOで物体検出&分類 お試し

今回は比較的お手軽にできる物体検知&分類ができる深層学習YOLOを試してみました。OpenCVでも検出はいろいろ出来ますが、分類(検出した物体が人とかクルマとか分類)まで必要となるとやっぱり深層学習が必要になりますよね。

実際に推論を実施する際は 「darknet」 コマンドを使うわけですが、dartnet はオープンソース深層学習フレームワークで、その環境でyoloというアルゴリズムを実行するという感じでしょうか。

darknetコマンドとか実行しちゃって大丈夫なの?とちょっと不安にさせますが、ご自身の責任ということで。。情シス部要員として働いた経験からするともうちょっと普通?でかっこいい名前にしてもらわないと使用許可とか出しにくそうですね。。

OS環境はUbuntu18.04です。オフィシャルガイドに従い、問題なくインストールできるかと思います。CUDA環境ではありません。Windowsの場合はちょっと難しそうですね。

公式インストールはこちらですね。

https://pjreddie.com/darknet/install/

https://github.com/pjreddie/darknet

darknetコマンドをおきたい場所で以下のコマンド3行を実施するだけですね。gitコマンドは事前インストールですね。makeでコンパイルしますが、私の環境では30秒くらいで無事コンパイル終了しますね。

git clone https://github.com/pjreddie/darknet.git
cd darknet
make

コンパイルが終わりましたら以下のコマンドでYOLOの実行ですね。同じフォルダで実行します。

./darknet

出力はこんなになればインストールはOKですね。

usage: ./darknet <function>

事前学習済み重みファイルダウンロード&物体検出・分類

で次は事前学習済みファイルがダウンロードできるようにしてくれてますので、ダウンロードして使ってみます。

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

wgetで重み取ってきます。

wget https://pjreddie.com/media/files/yolov3.weights

サンプル画像があるので、そちらに対して物体検出&分類実行です。

./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg

実行終わると同じフォルダ内にpredictions.jpg というファイルが作成されてますので、そちらを開いてdog,bicycle,truckが検出されているのを確認するのが手順ですね。

検出した物体の座標と確信度をPythonでとってくる。

このままですと画像の切り出しもできないし、推論の確信度もわからなので、応用できませんので、pythonで取ってきてみます。

darknet/pythonフォルダ内にdarknet.py なるそれっぽいファイルがありますので、これを変更してみます。python3ではそのままでは動きませんので、若干変更が必要ですね。

まず「libdarknet.so」を読み位置を絶対パスに変更です。ご自身の環境に応じて変更ください。

#darknet.py

#lib = CDLL("/home/pjreddie/documents/darknet/libdarknet.so", RTLD_GLOBAL)
#lib = CDLL("libdarknet.so", RTLD_GLOBAL)
lib = CDLL("/home/XXX/darknet/libdarknet.so", RTLD_GLOBAL)

でmain関数は以下のように変更です。使用する設定ファイル、重みファイルを指定です。結果は[クラス名、確信度、バウンティボックスタプル]のリストがさらにリスト化して帰ってきますね。文字列の部分をbyte列にしてやる必要があるようです。”b”を文字列の先頭につける、でもOKでした。

#darknet.py

if __name__ == "__main__":
    net = load_net("cfg/yolov3.cfg".encode('ascii'),"yolov3.weights".encode('ascii'), 0)
    meta = load_meta("cfg/coco.data".encode('ascii'))
    r = detect(net, meta, "data/dog.jpg".encode('ascii'))
    for kekka in r:
        print('class_name=',kekka[0].decode('ascii'))
        print('confidence=',kekka[1])    
        print('box=',kekka[2])   

実行するフォルダの場所に注意して以下のコマンドで実行してみます。

python3 python/darknet.py

結果

class_name= dog
confidence= 0.999338686466217
box= (224.18377685546875, 378.4237060546875, 178.60214233398438, 328.1665954589844)
class_name= bicycle
confidence= 0.9933530688285828
box= (344.39508056640625, 286.08282470703125, 489.40667724609375, 323.8568420410156)
class_name= truck
confidence= 0.9153000116348267
box= (580.7305908203125, 125.11731719970703, 208.38641357421875, 87.00074768066406)

バウンティボックスの座標は(ボックス中心座標X,ボックス中心座標Y、ボックス幅Width、ボックス高さHeight)で戻ってきてますね。