MAiX BiTでダックを検出する予定だったけど無理だった

# 動機

某氏よりMAiX BiTを譲っていただいた。有効活用したい。
丸一日考えた結果、手元に大量にあるダックを検出することにした。

俺の環境

   + PC: Lenovo Legion y520 
   + OS: Windows 10
   + preinstall software
     + Teraterm
     + Git for Windows

# 結果

![muri.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/4fd71a4a-497e-dc10-34a5-c4c9bc25cc5c.png)

自分で作ったモデルを組み込む方法が分からない。
Sipeedが準備してくれてるモデルを使うのが関の山。

# 前準備

下記をインストールする

[公式サイト](https://www.python.org/downloads/windows/)からpython3.6.6ダウンロードしてインストール。
Windows10なので、python x86-64 executable installerを選ぶ。
インストールが終わったらコマンドプロンプトを起動してバージョンを見てみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/3029276d-e591-ea3f-4ec8-5453059e7f5c.png)


<font color="dark_pink">そりゃそうだって感じのスクショ</font>

で、必要となるパッケージを入れる。

```bash
pip --no-cache-dir install -I --upgrade pip setuptools wheel
pip --no-cache-dir install -I pyserial
pip --no-cache-dir install -I kflash
pip --no-cache-dir install -I tensorflow
pip --no-cache-dir install -I tensorflow_datasets
pip --no-cache-dir install -I keras
pip --no-cache-dir install -I matplotlib
pip --no-cache-dir install -I numpy
pip --no-cache-dir install -I h5py pyyaml
pip --no-cache-dir install -I pillow
```

<font color="dark_pink">間違いなくいらないコマンド入っているので、興味のある方は自分で調べてやってみてください。</font>

一応インストール後のパッケージ

<details><summary>pip freeze</summary><div>

```text
     + absl-py==0.8.0
     + astor==0.8.0
     + attrs==19.1.0
     + certifi==2019.9.11
     + chardet==3.0.4
     + cycler==0.10.0
     + dill==0.3.0
     + enum34==1.1.6
     + future==0.17.1
     + gast==0.3.2
     + google-pasta==0.1.7
     + googleapis-common-protos==1.6.0
     + grpcio==1.23.0
     + h5py==2.10.0
     + idna==2.8
     + Keras==2.2.5
     + Keras-Applications==1.0.8
     + Keras-Preprocessing==1.1.0
     + kflash==0.8.2
     + kiwisolver==1.1.0
     + Markdown==3.1.1
     + matplotlib==3.1.1
     + numpy==1.17.2
     + Pillow==6.1.0
     + promise==2.2.1
     + protobuf==3.9.1
     + psutil==5.6.3
     + pyelftools==0.25
     + pyparsing==2.4.2
     + pyserial==3.4
     + python-dateutil==2.8.0
     + PyYAML==5.1.2
     + requests==2.22.0
     + scipy==1.3.1
     + six==1.12.0
     + tensorboard==1.14.0
     + tensorflow==1.14.0
     + tensorflow-datasets==1.2.0
     + tensorflow-estimator==1.14.0
     + tensorflow-metadata==0.14.0
     + termcolor==1.1.0
     + tqdm==4.35.0
     + urllib3==1.25.3
     + Werkzeug==0.15.6
     + wrapt==1.11.2
```

</div></details>

任意のディレクトリにファーム書き込み用リポジトリをクローンする。

```bash
git clone https://github.com/sipeed/kflash.py
```

CH340ドライバのインストール。[ここ](https://www.arduined.eu/ch340-windows-8-driver-download/)から``CH340 driver for Windows 8.1 x64 & x86``をクリックして入れる。
インストールが終わったらMAiX BiTをPCにつなぐ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/e1993d7f-ae19-0f2c-b0f7-d809aa823daf.png)

<font color="dark_pink">よく分かんないけどポート2つ取られた</font>

