SSブログ

SPRESENSEカメラのモニターをProcessingで作ってみた! [SPRESENSE]

前回、SPRESENSEとProcessingを使ってタイムラプスカメラを作ってみました。そこに、いつもチェックしているスタックオーバーフローで次のような問いかけが!



カメラのリアルタイムのプレビューをPCの画面に表示する方法

SPRESENSEのカメラで現在映しているプレビューを、PCの画面に表示させることは可能でしょうか。接続方法は、できれば、USB(メインボード側のSerial)が良いです。




ん!?これは、できそうな気がするぞ。SPRESENSEとProcessingを使えば…。

ということでチャレンジしてみました!

接続はリクエスト通りシリアルケーブル一本で。SPRESENSE からプレビュー画像を転送し、PC上の Processing でデータを受けて画像を表示します。


Spresense_monitor_s.png


余談ですが、少し前に3Dプリンタで作ったカメラホルダをつけてみました。カメラとUSBケーブルの干渉がなくなり、少しすっきりしました。


sDSC_0711.jpg


今回作成したスケッチです。すごくシンプルなのですが、Processing のシリアルはなかなか使いこなすのが大変で苦労しました。Windows + Java のためか、リアルタイムには程遠く、安定した通信をするために、ところどころ工夫が必要でした。


SPRESENSEのスケッチ
#include <Camera.h>

#define BAUDRATE       2000000

void CamCB(CamImage img) {

  if (img.isAvailable() == false) return;
 
  while (Serial.available() <= 0); 
  // taking a picture is started by receiving 'S'
  if (Serial.read() != 'S') return;
  delay(1); // wait for stable connection
  
  digitalWrite(LED0, HIGH);
  img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
  char *buf = img.getImgBuff();
  for (int i = 0; i < img.getImgSize(); ++i, ++buf) {
    Serial.write(*buf);
  }
  digitalWrite(LED0, LOW);
}

void setup() {
  
  Serial.begin(BAUDRATE);
  while (!Serial) {};

  theCamera.begin();
  theCamera.startStreaming(true, CamCB);
  theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
}

void loop() {
  /* do nothing here */
}



Processingのスケッチ
import processing.serial.*;
import java.io.*;
Serial myPort;

PImage img;
final static int WIDTH = 320;
final static int HEIGHT = 240;
boolean started = false;
int serialTimer = 0;
int total = 0;
int x = 0;
int y = 0;

void setup() {
  size(320, 240); 
  background(0);
  img = createImage(WIDTH, HEIGHT, RGB); 
  myPort = new Serial(this, Serial.list()[0], 2000000);  
  myPort.clear();
  println("setup finished");
  delay(2000); // wait for stable connection
}

void draw() {

  if (started == false) {
    started = true;  
    println("start");
    myPort.write('S');
    myPort.clear();
    total = 0;      
    delay(10);
    return;
  }

  // To get stable connection, please adjsut this interval
  final int interval = 1;
  if (millis() - serialTimer > interval) {
    serialTimer = millis();   
    if (myPort.available() <= 0) return;
    
    while (myPort.available() > 0) {       
      char lbyte = (char)myPort.read();
      char ubyte = (char)myPort.read();
      x = total % WIDTH;
      y = total / WIDTH;
      int value = (ubyte << 8) | (lbyte); // RGB565 format
      char r = (char)(((value & 0xf800) >> 11) << 3);
      char g = (char)(((value & 0x07E0) >> 5)  << 2);
      char b = (char)((value & 0x001f) << 3);
      color c = color(r, g, b);
      img.set(x, y, c);
      ++total;

      if (total >= WIDTH*HEIGHT) {
        println("end");
        myPort.clear();
        started = false;
        total = 0;
        image(img, 0, 0);
        break;
      }
    }
  }
}



動かしてみると、パフォーマンスは、おおよそ 0.9-0.8fps 。理論的には、 (2000000/8) bytes / 153,600 bytes / =1.6 fps 位のはずですが、Processing の応答性が思いのほか悪く、あまり良い数字は出ませんでした。

実際の動きはこちらの動画で見ることができます!





パフォーマンスはいまいちですけど、この小さなカメラで画面を見れるのはいいですね。次はプレビューではなくて、もう少し大きな画像を転送してみようかな…。
(^^)/~


<参考記事>
SPRESENSEとProcessingでタイムラプスに挑戦! 
https://makers-with-myson.blog.so-net.ne.jp/2019-08-17






nice!(32)  コメント(2) 

nice! 32

コメント 2

ぽちの輔

監視カメラを自作できそうですね^^
by ぽちの輔 (2019-09-09 05:51) 

ys_oota

そのうち、WiFi版を作ってみたいと思います!
by ys_oota (2019-09-16 21:12) 

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。