Posted at

YOLO V3に、VoTTでアノテーションを付けた独自のデータセットを学習させる

YOLO V3を試すだけであれば学習済みモデルを使えばよいのですが、「やっぱり独自の物体検出をやってみたい!」ということで、独自のデータセットを学習させてみました。その内容を紹介します。

今回はグーの手を検出するだけのモデルを作成することとし、自分のグーの手を撮影し、その動画にVoTTでアノテーションを付けて学習データにしました。

yologu1.jpg


私が実行した環境


  • Windows 10 Home

  • NVIDIA GTX1080Ti

  • CUDA 9.1.85.3

  • CuDNN 7.1.3

  • Python 3.6.5

  • Tensorflow-gpu 1.12.0

  • Keras 2.2.4

  • opencv-python 4.0.0.21

  • matplotlib 3.0.2

  • Pillow 5.4.1

  • VoTT 1.7.2


まずはYOLO V3を動かす

以下のPythonライブラリをインストール

tensorflow、keras、opencv-python、matplotlib、pillow

Yolo V3のソース一式をダウンロードし、任意のパスに配置

https://github.com/qqwweee/keras-yolo3

学習済みモデルをダウンロードし、"keras-yolo3"フォルダに配置

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

weightsをkeras用に変換

python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5


YOLOの実行(静止画)

python yolo_video.py --image

"Input image filename:"と聞かれたらファイル名を入力します。


YOLOの実行(動画)

python yolo_video.py --input hoge.mp4

上記でYOLOが動くことを確認できたら、安心して独自データセットの収集に取り組みます。


データの収集

今回は自分のグーの手をあらゆる角度からただひたすら動画撮影します。

後で1秒毎にアノテーションを付けるので、500枚ほどの学習データを集める想定で10分ほどiPhoneの前でグーの手をグリグリ動かします。


データにアノテーションを付ける

十分な動画が撮れたらアノテーションを付けていきます。

マイクロソフトが公開しているVoTTというアノテーションツールだと、動画へのアノテーションが楽ちんです。

VoTTをダウンロードしてインストールします。

https://github.com/Microsoft/VoTT/releases

VoTTはmp4、oggの動画ファイルに対応しています。

今回はiPhoneで撮影した動画を使ったのでffmpegでmov形式からmp4形式に変換しました。

また、私の環境ではFullHDだと学習中にメモリ不足でエラーが発生したので解像度を下げました。

ffmpeg -i hoge.mov -s 416x234 hoge.mp4

あとはVoTTでこの動画ファイルを読み込んで黙々とアノテーションをつけていきます。

途中で「こんな同じ様な画像ばっかりで意味があるのか…」という考えがよぎりましたが、それほど大変でもないので最後までやりきりました。

一通りアノテーションを付け終えたらExport Tagsを選択し、"Tensorflow Pascal VOC"形式でExportします。

vott.jpg


アノテーションをYOLO V3形式にする

YOLO V3のソースに付属している"voc_annotation.py"を使い、VOC形式のアノテーションをYOLO V3で学習する形式に変換します。


voc_annotation.pyの処理に合わせたファイル構成にする

"keras-yolo3"フォルダに"VOCDevkit"というフォルダを作成します。

VoTTからExportした"hoge_output"フォルダの名称を"VOC2007"に変更し、先の"VOCDevkit"フォルダ内に移動します。

"keras-yolo3/VOCDevkit/VOC2007/ImageSets/Main"フォルダに"train.txt"を作成します。

テキストファイルには"keras-yolo3/VOCDevkit/VOC2007/JPEGImages"フォルダ内の全jpgファイルを拡張子なしで列挙します。


このような感じ

hoge_frame_1

hoge_frame_2
...

"train.txt"をコピーして"test.txt"、"val.txt"を作成します。

学習用と評価用などでデータを振り分ける場合は振り分けておいても構いません。


voc_annotation.pyの処理を修正する

VoTTで出力したファイルには、アノテーション位置がfloatで書かれています。そのままでは"voc_annotation.py"で読み込めないので、下記のようにfloatからintに変換するようにソースを修正します。


voc_annotation.py,21行目あたり

        b = (int(float(xmlbox.find('xmin').text)),

int(float(xmlbox.find('ymin').text)),
int(float(xmlbox.find('xmax').text)),
int(float(xmlbox.find('ymax').text)))

また、6行目あたりのclassesのリストも自分で学習させる内容に合わせて修正します。今回は1クラスなのでclasses = ["gu"]としておきました。


voc_annotation.pyで変換する

あとは"voc_annotation.py"を実行して変換します。

python voc_annotation.py

出力された"2007_train.txt"がYOLO V3用のアノテーションの形式です。


このような形式

~\keras-yolo3/VOCdevkit/VOC2007/JPEGImages/hoge_frame_1.jpg 100,200,250,300,0

~\keras-yolo3/VOCdevkit/VOC2007/JPEGImages/hoge_frame_2.jpg 200,100,300,400,0
...


学習


独自のクラスの列挙

"keras-yolo3\model_data"フォルダに"my_classes.txt"を作成し、自分で学習させるクラスを列挙します。

今回はguとだけ記載しました。


train.pyの修正

"train.py"が"2007_train.txt"、"my_classes.txt"を読み込むように修正します。

17行目の"annotation_path"に"2007_train.txt"を指定します。

19行目の"classes_path"に"model_data/my_classes.txt"を指定します。

また、私の環境ではデフォルトのbatch_sizeだと学習中にメモリ不足でエラーが発生したので減らしました。

57行目と76行目の"batch_size"を32から8にしています。


学習用にweightsをコンバート

学習用にweightsをコンバートします。

python convert.py -w yolov3.cfg yolov3.weights model_data/yolo_weights.h5


学習の実行

python train.py

学習済みモデルは"\keras-yolo3\logs\000\trained_weights_final.h5"として生成されます。


学習済みモデルで物体検出

学習済みモデル、クラスを指定して起動します。


YOLOの実行(静止画)

python yolo_video.py --model logs/000/trained_weights_final.h5 --classes model_data/my_classes.txt --image


YOLOの実行(動画)

python yolo_video.py --model logs/000/trained_weights_final.h5 --classes model_data/my_classes.txt --input hoge.mp4

学習に用いたのは自分のグーだけでしたが、うちの子のグーも検出できました。

yologu2.jpg

顔でもグーと検出される時もありましたが…