まともに認識されてないので、下記をためす

 + [CH552 Driver?](http://wch.cn/download/WCHISPTool_Setup_exe.html)をインストールする
 + Arduino IDEインストールする(ドライバ用)
 + [FTDI2232 Driver](https://www.ftdichip.com/Drivers/VCP.htm)をインストールする

無事に認識されたらファームのアップデートとかHelloWorldとかやる。
以降の手順は[Sipeed M1 dock suit (Dan Dock) を買ってからサンプルの顔検出プログラムを動かすまで](https://qiita.com/Ke_N_551/items/55c6442a53ffc0072363)という素晴らしい記事を参考にしてほしい。

 + [Releases](https://github.com/sipeed/MaixPy/releases)のface_model_at_0x300000.kfpkgを選んだ。
 + `python kflash.py -p COM3 -b 115200 -B bit face_model_at_0x300000.kfpkg`を実行

で、`Getting fail.check Serial port (Attempting to use a port that is not open)`ってでた。

guiからチャレンジする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/1765376e-7f72-daf6-ff38-2db6cb20f5bb.png)

<font color="dark_pink">無事書き込めた模様</font>

無事書き込めたのでFaceDetectしてみる。

コードは[demo_find_face.py](https://github.com/sipeed/MaixPy_scripts/blob/master/machine_vision/demo_find_face.py)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/86a457f3-fa8e-af34-d536-e07224e77e56.png)


認識されなかったけどとりあえずpythonからカメラ周り実行を確認

# モデルを作成してMAiX Bit用に変換する

## 準備

[ココ](https://github.com/fchollet/deep-learning-models/releases)からsource codeをダウンロードして展開する。
keras配下のmobilenet.pyをいったん退避し、展開したsource code配下のmobilenet.pyで上書きする。

大事な事なのでもう一回書く。

`keras配下のmobilenet.pyをいったん退避`(<-忘れない気持ちが大事)
具体的に言うと下記ファイル。

 + "C:\Users\nmiya\AppData\Local\Programs\Python\Python36\Lib\site-packages\keras_applications\mobilenet.py"

検索するとなぜか3つほどmobilenet.pyがある。

その後、変換等で必要になるツールを落とす

```bash
git clone https://github.com/sipeed/Maix_Toolbox.git
```

## 学習させる

とりあえずダックの画像とか用意して学習させる。keras使うので前回やった[TensorFlowを使うだけ使う](https://qiita.com/miyatama/items/213305fb268e685e315c)を参考にガリガリ書く。
ただし、h5の保存までにする。

<details><summary>duck_detector.py</summary><div>

```python
import tensorflow as tf
import numpy as np 
from PIL import Image 
import glob 

folder = ["datasets/duck", "datasets/jojo"] 
X = [] 
Y = [] 

def img(x): 
  y = Image.open(x) 
  y = y.convert("RGB") 
  y = y.resize((128, 128)) 
  return np.asarray(y)  

for index, name in enumerate(folder): 
  dir = "./" + name 
  files = glob.glob( dir + "/*.jpg") 
  for i, file in enumerate(files): 
    image = img(file) 
    X.append(image) 
    Y.append(index) 

X = np.array(X) / 255 
Y = np.array(Y) 

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(128, 128, 3)),
  tf.keras.layers.Dense(512, activation=tf.nn.relu),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(2, activation=tf.nn.softmax)
])

model.compile(
  optimizer='adam',
  loss='sparse_categorical_crossentropy',
  metrics=['accuracy'])

model.fit(X, Y, epochs=5, batch_size=1)
model.save(
  'duck_detect.h5', 
  include_optimizer=False)
```

</div></details>

で、エラーが出るのでmobilenet.pyを戻して学習させる。
.h5ファイルが出来上がったらMaix_Toolbox内にコピーする

## h5 -> pb の変換(したかった)

まずはpbファイルを作る。

```bash
python keras_to_tensorflow.py --input_model duck_detect.h5  --output_model duck_detect.pb
```

エラーが出るのでどうにもならず。

もしpbファイルが出来たなら、謎のグラフ用ファイルを作る(予定)

```bash
./gen_pb_graph.py duck_detect.pb
```

## pb -> tflite の変換(したかった)

無事にpbファイルと謎のグラフ化が済んだならtfliteを作る(予定)

```bash
toco \
  --graph_def_file=duck_detect.pb \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --output_file=duck_detect.tflite \
  --inference_type=FLOAT \
  --input_type=FLOAT \
  --input_arrays=input_1 \
  --output_arrays=dense_1/Softmax \
  --input_shapes=1,128,128,3
```

## tfile -> kmodel の変換(したかった)

ここまで来たらあと一息。kmodelに変換する(予定)

```bash
./get_nncase.sh
cd ncc
tar fx ncc-linux-x86_64.tar.xz
cd ../
./tflite2kmodel.sh workdpace/duck_detect.tflite
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42445/0035679b-e105-6b47-cbbc-d8662b5172e5.png)

<font color="dark_pink">まぁ、shって書いてあったから何となくわかってた</font>

さて`thanks windows`の時間だ。とりあえずget_nncase.shの中身をみてみる。
どうやらディレクトリ切ってncc入れているだけっぽい。なので、

```bash
cd Maix_Toolbox
mkdir ncc
mkdir workspace
mkdir images
mkdir log
```

で、[ココ](https://github.com/kendryte/nncase/releases)からncc-win7-x86_64.zipを取得してnccディレクトリに展開。

tflite2kmodelの中身をみるとnccを呼び出しているだけっぽいので下記コマンドを実行する

```bash
.\ncc\ncc -i tflite -o k210model --dataset images duck_detect.tflite duck_detect.kmodel
```

# モデル込みのプログラムを焼く(焼きたかった)

とりあえずsdcardに書き込んで実行する(予定)
起動時に実行されるように変更する。(予定)

# 振り返り

環境回りの整備が全く進まない。特に学習回り。
sipeedが用意してくれているモデルを使って顔認識とか人認識とかするぐらいしかできない。
せめてチュートリアルに環境回りの情報書いてくれてたら少しはそれっぽいものができたかもしれない。
公式があってここまで消耗したのは久しぶり。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">keras_to_tensorflow.pyにてエラー発生。これチュートリアル通りできた奴いんのかな？<br><br>ValueError: Unknown initializer: GlorotUniform<a href="https://twitter.com/hashtag/MAiXBiT?src=hash&amp;ref_src=twsrc%5Etfw">#MAiXBiT</a></p>&mdash; みやた@代打中 (@miyata080825) <a href="https://twitter.com/miyata080825/status/1173133008477405184?ref_src=twsrc%5Etfw">September 15, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>