YOLOを用いて物体検出を行うモデルを3時間で作る方法

#YOLOを用いて物体検出を行うモデルを３時間で作る方法を教えます。
めちゃめちゃ雑な内容になっていますが、超簡単に物体検出を行う方法を紹介します。
## 今回作成するにあたって用いたツール
- labelImg
- YOLO
- GoogleColabratory
- Googledrive(Googleアカウント必須)

## 参考にした記事（本当に感謝）
- YOLOオリジナルデータの学習 http://takesan.hatenablog.com/entry/2018/08/16/013452
- Google Colaboratory上でYOLOv3のオリジナルデータ学習 https://qiita.com/emi-cd/items/60e8fe877dbedb2cfae7
- Google Colab上でdarknet（YOLO）を使って物体を数える【画像認識】 https://wakuphas.hatenablog.com/entry/2018/09/19/025941

## モデルの作り方
そもそものYOLOとは？物体検出とは？などといった質問に関する回答は上記事などを参考にしてください。
この記事も作成における３時間の中に含んでいるのでところどころ端折っている場所もありますがご容赦を。

### ①教師データを用意し、labelImgでアノテーション作業を行う
簡易的な教師データを用意します。自分の場合は今回ビニールハウスの検出を行なってみたかったので、とりあえず画像を30枚用意。こんな感じ。Googleマップの航空写真めちゃ綺麗ですよね![スクリーンショット 2019-12-20 20.37.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285361/aa7b62c1-f85c-4b13-b543-35e0fe032768.png)

それに対しアノテーション作業（ラベルづけ）を行なっていきます。
今回使用したのはlabelImgというツール。他にもVoTTというツールや、BBox-Label-Toolというものがあるのですが、VoTTはYOLOに対応しているものの、うまくいかないとやり直しが大変、BBoxの方は複数クラスを作ろうとすると設定が面倒ということでlabelImgを採用しました。

以下コマンドを実行し、labelImgが使える状態にします。Python3をインストール済みであれば3.4行目はスルーして良いです。

git clone https://github.com/tzutalin/labelImg.git
sudo apt install pyqt5-dev-tools
sudo apt install python3-pip
sudo pip3 install lxml
cd labelImg
make qt5py3

labelimgのフォルダの中に好きな名前でフォルダを作成し、そこに用意した画像を移動します。（ビニールハウスならvinylなど）
次にlabelimg/data の中にあるpredefined_class.txtを修正します。最初は20クラスぐらいあらかじめ書き込んでありますが、今回は既に書き込んであるクラス名を全部消し、自分の好きな名称でクラス名を改行して書き込みます。vinylと一行書き込みました。

python3 labelimg.py
によってlabelImgを実行します。
内部作業に関してはカット。ざっというと、
1. 利用するディレクトリを開く
2. Change Save Dir でラベルの座標情報を記したテキストファイルを指定する（labelimgフォルダ内にvinyl_txtといったフォルダを作った）
3. Saveの下にあるPascalVOCをクリックしYOLOに変更
4.あとはD -> 対象物をマウスをドラッグしてして囲む -> w押してラベル位置の確定 -> Saveを押して保存 -> D押して次の画像...

といった感じでラベル付けをしていきます。30枚なら一瞬です。これで教師データ準備完了。

### ②学習に向けた下準備

学習に向けた下準備を行なっていきます。
YOLOの利用にあたって、darknetというフレームワークをインストールします。このフレームワークはYOLOとかなり相性が良いです。（というより確かYOLOの開発者が使っている？）
以下コマンドよりインストールします。

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

次に、labelImgで使用した画像をdarknet/data/imagesに、labelImgで作成したテキストファイルをdarknet/data/labelsに移動します。その状態で/darknet にて
python3 process.py
を実行します。これにより教師データが教師ファイルと学習用ファイルに分けられます。

ここから様々な作業を行います。列挙します。
・ /darknet/data/images/obj.names を作成し、判別させたいラベルの名称を記入(vinyl)
・ /darknet/data/images/obj.list にも同様の作業を
・ /darknet/cfg/yolo-obj.cfg の244行目のclassesを上と同様1に、237行目のfiltersを（classes + coord + 1）*5 に当たる数値に。今回の場合30です。
・ /darknet/cfg/yolo-obj.cfg の20行目にあるmax_batchesが実際に学習する回数になります。理想はclasses * 2000なので今回の場合2000とします。

/darknet/cfg/yolo-obj.cfgがない場合、/darknet/cfg/yolov2-voc.cfgをコピーして編集します。
3行目：batch=64 にする。学習ステップごとに使う画像の枚数。コメントアウトして6行目をオンにするでもOK
4行目：subdivisions=8 にする。バッチが8で除算される。コメントアウトして7行目をオンにするでもOK


最後に、/darknet/cfg/obj.dataを以下のように変更します。
classes=1 
train = data/images/train.txt 
valid = data/images/test.txt 
labels = data/images/obj.names 
backup = backup/

https://pjreddie.com/media/files/darknet19_448.conv.23
をダウンロードすることで下準備完了です。

### ③GoogleColabratoryを用いて学習開始

いよいよ学習です。今の状態で
 ./darknet detector train cfg/obj.data cfg/yolo-obj.cfg darknet19_448.conv.23
として学習を初めてもいいのですが、CPUだとありえないくらい時間がかかって絶望します。よってここではGoogleColaboratoryを用いてGPUによって学習を行います。

GoogleColaboratoryはGPUを無料で使うことができるツールであり、ディープラーニングを行うためのツールが基本的に完備されているため非常に優しい。AI初学者は絶対に使うべき。（オープンソースなのでどうしても公開できない情報などを利用しない場合に限る。）

先ほどまで作業していたdarknetフォルダをdriveにアップロードします。
その後は以下からGoogleColaboraoryに関するファイルを保存し、.ipynbに書いてあるようことを実行していってください。
git clone https://github.com/foifoi1201/yolo.git

自分の投稿が正しければ、これにてモデル作成が完了すると思います。あとはダウンロードした.weightsをベースに
./darknet detect cfg/obj.cfg obj_final.weights data/***.jpg
を実行すれば検出ができると思います。

## 結果！
３時間以内に30枚の教師データで物体検出モデルを作成しようとすると、結果このような形になります。

![スクリーンショット 2019-12-21 2.42.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285361/bf4057e6-71d5-d372-7213-75ef8c87e12d.png)

まあまあ確認できてるやん。。。

YOLOを用いた物体検出は作成までが非常に面倒で、実際この通りにやったらすべてうまくできる訳でもないかもしれません。それにGoogleColabratoryも常にアップデートされ続けているので時間が経つと同じ作成方法が通用しない、なんてこともありえます。（実際今回もアップデートがなされていたようで、予想以上に作成に手間取りました。参考文献に多大なる感謝、、、、、、、）

自分と同じAI初学者に少しでも参考になれば幸いです。