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

LCDとカメラをspreseneに固定し、作業監視ツールを制作する

LCDとカメラをspreseneに固定し、作業監視ツールを制作する

キャプションを入力できます

  1. はじめに
    この投稿ではLCDとカメラをSpresenseに固定し、カメラの位置が決められることでNeuralNetworkConsolを使った物体認識等の機能を使いやすくすることを目的とします。
    そして、使用例としてこの記事では、デスクの前で作業を行っているかを検知する装置を制作します。
    (作業用のデスクの前にいるかをカメラから検知しデスクから離れた際はブザーを鳴らして警告するプログラム)
    私がこの装置を提案する理由は、普段私が自宅で作業をするときに気が散りデスクから離れてTwitter等を見ていることが多く、この装置を使えば作業効率のアップが期待できると考えたためです。
    また、 太田義則(2022)『SPRESENSEではじめるローパワーエッジAI』で紹介されている数字を識別するプログラムを一部変更することで実装します。

  2. 使用機材
    Spresense メインボード
    Spresense 拡張ボード
    Spresense カメラボード(通常カメラ)
    Mic&LCD KIT for SPRESENSEAUTOLAB-001
    Micro USB (USB A-Microb)ケーブル
    microSDHCカード
    電子ブザー

  • カメラ固定用素材
    タミヤ 楽しい工作シリーズ プラバン 0.1mm
    タミヤ 楽しい工作シリーズ プラ材5mm 角棒
    こなべねじ M2×25mm

  • 工作用道具(プラバンや角棒が加工できれば何でもいいです)
    直角定規
    デザインナイフ
    カッターマット
    2mmの穴があけられるドリル
    瞬間接着剤

3.制作過程
キャプションを入力できます
プラバンを4cm×12cmぐらいに切ります
キャプションを入力できます
キャプションを入力できます
Mic&LCD KIT for SPRESENSEAUTOLAB-001付属の台座を使用します。
プラバンの端とSPRESENSEのLCD取り付け位置と逆側の端をそろえて2mmの穴をプラバンに開けねじでとめれるようにします。
そうしたら、定規等を当てて90度に折り曲げる箇所に線を引きます。
キャプションを入力できます
線に沿って切ります。
キャプションを入力できます
キャプションを入力できます
また、SPRESENSE本体と干渉する箇所が出るので切り取ります
キャプションを入力できます
キャプションを入力できます
角棒を長さを合わせて切り、接着剤等で接着します
キャプションを入力できます
プラバンの上側をカメラのコードが届きカメラを付けられる位置になるまで切り調節します。
そのあとは2mmの穴をあけねじで固定します。

  • 完成
    キャプションを入力できます
    キャプションを入力できます
    完成です。
    使用する際は写真のようにある程度高さのある台に置くとよいと思います。
  1. 使用例
    実際にNeuralNetworkConsolを使用し検知を行ってみたいと思います。
    https://github.com/TE-YoshinoriOota/Spresense-LowPower-EdgeAI/tree/main/Chap07
    太田義則(2022)『SPRESENSEではじめるローパワーエッジAI』において紹介された
    学習モデル model.nnb とソースコード number_recog_simple.ino を一部変更し、使用しました。

一部変更したプログラム

/* * number_recog_simple.ino - Simple number recognition sketch * Copyright 2022 Sony Semiconductor Solutions Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include <Camera.h> #include "Adafruit_ILI9341.h" #include <DNNRT.h> #include <SDHCI.h> #define TFT_DC 9 #define TFT_CS 10 Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC); #define PIN1 1 #define OFFSET_X (104) #define OFFSET_Y (0) #define CLIP_WIDTH (112) #define CLIP_HEIGHT (224) #define DNN_WIDTH (28) #define DNN_HEIGHT (28) SDClass SD; DNNRT dnnrt; DNNVariable input(DNN_WIDTH*DNN_HEIGHT); const char label[11] = {'0','1','2','3','4','5','6','7','8','9',' '}; void CamCB(CamImage img) { if (!img.isAvailable()) return; // カメラ画像の切り抜きと縮小 CamImage small; CamErr err = img.clipAndResizeImageByHW(small , OFFSET_X, OFFSET_Y , OFFSET_X + CLIP_WIDTH -1 , OFFSET_Y + CLIP_HEIGHT -1 , DNN_WIDTH, DNN_HEIGHT); if (!small.isAvailable()) return; // 認識用モノクロ画像をDNNVariableに設定 uint16_t* imgbuf = (uint16_t*)small.getImgBuff(); float *dnnbuf = input.data(); for (int n = 0; n < DNN_HEIGHT*DNN_WIDTH; ++n) { // YUV422の輝度成分をモノクロ画像として利用 // 学習済モデルの入力に合わせ0.0-1.0に正規化 dnnbuf[n] = (float)(((imgbuf[n] & 0xf000) >> 8) | ((imgbuf[n] & 0x00f0) >> 4))/255.; } // 推論の実行 dnnrt.inputVariable(input, 0); dnnrt.forward(); DNNVariable output = dnnrt.outputVariable(0); int index = output.maxIndex(); // 推論結果の表示 String gStrResult; if (index < 11) { gStrResult = String(label[index]) + String(":") + String(output[index]); } else { gStrResult = String("Error"); } Serial.println(gStrResult); img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565); display.drawRGBBitmap(0, 0, (uint16_t *)img.getImgBuff(), 320, 240); //変更部分 if (label[index] != ' ') { digitalWrite(PIN1, LOW); } else { digitalWrite(PIN1, HIGH); //PIN1をON } } void setup() { pinMode(PIN1, OUTPUT); Serial.begin(115200); // SDカードの挿入待ち while (!SD.begin()) {Serial.println("Insert SD card");} // SDカードにある学習済モデルの読み込み File nnbfile = SD.open("model.nnb"); // 学習済モデルでDNNRTを開始 dnnrt.begin(nnbfile); display.begin(); display.setRotation(3); theCamera.begin(); theCamera.startStreaming(true, CamCB); } void loop() { }

キャプションを入力できます
ブザーを鳴らすため、Spresenseのpin1番に電子ブザーの+極、SpresenseのGNDに電子ブザーの-極を付けてください。
pin1番を出力用に PIN1 として定義しています。
数字が検知されないときにPIN1からブザーを鳴らすように変更しました。
数字を印刷した紙を体に貼りデスクの上にこの装置を置くことで、数字を検知している間は音が止まり、
デスクから離れると数字を認識しなくなるので音が鳴ります。

実行方法

  1. https://github.com/TE-YoshinoriOota/Spresense-LowPower-EdgeAI/tree/main/Libraries
    URLからライブラリをダウンロードし、AruduinoIDEに読み込みます。
  2. microSDカードにgitHubからダウンロードしたmodel.nnbを入れてSpresenseにmicroSDカードに差し込みます。
  3. ソースコードをArduinoIDEからSpresenseに書き込み起動します。

実行結果

キャプションを入力できます
シュール。
(プライバシー保護のために顔を隠しています。)

数字を読み違えることはありますが、目の前に数字さえあれば0~9の出力をするため今回は問題ないです。
人がいない(どっかでサボってる)= 数字が読めない ときは ' ' が出力 となります。
そして出力が ' ' のときにブザーを鳴らすことにより、作業をしていない人に警告を行います。

5.参考文献
太田義則(2022)『SPRESENSEではじめるローパワーエッジAI』

ログインしてコメントを投稿する