57934


SPRESENSEのカメラで現在映しているプレビューを、PCの画面に表示させることは可能でしょうか。

接続方法は、できれば、USB（メインボード側のSerial）が良いです。


CC BY-SA 4.0
2019-08-25T02:33:06.667
57583
2019-09-09T01:53:34.453
35541
question
spresense
カメラのリアルタイムのプレビューをPCの画面に表示する方法


ご質問に触発されて Processing で作ってみました。

SPRESENSE のスケッチ

[code]

    #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 */
    }
    
    
[/code]

Processing のスケッチ

[code]

    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;
          }
        }
      }
    }
    
[/code]

このサンプルは、シリアルケーブル一本で PC にプレビュー画面を転送し、PC側は Processing で受けて表示するというものです。

次のサイトに動作の様子を記録した動画がありますので、ご興味があれば。

<https://makers-with-myson.blog.so-net.ne.jp/2019-09-08>

2Mbps なので転送能力としては、毎秒250kB。一方で、SPRESENSE のプレビュー画像は RGB565 の 320 x 240
ですので、153.6kB。フレームレートは理論的に 1.6 fps。なので 1.5 -1.4 fps くらいを期待していたのですが、実能力としては 0.9
-0.8 fps。Processing にオーバーヘッドがあるようで、思ったよりも性能が出ませんでした。

以上、ご参考になれば。


CC BY-SA 4.0
2019-09-08T16:20:30.813
57934
2019-09-09T01:53:34.453
2019-09-09T01:53:34.453
27334
27334
57583
answer