busyoucowのアイコン画像
busyoucow 2022年09月26日作成 (2022年09月26日更新) © CC BY 4+
製作品 製作品 閲覧数 787
busyoucow 2022年09月26日作成 (2022年09月26日更新) © CC BY 4+ 製作品 製作品 閲覧数 787

NumTone

NumTone

NumTone ~とりあえずAI使ってみよう!~

spresense、かっこいいですよね。
マイコンボード上で動くAI(エッジAI)を使って何かしたい!
そう思って使い方調べてみても、動画見ているだけで頭がクラクラ…
そう感じている人は、少なくないはずです!

ちょいとお試しで、手っ取り早く何か作ってみよう!
そんな人のための記事です。
AIを使って、演奏してみましょう!

必要なもの

  • spresenseメイン基板
  • spresenseカメラボード
  • spresense拡張ボード(公式)
  • googleアカウント か Sony ID
  • 小さめのスピーカ(開発中はヘッドフォンの方がよい)
  • i5第四世代以上のCPUを搭載したWindowsパソコン(GPUがついているとよい)
  • 日本国内にてインターネットが使える環境
  • MicroUSB to USBケーブル
  • MicroSDメモリーカード(4Gバイト以上を推奨)
  • メモ用紙10枚と筆記用具

それでは作ってみましょう!

〇spresenseを組み立て、カメラボードと拡張ボードがちゃんと接続されているか確認する

まず、こちらを参考にしてArduinoIDEをインストールしてspresense用の開発環境を整えます
 LEDを光らせるところまで行ってください
  https://developer.sony.com/develop/spresense/docs/arduino_set_up_ja.html
 スピーカかヘッドフォンも接続してしまいましょう
キャプションを入力できます

次にこちらを参考にしてMicroUSBケーブルをメインボードに接続し、拡張ボードが実際に接続されているか動作確認をします
 リチウムポリマーバッテリーのところは行わなくてよいです
  https://deviceplus.jp/mc-general/spresense-02/

更にカメラボードが実際に接続されているか動作確認をします。
 ボタンを押して操作する以降のところは行わなくてよいです
  https://deviceplus.jp/mc-general/spresense-05/

ここまできて何故、動作確認を行うのか疑問に思う方も多いと思います
 他のマイコン入門デバイスと違って、spresennseはメインボードに何か接続した際きちんと繋がった感が薄いのです
 差し込んでも接続されていないケースが多いため、手っ取り早く動作するもので確認をしないと
 動作しなかった際何処に不具合があるのかわからなくなることが多いのです
 面倒くさがらず、一歩一歩確認しながら行ってください

〇NeuralNetworkConsolを「インストール」する

ここからNeuralNetworkConsol Windows版(アプリ)をダウンロードしてインストールしてください
  https://dl.sony.com/ja/app/
 インストール方法はこちらを参考にしてください
  https://www.mgo-tec.com/blog-entry-nnc-introduction.html
 インストールにはGoogleアカウントかSony IDが必要ですが、日本国内であれば2022年9月現在無料で使えます
 クラウド版は従量課金であり無料枠が少ないため、試しに使う用途には推奨しません
 Windows版(アプリ)はインストールしたパソコン自体で機械学習を行い学習済みモデルを作成します

機械学習には比較的マシンパワーを必要とするため、できればGPUを搭載したパソコンで行うことを推奨します
 ゲーミングPCなどがお勧めです。ビジネス向けパソコンでも動作はしますが時間がかかります
 学習済みモデルを一度作成すれば、あとはそれをspresenseに組み込んで単体にて動作します

〇サンプルプロジェクトで学習済みモデルファイルを生成する

ここの手書き文字MNISTデータセットをダウンロードする以降を行ってください
https://www.mgo-tec.com/blog-entry-nnc-introduction.html

もしくは、ここからtutorial.image_classification.digitsをダウンロードし
NeuralNetworkConsole Windows版でダウンロードしたファイルdigits.sdcprojをプロジェクトで開くで開いてください
https://dl.sony.com/ja/project/
この場合、次の画面になります
キャプションを入力できます
digits.sdcprojをクリックすると、次の画面になります
キャプションを入力できます
右上のデータセットをクリックします
キャプションを入力できます
左のTrainingをクリックし、右上のデータセットから下のアイコンをクリックするとデータセットを開くことができます
キャプションを入力できます
右に一覧が出るのでmnist_training.csvをクリックします。
キャプションを入力できます
この画面が出るとトレーニング用のデータセットをセットされます
次にValidationをクリックします
キャプションを入力できます
右に一覧が出るのでmnist_test.csvをクリックします
左上の学習をクリックして右上の学習を確認して実行をクリックすると、機械学習が始まります
ここは結構時間がかかり、RTX2060というGPUを使用して20分弱でした
キャプションを入力できます
終了したら、右上の評価を確認して実行をクリックします
キャプションを入力できます
終了したら、左上の結果を右クリックして、エクスポート→NNBを選択します
キャプションを入力できます
model.nnbという学習済みファイルが生成されるので、これをnumtone.nnbにリネームして
MicroSDカードの直下(ディレクトリに入れない)にコピーし、spresense拡張ボードに差し込みます。
キャプションを入力できます

