ＥＳＰ３２は深い学習の夢を見るか？[５](カメラ画像でリアルタイムDeepLearning)

#目的
　DeepLearningの定番では、まず画像ファイルを作成してバッチ(一括)でトレーニング、評価を行う。
　でもこれでは、結果が出てくるのに時間がかかりその場では判らない。
　持ち運ばないのだったら、パソコンでいいじゃん。ESP32の出番はないよね。
　ウェアブルでリアルタイムにその場で判断しなくっちゃ。
　◆◆◆　そうだ、カメラ画像でリアルタイムDeepLearningしてみよう　◆◆◆
　出来れば野望にまた一歩近づくぞ。


#経緯
　1. 「[前々々回](https://qiita.com/hi631/items/9e97ba582c2d7a6c2029)」と「[前回](https://qiita.com/hi631/items/d6573dbe5b8d30f4ed1b)」で、ESP32によるDeepLearningの初歩とカメラ画像処理は一応手に入れた。
　2. 次のステップとしてカメラ画像のリアルタイムDeepLearning(EVALUATION)を目指すことにした。
　3. 追試をやり易いようにMNISTデータを使う。※やる人がいるかどうかは疑問が残るが
　4. MNISTデータをNeuralNetworkConsoleによるDeepLearningにかけ、c_sourceを作成する。
　5. 前回のesp-nncとesp-camを結合してc_sourceをぶち込み、コンパイル可能になるまで煮詰める。
　6. ディスプレイ画面にMNIST画像を表示してカメラで読み取り、画像認識性能を確認。
　7. うーーーーむ、旨くいかない。出鱈目が表示される。
　8. カメラ画像の輝度と画像の定位位置に問題が有る様だ。
　9. 解決ソフトをでっち上げ、何とか認識出来ました。


#前提条件(前回と同様)
　以下のソフトを予め導入の事。
　1.neural_network_console　(当たり前、for Windows 8.1/10_64bit 1.4.0にて検証)
　2.ESP-IDF　　　　　　　　 (ESP32の開発環境)
　3.visualstudio(2017)　　　(自分好みにツールの変更を行いたい場合)

#ESP32へのカメラ接続
　「[前々々回](https://qiita.com/hi631/items/9e97ba582c2d7a6c2029)」と同様

追記 : TTGO-Cameraによる動作検証
　TTGO-Cameraを入手したので動かしてみた。(うまくいった)
　ピン配置が異なるので、sdkconfigを変更。
　※sdkconfig_TTとして追加アップしたので差し替えれば実行可能。sdkconfig_32sで元に戻せる。
　※spiffsの機能は使ってないが(ヘッダ類は存在)、spiffsにデータを格納しないとエラー停止するので格納要。

#neural_network_consoleでの操作
　「[前回](https://qiita.com/hi631/items/d6573dbe5b8d30f4ed1b)」と同様。


#ESP32によるEVALUATION
　ESP32のesp-idfでコンパイル可能な形で下記に格納している。
　　 [ESP32によるDeepLearningのEVALUATIONソフト] (https://github.com/hi631/esp32-nnc/tree/master/esp-nnc-cam)
　1. make cleanを実行後、make flash monitor を実行する。
　2. ディスプレイに下図のようなMNIST画像を拡大して表示する。
　3. 画像収集ソフトを起動し、画像読込を行う。※画像収集のタイミングで画像認識が行われる。
　　※単独で動かすのであれば、app_main.c内のapp_main()を弄る。
　4. ディスプレイ上の数値画像をカメラで撮影する。(例えば9)
　　※画像は外光の影響を避けた状態で、なるべく画面いっぱいに、カメラを傾けずに撮影するのがコツ。

![Image0-9a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159764/60b62b00-d40e-710d-f89e-d744adc596ea.jpeg)

　5. 下記のようにシリアルに表示され、( 9 )と認識されれば成功。(Good Luck)
　　※上記画像(0-9)を一通り認識できる事を確認している。

		Pos= -1 -3
		............................
		............................
		............................
		............................
		............................
		..........OOOOO.............
		........OOOOOOOO............
		.......OOOOOOOOOO...........
		......OOOO.....OO.OO........
		.....OOOO........OOOO.......
		.....OOO........OOOO........
		.....OOO.........OOO........
		.....OOO........OOOO........
		....OOOO........OOOO........
		.....OOO.......OOOO.........
		.....OOO.....OOOOOO.........
		.....OOOOOOOOOOOOOO.........
		......OOOOOOOOOOOO..........
		.......OOOOOOOOOOO..........
		..............OOOO..........
		..............OOOO..........
		.............OOOOO..........
		.............OOOO...........
		.............OOOO...........
		.............OOOO...........
		.............OOO............
		.............OOO............
		............................
		 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +0.000 +1.000 ( 9 )


#EVALUATION結果の評価
　当初失敗した原因と対策を次に示す。

　<カメラの輝度>
　MNIST画像では数値以外の部分は0.0となっているが、カメラ画像は画面の反射が含まれ0.0とはなってはいない。
　そこでカメラ画像に対する輝度補正の処理を追加した。
　1. 画面の反射の変化は画像の右左では異なるが直線的と想定し、左端と右端の数値を基準として測定した輝度から差っ引く。
　2. 差っ引いた事により、輝度の最大値が下がるのでその分の最大値を引き上げる。
　3. 輝度0付近にはゴミが多量に落ちているので、輝度が10%以下の場合0.0とする。

　<画像の位置>
　上記により一応認識するようにはなったが、認識範囲が極端に狭く、位置が少しずれると誤認識となる。
　そこで、画像を中心に移動する処理を追加した。
　1. 画像の重心を求める。
　2. 重心がディスプレイの中心に来るように画像を移動。
　　※実施例では Pos -1 -2 と表示されるが、撮影画像のセンターがずれていることを示している。
  　※もう少し移動可能範囲を大きくとれるようにすべきであった。

　本対応は、MNIST画像の周辺が黒いことを利用しており、一般的な解決策とはならない。
　今回は輝度、位置に対応したが、それ以外(大きさ、角度等)でも認識精度が悪化することが想定される。
<br>
　DeepLearningによる画像認識は万能ではなく、トレーニング画像に含まれないものは認識ない。(当たり前田のクラッカー)
　全てトレーニング画像に含めるか、画像の前処理を行っておかなければ精度は望めないだろう。
　MNIST画像でさえ、こんな小手先の手法が必要とは。(数字は写っているんだから認識してよねDeepLearning様なんてね)
　実画像を使用する場合、撮影条件を同一に出来ても、撮影方向、距離などをどうするか等、精度向上への課題はてんこ盛りだね。
　認識対象物へのハンドリングを妨げない範囲で、諸条件をうまく固定化しないと実用化は出来ないのではないのかな。

　次は我が家の家電製品たちの認識に迫る予定。はたしてうまく認識出来るのでしょうか..??。
　なお、もし追試する奇特な方がおられた場合、上記記載内容は無保証であり、各自の責任においてご利用願います。