AutoML VsionとTPUを用いて知識ゼロからEdge(Raspberry Pi)でゴミの画像認識


備忘録です
やり方について書いていきます
# 筆者について
某大学の修士１年
動画像符号化、電気回路、機械学習について勉強中
C, C++, JAVA, python, chainer, Ubuntuなどは触った事があるが
ラズパイ, GCP, API, Raspbianに関しては全くの無知識

# 環境
Ubuntu 18.04.2 LTS（ノーパ）（windowsでもOK）
Raspbian（Raspberry Pi 3 Model B+）
Coral accelerator EDGE TPU

# やること
ラズパイでUSBカメラ、TPUを用いてゴミの画像認識をリアルタイムで行う（本記事）
その結果を用いてハードウェア制御を行い自動判別できるゴミ箱を作成（本記事外）

# 参考
[Python, OpenCVで画像ファイルの読み込み、保存（imread, imwrite）](https://note.nkmk.me/python-opencv-imread-imwrite/)
[Raspberry PiをWindowsで操作する(SSH)](https://s2jp.com/2014/01/raspberry-pi-ssh/)
[Windows10標準のSSHクライアントを使ってみた](https://www.onebizlife.com/windows10-ssh-client-1980)
[AutoML Vision EdgeのカスタムモデルをCoral Edge TPUで試す](https://www.apps-gcp.com/automl-vision-edge/)
[AutoML Vision EdgeのカスタムモデルをCoral Edge TPUで試す](AutoML Vision EdgeのカスタムモデルをCoral Edge TPUで試す)
[機械学習の始め方！GoogleのAutoML Vision Edgeで簡単に入門](
https://misoji-engineer.com/archives/ml-start.html)
# 目次
### ラズパイの準備
1. OSを入れる
1. SSHの設定
1. ラズパイでAutoMLやるための準備
1. OpenCVのインストール
2. USBカメラをつなぐ準備

### データセットの作成
1. OpenCVのインストール
2. 写真とるプログラムを作成、実行
3. ZIPに圧縮

### ブラウザでやるAutoMLの準備
1. データセットの登録
2. トレーニング
3. モデルのダウンロード

### プログラムの作成
1. 写真を取るプログラム（関数）作成
2. 写真を元に画像認識するプログラム（関数）作成


# ラズパイの準備
### OSを入れる
[公式サイト](https://www.raspberrypi.org/downloads/)からOSをダウンロードしてSDカードに入れてラズパイに挿して起動すればOKです
ディレクトリを日本語から英語にするのが面倒な方は、最初から英語でOSインストールするのがオススメ
出来なければここらへんの記事が参考になるかも：[最近のRaspberry Piイメージ（Raspbian）をインストールするメモ](https://www.1ft-seabass.jp/memo/2018/07/23/raspbian-install-201807-memo/)
### SSH（遠隔接続的な）の設定
ラズパイでcrtl + alt + t でターミナルを起動
`sudo raspi-config`
コマンドを打ち込み開いた窓から
8 Advanced Options 
A4 SSH 
Enable
でSSHが有効になります

Ubuntuでcrtl + alt + t でターミナルを起動
ラズパイと同一wifiに繋いだ後に
`ssh pi@raspberrypi.local`で繋がります
初期パスワードは
`raspberry`です


`ssh [ipアドレス]`でも繋がります
ipアドレスはラズパイで`ip a`コマンドで見れます
wlan0のトコロをみて
`inet 192.168.195.212/24 brd 192.168.195.255 scope global noprefixroute wlan0`
などとあったら192.168.195.212がipアドレスです
なので`ssh 192.168.195.212`コマンドでOKですね
詳しくは[ifconfigが非推奨に!? ifconfigコマンドを使わずにRaspberry PiのIPアドレスを調べる方法](http://densikousaku.com/archives/861)

windowsでも[このように](https://www.onebizlife.com/windows10-ssh-client-1980)同様の事が出来ます


### ラズパイでAutoMLやるための準備
参考:[AutoML Vision EdgeのカスタムモデルをCoral Edge TPUで試す](https://www.apps-gcp.com/automl-vision-edge/)
モジュールのインポート

```
cd ~/
wget --no-check-certificate https://dl.google.com/coral/edgetpu_api/edgetpu_api_latest.tar.gz -O edgetpu_api.tar.gz --trust-server-names
tar xzf edgetpu_api.tar.gz
cd edgetpu_api
bash ./install.sh
```
`--no-check-certificate `は入れないと[エラー](https://blog.dreamhive.co.jp/mkoba/?p=5741)が出たので入れた。


# データセットの作成
### OpenCVのインストール
[ラズパイでpython3にopencvを入れたらエラーが出た【対処法】](https://qiita.com/XM03/items/48463fd910470b226f22)
 写真とるプログラムを作成、実行
ZIPに圧縮

# ブラウザでやるAutoMLの準備
### データセットの登録
 トレーニング
 モデルのダウンロード
※この手法は失敗しました。経緯について書きます。
なお、はじめから[ここの通り](https://cloud.google.com/storage/docs/gsutil_install?hl=ja)SDKを入れたら多分問題なくいけます。
ガイドに従い`1.Export your model to Google Cloud Storage. `したのち
`$ gsutil cp -r gs://dust2/dust_box_model/ ./download_dir`
を入力すると`Command 'gsutil' not found`と言われたので
`sudo apt  install gsutil`でインストールしてからリトライ←これがミス

``` 
gsutil cp -r gs://＊＊＊＊＊/ ./download_dir
No command was given.

Choose one of -b, -d, -e, or -r to do something.
Try `/usr/bin/gsutil --help' for more information.
```
と言われてしまう。
Q.ちゃんと`-r`optionを付けてるのにエラー？？？
A.googleのとは別の`gsutil`をインストールしているらしい
[ここから](https://cloud.google.com/storage/docs/gsutil_install?hl=ja)からダウンロードしよう
この通りやれば多分いけます

####なんかうまく出来ないのでラズパイから再チャレンジ
まずタイムゾーンがずれていると弾かれるので
`sudo date -s '11/04 20:10 2019'`
で時刻の設定
python のversionは2系だったのでそのまま
`curl https://sdk.cloud.google.com | bash`
↑このコマンドは私の環境だとよく403エラーになるけど諦めず何回か実行したら4回目で行けた。

```
 $ exec -l $SHELL
 $ which gcloud
 $ gcloud init
```
SSH接続だとブラウザが開けないからかうまく出来なかったのでラズパイで直接実行した。
ちなみに@はShift+2で入力になってた。

[Google cloud SDK](https://cloud.google.com/storage/docs/gsutil_install?hl=ja#deb)をインポートします

```
#環境変数の設定
export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"

#cloud SDKのURLを追加
echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list

#公開鍵をインポート
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

#SDKを更新してインストール
#ダウンロードエラーが出ることが多々あるので --fix-missing　を追加しています
sudo apt-get update && sudo apt-get install google-cloud-sdk --fix-missing

#ついでにpythonのコンポーネントをインストール
sudo apt-get install google-cloud-sdk-app-engine-python

#開始コマンド
gcloud init
```

この後Visionの
`$ gsutil cp -r gs://****/*****/your_model/ ./download_dir`
からmodelのとこの/を一つ除いて←ココ重要
`$ gsutil cp -r gs://****/*****/your_model ./download_dir`
でダウンロード出来ました。
1行のコマンドにこんなに苦労するとは。。。。


# TPUを動かす
TPUを動かすためのプログラムをダウンロード
git clone https://github.com/google-coral/tflite.git

tflite_runtimeが無いと言われたのでインストール
[ここ](https://dl.google.com/coral/python/tflite_runtime-1.14.0-cp37-cp37m-linux_x86_64.whl)からファイルをダウンロード
リンクが怪しいと思った方は正しいです。そういう方は[ソース](https://www.tensorflow.org/lite/guide/python)からどうぞ
このファイルのあるディレクトリで
`pip3 install tflite_runtime-1.14.0-cp37-cp37m-linux_armv7l.whl`
コマンドでインストールできます

その後
`python3 classify_image.py --m edgetpu_model.tflite --l dict.txt --i images.jpeg`
で実行可能
それぞれのファイルは自分のファイルパスに合わせてください



# プログラムの作成
### 写真を取るプログラム（関数）作成
### 写真を元に画像認識するプログラム（関数）作成
`classify_image.py`に以下の関数を追加
コマンドライン引数を普通の引数に変更したのですが，もっと良いやり方あれば教えてください

```
def get_label(labels = "dict.txt",model = "edgetpu_model.tflite",input_i = "images.jpeg",count =5,threshold = 0.0,top_k =1):

  labels = load_labels(labels) if labels else {}

  interpreter = make_interpreter(model)
  interpreter.allocate_tensors()

  size = classify.input_size(interpreter)
  image = Image.open(input_i).convert('RGB').resize(size, Image.ANTIALIAS)
  classify.set_input(interpreter, image)

  for _ in range(count):
    start = time.monotonic()
    interpreter.invoke()
    inference_time = time.monotonic() - start
    classes = classify.get_output(interpreter, top_k, threshold)

  for klass in classes:

    label = (labels.get(klass.id, klass.id))
    score = klass.score

    return label,score
```
そうすると以下のようにimportして実行する事でラベルと信頼度を得る事が出来ます。

```
import classify_image as clfi

if __name__ == '__main__':

	labels ="dict.txt"
	model = "edgetpu_model.tflite"
	input_i ="images.jpeg"
	label ,score = clfi.get_label(labels =labels,model = model , input_i =input_i)
	print(label)
	print(score)
```
こんな感じで結果が取れます

```
INFO: Initialized TensorFlow Lite runtime.
burnable
0.703125
```
とりあえず各ラベル30データくらいで学習して，
ネットから拾った燃えるゴミでテストしてみたのですが，意外といけてますね。
まあ精度としてまだコメント出来るレベルではないですが・・・
ゴミをストック中なのでデータが増えたらちゃんとやってみたいと思います。

結局ラズパイで画面表示して開発を行ってるので発熱がすごい

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391105/1202158d-dd45-b16a-3c4a-86829077dac9.jpeg" width=50%>