〇spresense上で動作させる

こちらのコードをspresense上にて実行してください

Numtone本体

#include <Camera.h> #include <SPI.h> #include <EEPROM.h> #include <SDHCI.h> #include <NetPBM.h> #include <DNNRT.h> #include <Audio.h> AudioClass *theAudio; SDClass SD; #define DNN_IMG_W 28 #define DNN_IMG_H 28 #define CAM_IMG_W 320 #define CAM_IMG_H 240 #define CAM_CLIP_X 104 #define CAM_CLIP_Y 0 #define CAM_CLIP_W 112 #define CAM_CLIP_H 224 int data[10] = {0,262,294,330,349,392,440,494,523,552}; int count = 1; uint8_t buf[DNN_IMG_W*DNN_IMG_H]; DNNRT dnnrt; DNNVariable input(DNN_IMG_W*DNN_IMG_H); static uint8_t const label[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; void CamCB(CamImage img) { if (!img.isAvailable()) { Serial.println("Image is not available. Try again"); return; } CamImage small; CamErr err = img.clipAndResizeImageByHW(small , CAM_CLIP_X, CAM_CLIP_Y , CAM_CLIP_X + CAM_CLIP_W -1 , CAM_CLIP_Y + CAM_CLIP_H -1 , DNN_IMG_W, DNN_IMG_H); if (!small.isAvailable()){ putStringOnLcd("Clip and Reize Error:" + String(err), ILI9341_RED); return; } small.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565); uint16_t* tmp = (uint16_t*)small.getImgBuff(); float *dnnbuf = input.data(); float f_max = 0.0; for (int n = 0; n < DNN_IMG_H*DNN_IMG_W; ++n) { dnnbuf[n] = (float)((tmp[n] & 0x07E0) >> 5); if (dnnbuf[n] > f_max) f_max = dnnbuf[n]; } for (int n = 0; n < DNN_IMG_W*DNN_IMG_H; ++n) { dnnbuf[n] /= f_max; } String gStrResult = "?"; dnnrt.inputVariable(input, 0); dnnrt.forward(); DNNVariable output = dnnrt.outputVariable(0); int index = output.maxIndex(); if (index < 10) { gStrResult = String(label[index]) + String(":") + String(output[index]); } else { gStrResult = String("?:") + String(output[index]); } Serial.println(gStrResult); img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565); uint16_t* imgBuf = (uint16_t*)img.getImgBuff(); } void setup() { Serial.begin(115200); //while (!Serial) { // ; // wait for serial port to connect. Needed for native USB port only //} theSD.begin(); theAudio = AudioClass::getInstance(); theAudio->begin(); puts("initialization Audio Library"); theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, 0, 0); File nnbfile = SD.open("numtone.nnb"); if (!nnbfile) { Serial.print("nnb not found"); return; } int ret = dnnrt.begin(nnbfile); if (ret < 0) { Serial.println("Runtime initialization failure."); if (ret == -16) { Serial.print("Please install bootloader!"); Serial.println(" or consider memory configuration!"); } else { Serial.println(ret); } return; } theCamera.begin(); theCamera.startStreaming(true, CamCB); //dnnrt.inputVariable(input, 0); //dnnrt.forward(); } void loop() { puts("loop!!"); DNNVariable output = dnnrt.outputVariable(0); int index = output.maxIndex(); //theAudio->setBeep(1,-40,262); theAudio->setBeep(1,-40,data[index]); usleep(500 * 1000); theAudio->setBeep(0,0,0); usleep(100000); }

メモ用紙に0~9までの数字を大きめに書いて、カメラに見せると数字によって音階が鳴ると思います
数字を入れ替えることによって演奏?できるので、これはもう新しい楽器!?
独立して動作するので、パソコンからMicroUSBケーブルを外しモバイルバッテリーに付け替えても楽しめます

〇最後に

今回はSonyより提供されているデータセットを使用して学習モデルを生成しました
しかし、これで満足できない方も多いと思います
ハンドサインで演奏したり、人の顔で演奏したり?

その思いが、機械学習を本格的に学習するきっかけになれば幸いです

spresenseに関してSonyより提供された様々なドキュメント、および有志の方々の記事を「大いに」参考にさせていただきました
この場を借りてお礼申し上げます

busyoucowのアイコン画像
よろしくお願いします。
ログインしてコメントを投稿する