ncnnのオブジェクト認識の学習モデル(YoloV2)を作成する

## 概要 
M5StickV2 で使える深層学習フレームワークのncnnの学習モデル作リ方について説明します。ncnnの学習データトレーニングは、Pytorchなどの深層学習フレームワークで学習したモデルを変換することで作成します。

ここで説明するプロセスでは、
Pytorchトレーニング→(変換)→onnxモデル→(変換)→ncnnモデル
という流れとなります。


dianjixz氏がGitHubで公開しているv831_yoloのコードを使います。
v831_yoloは、yoloc2という深層学習のモデルを元にして、ncnnのオブジェクト認識の学習モデルを作成することができます。


## PC環境
構築手順に入る前に、まずPCに以下のバージョンのUbuntuをインストールした環境で、構築しました。

[M5UnitV2のクロスコンパイル環境を構築する手順](https://qiita.com/nnn112358/pbulic/9e15450265b689300216)

```
Ubuntu 22.04.3 LTS(x64)
OpenCV ver 0.4.4
ncnn ver 231027
```

### 注意
この学習モデルを作るプログラムは、メモリを18GB以上搭載してないとエラーで終了します。


## Minicondaのインストール

まず最初に、Minicondaをインストールして、Pythonの環境を作ります。
Minicondaのインストーラは、Minicondaのウェブサイトからダウンロードして取得します。


```
% wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
% sh Miniconda3-latest-Linux-x86_64.sh
```

Miniconda上で、pythonの仮想環境を作成します。

```
% conda create -n _unitv2 python=3.8
```

condaをアクティブ化します。condaのアクティブ化する作業は、シェル立ち上げるごとに必要です。
次に、Pytorchをインストールします。

```
$ conda activate _unitv2
$ conda install pytorch torchvision torchaudio cpuonly -c pytorch
$ conda install opencv onnx
$ pip install pycocotools torchsummary
```

https://pytorch.org/get-started/locally/


## v831_yoloのダウンロード

GitHubからv831_yoloのコードをダウンロードします。
v831_yoloは、M5UnitV2のために作成されたリポジトリではなく、Allwinner　v831というCPUを搭載しているSipeed社のMAixⅡのための学習モデルさくせいのためのリポジトリです。
MAixⅡは、MaixPy3という開発環境が用意されているのですが、MaixPy3はM5UnitV2と同じく、ncnnの学習モデルを使った画像処理を行うことができます。今回は、v831_restnet18を使って、ncnnの学習モデルを作成します。

```
% git clone https://github.com/dianjixz/v831_yolo --recursive
% cd v831_yolo/
```

## 画像検出

画像検出に使用される主なモデルはYOLOv2で、pytorchアーキテクチャで学習され、onnx形式を介して、ncnnの形式にモデル変換します。

### データセットの準備  

YOLOv2は、デフォルトでvoc形式のデータセットを使用します。

# オブジェクト認識の学習モデル作成 

## 画像検出

画像検出に使用される学習モデルはYOLOv2です。pytorchで学習を行い、トレーニング終了後にネットワークモデルを変換して、ncnnモデルを作成します。 

### データセットの準備  

データセットを以下のフォルダ構造になるように準備します。  
YOLOv2は、デフォルトでvoc形式のデータセットを使用します。

~~~ bash
#YOLOのトレーニングデータセットをvocフォーマットで用意する。
├── custom #データフォルダ名
├── Annotations #アノテーションファイル
│ ├── ImageSets #トレーニングパラメータ
│ └── main
│ ├── train.txt #トレーニングに使用する画像の名前リスト
│ ├── val.txt #証に使用する画像の名前リスト
├──JPEGImages #トレーニング画像
~~~

train.txtとval.txtの各行はデータ（画像）名であり、パスは`JPEGImages`からの相対パスです。


### 設定の変更

data/custom.py の `CUSTOM_CLASSES` 変数を正しい `labels` に変更します。

``` data/custom.py
custom_classes = [
    "mouse", "sipeed_logo"
]
```


### トレーニング

CPUでのトレーニングコマンドは以下です。トレーニングを開始します。

```bash
python train.py -d custom  -v slim_yolo_v2 -hr -ms 
```

GPUでのトレーニングコマンドは以下です。ト

```bash
python train.py -d custom --cuda -v slim_yolo_v2 -hr -ms 
```

トレーニングが完了すると、トレーニング中に保存されたパラメータが weights/custom/slim_yolo_v2 ディレクトリに生成されます。

```
$ ls weights/custom/slim_yolo_v2 
slim_yolo_v2_10.pth   slim_yolo_v2_180.pth  slim_yolo_v2_260.pth
slim_yolo_v2_100.pth  slim_yolo_v2_190.pth  slim_yolo_v2_30.pth
slim_yolo_v2_110.pth  slim_yolo_v2_20.pth   slim_yolo_v2_40.pth
slim_yolo_v2_120.pth  slim_yolo_v2_200.pth  slim_yolo_v2_50.pth
slim_yolo_v2_130.pth  slim_yolo_v2_210.pth  slim_yolo_v2_60.pth
slim_yolo_v2_140.pth  slim_yolo_v2_220.pth  slim_yolo_v2_70.pth
slim_yolo_v2_150.pth  slim_yolo_v2_230.pth  slim_yolo_v2_80.pth
slim_yolo_v2_160.pth  slim_yolo_v2_240.pth  slim_yolo_v2_90.pth
slim_yolo_v2_170.pth  slim_yolo_v2_250.pth
```

## モデルのテスト・エクスポート

モデルのテストとncnn形式へのエクスポートを行います。
export modelコマンドを実行すると、outディレクトリにテスト画像とモデルファイルが生成されます。

```bash
python test.py -d custom -v slim_yolo_v2 --trained_model weights/custom/slim_yolo_v2/slim_yolo_v2_260.pth --visual_threshold 0.3 -size 224 --export

 -d custom カスタムデータセットのフォルダ名
 -v slim_yolo_v2 検出モデル:slim_yolo_v2を利用する。 
 --trained_model weights/custom/slim_yolo_v2/slim_yolo_v2_260.pth 260 回目に学習したモデルのパラメータを利用する（ファイル名で変更可能）
 --visual_threshold 0.3 検出しきい値を0.3に設定。 
 --size 224 画像サイズを224 X 224。 
 --export 画像をテストした後、oxnnモデルをエクスポートする（このオプションがない場合、手動でpytorchモデルをoxnnモデルに変換する必要があります） 
```

outフォルダの中で、onnxの学習モデルファイル"yolov2.onnx"とncnnの学習モデルファイル"yolov2.bin"と"yolov2.param"が作成できれいれば学習モデルの作成が終了です。

```
$ ls out/
test  yolov2.bin  yolov2.onnx  yolov2.param
```


## 参考情報

この記事を作成するにあたり、以下のウェブサートを参考にしました。

[dianjixz/v831_yolo](https://github.com/dianjixz/v831_yolo)