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

tws が 2022年09月26日05時58分42秒 に編集

初版

タイトルの変更

+

背後の危険を察知する

タグの変更

+

spresense

記事種類の変更

+

製作品

本文の変更

+

# 概要 歩行者の背後の映像から急接近する自転車等を検出し、イヤホンから報知することで危険を知らせる。 SPRESENSEを利用してカメラ画像から差分を検出して、変化量が大きい場合に音を鳴らします。 自転車が背後から急接近してビックリすることが多く、なんとか事前に危険を察知しておきたい。 顔検知、自転車の検知、Optical Flow等を使うことが考えられますが、とりあえず連続したカメラ画像の差分を取り、差分の大きさで簡易的に検出しています。 現状は簡易的過ぎて反応しすぎてしまいます。 # 部品 - SPRESENSEメインボード - SPRESENSE拡張ボード - SPRESENSEカメラボード - SDカード - USBケーブル - モバイルバッテリー - リュックサックの肩紐に設置するケース # 概略図 SPRESENSEを通常通り組み立て、モバイルバッテリーより電源供給します。 SDカードにはDSPファイルをインストールの上([チュートリアルの通り](https://developer.sony.com/develop/spresense/docs/arduino_tutorials_ja.html#_dsp_%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB))、alarm.mp3を保存、SPRESENSEに挿しておいてください。 SPRESENSEはリュックサックの肩紐に設置して背後にカメラを向けます。 ![キャプションを入力できます](https://camo.elchika.com/d3d200fc885eead061fb643d8382b303de6c9c07/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f63336637626331662d656435642d343037642d393363332d3138633063306664626363322f36393939656232392d386630642d343935342d613233312d396534326430333533376463/) # 仮説 - 歩行者の背後に向けカメラを設置。 - 全部の歩行者を検知する必要はない。 - 遠くのものは検知する必要はない。 - 背景はあまり急には動かない(実際には歩行の上下運動や方向転換で結構動く)。 - スピードを出している自転車(に限らず)により連続した画像の差分が大きくなる。 # ソースコード ```ino:SPRESENSEのコード /* * camera.ino - Simple camera example sketch * Copyright 2018, 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 * * This is a test app for the camera library. * This library can only be used on the Spresense with the FCBGA chip package. */ #include <Camera.h> #include <SDHCI.h> #include <Audio.h> SDClass theSD; AudioClass *theAudio; File myFile; #define BAUDRATE (115200) uint8_t image[CAM_IMGSIZE_QQVGA_H*CAM_IMGSIZE_QQVGA_V]; int bufno = 0; unsigned long prediff; void CamCB(CamImage img) { /* Check the img instance is available or not. */ if (img.isAvailable()) { //Serial.print("Image data size = "); //Serial.print(img.getImgSize(), DEC); //Serial.print(" , "); //Serial.print("buff addr = "); //Serial.print((unsigned long)img.getImgBuff(), HEX); //Serial.println(""); uint16_t* imgbuf = (uint16_t*)img.getImgBuff(); if(bufno == 0){ for (int n = 0; n < CAM_IMGSIZE_QQVGA_H*CAM_IMGSIZE_QQVGA_V; n++) { image[n] = (uint8_t)(((imgbuf[n] & 0xf000) >> 8) | ((imgbuf[n] & 0x00f0) >> 4) & 0xff); } bufno++; } else { int diff = 0; for (int n = 0; n < CAM_IMGSIZE_QQVGA_H*CAM_IMGSIZE_QQVGA_V; n++) { uint8_t data = (uint8_t)(((imgbuf[n] & 0xf000) >> 8) | ((imgbuf[n] & 0x00f0) >> 4) & 0xff); diff = diff + abs(image[n] - data); } if(prediff/diff > 1.3){ Serial.println((unsigned long)diff); theAudio->stopPlayer(AudioClass::Player0); myFile.close(); myFile = theSD.open("alarm.mp3"); theAudio->writeFrames(AudioClass::Player0, myFile); theAudio->startPlayer(AudioClass::Player0); } prediff = diff; bufno = 0; } } else { Serial.println("Failed to get video stream image"); } } void setup() { CamErr err; Serial.begin(BAUDRATE); while (!Serial) { ; /* wait for serial port to connect. Needed for native USB port only */ } Serial.println("Prepare camera"); err = theCamera.begin(2, CAM_VIDEO_FPS_120, CAM_IMGSIZE_QQVGA_H, CAM_IMGSIZE_QQVGA_V, CAM_IMAGE_PIX_FMT_YUV422); Serial.println("Start streaming"); err = theCamera.startStreaming(true, CamCB); Serial.println("Set Auto white balance parameter"); err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT); while (!theSD.begin()) { Serial.println("Insert SD card."); } theAudio = AudioClass::getInstance(); //theAudio->begin(audio_attention_cb); theAudio->begin(); theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL); theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT); theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO); theAudio->setVolume(-160); } void loop() { } ``` # まとめ 簡易的な方法なので実用できず、もう少し歩行の動きに影響されないようにする必要がある。 Optical Flow、Deep Learningを使った方法も試してみたい。