編集履歴一覧に戻る
eMoi-picのアイコン画像

eMoi-pic が 2024年06月20日13時50分22秒 に編集

コメント無し

本文の変更

# EMOI-PIC ライブキャプチャーAI画像評価サンプルコード - Spresenseカメラでライブ撮影した画像を深層学習で評価するサンプルプログラムです。あらかじめSONY Neural Network Consoleで学習済のネットワークをmodelとして取り込んで実行します。評価値に基づいて様々なアプリケーションに応用することが可能です。 - 撮影画像: 160*120画素、RGB565カラー - AI評価対象画像: 16*12画素、RGB888カラー - Spresenseカメラ取付方向: カメラ基板のSONYロゴの上下が通常の場合は、 CAMERA_UPSIDEDOWNはFALSEで、ロゴが上下逆の場合はTRUEにしてください

+

![SONY NNC ネットワーク構造](https://camo.elchika.com/9fe5f8b3d6fe2d5875b2cbc0c5805049075b591f/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f64343830333136392d363131652d343365322d383663332d6331616438303838646561382f61653061653136392d373631382d343038612d383130382d656638396235353339663762/)

``` #include <stdio.h> #include <Camera.h> #include <Adafruit_ILI9341.h> #include <SDHCI.h> #include <DNNRT.h> #define TFT_DC (9) #define TFT_CS (10) #define CAMERA_UPSIDEDOWN FALSE #define DISPLAY_WIDTH (320) #define DISPLAY_HEIGHT (240) #define DNN_WIDTH (16) #define DNN_HEIGHT (12) #define DNN_COLOR (24) Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC); SDClass theSD; DNNRT dnnrt; DNNVariable input(DNN_WIDTH*DNN_HEIGHT*DNN_COLOR); uint16_t* image_buffer; uint16_t drawImageBuf[160*120]; int total_image_count = 0; void putStringOnLCD(String str, int line, int color) { int len = str.length(); display.fillRect(0, DISPLAY_HEIGHT/2+line*18+6, DISPLAY_WIDTH-1, DISPLAY_HEIGHT/2+(line+1)*18+5, ILI9341_BLACK); display.setTextSize(2); int sx = DISPLAY_WIDTH/2 - len/2*12; if (sx < 0) sx = 0; if (line < 0) sx = 0; else if (line > 5) sx = 5; display.setCursor(sx, DISPLAY_HEIGHT/2+line*18+8); display.setTextColor(color); display.println(str); } void CamCB(CamImage img) { if (img.isAvailable()) { image_buffer = (uint16_t *)img.getImgBuff(); } } void setup() { CamErr err; display.begin(); display.setRotation(3); display.fillScreen(ILI9341_BLACK); display.fillScreen(ILI9341_BLACK); err = theCamera.begin(1, CAM_VIDEO_FPS_5, CAM_IMGSIZE_QQVGA_H, CAM_IMGSIZE_QQVGA_V, CAM_IMAGE_PIX_FMT_RGB565); err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_AUTO); err = theCamera.startStreaming(true, CamCB); while (!theSD.begin()) { putStringOnLCD("Insert SD card", 0, ILI9341_GREEN); } File nnbfile = theSD.open("model.nnb"); // SDカード内の学習済モデルのファイルをオープン if (!nnbfile) { putStringOnLCD("model.nnb is not found", 0, ILI9341_RED); while(1); } int ret = dnnrt.begin(nnbfile); // DNNRTを初期化 if (ret < 0) { char textBuf[16] = {0}; sprintf(textBuf, "DNNRT begin fail: %f", ret); putStringOnLCD(textBuf, 0, ILI9341_RED); while(1); } } void loop() { // 入力画像(160*120)をディスプレイに描画 display.drawRGBBitmap(0, 0, image_buffer, CAM_IMGSIZE_QQVGA_H, CAM_IMGSIZE_QQVGA_V); float* rPlane = input.data(); float* gPlane = rPlane + DNN_WIDTH * DNN_HEIGHT; float* bPlane = gPlane + DNN_WIDTH * DNN_HEIGHT; // 入力画像(160*120)を16*10に間引きながら1次元入力ベクトルに書き込み if(CAMERA_UPSIDEDOWN == FALSE) { for (int y = 0; y < DNN_HEIGHT; y++) { for (int x = 0; x < DNN_WIDTH; x++) { int n = y*10*CAM_IMGSIZE_QQVGA_H + x*10; *(rPlane++) = (float)((image_buffer[n] >> 8) & 0xf8) / 255.0; *(gPlane++) = (float)((image_buffer[n] >> 3) & 0xfc) / 255.0; *(bPlane++) = (float)((image_buffer[n] << 3) & 0xf8) / 255.0; } } } else { for (int y = DNN_HEIGHT; y >= 0; y--) { for (int x = DNN_WIDTH; x >= 0; x--) { int n = y*10*CAM_IMGSIZE_QQVGA_H + x*10; *(rPlane++) = (float)((image_buffer[n] >> 8) & 0xf8) / 255.0; *(gPlane++) = (float)((image_buffer[n] >> 3) & 0xfc) / 255.0; *(bPlane++) = (float)((image_buffer[n] << 3) & 0xf8) / 255.0; } } } dnnrt.inputVariable(input, 0); // 入力データ設定 dnnrt.forward(); // 推論実行 DNNVariable output = dnnrt.outputVariable(0); // 推薦結果取得 char textBuf[16] = {0}; sprintf(textBuf, "AI eval: %f", output[0]); // outputベクトルの先頭がスカラー評価値 putStringOnLCD(textBuf, 3, ILI9341_WHITE); delay(1000); } ```