0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ArduCAMで撮った画像をFTPサーバに送る

Last updated at Posted at 2024-04-27

ArduCAM to FTP

0. Motivation

ArduinoのカメラモジュールArduCAM-Mini-2MPで撮った、連続した2画像の差分が大きい場合のみ、その画像をサーバ上にコピーしたかったのすが、ググっても撮った画像をSDカード(モジュール)上に保存するサンプルしか見つかりませんでした。

1. ArduCAMでjpgフォーマットとして画像を撮る

下記にArduCAM-Mini-2MPでjpg画像として撮って、Arduionoのバッファ上に保持するサンプルはありました。
https://github.com/Dasch0/esp32-arducam-edge-impulse/blob/main/src/main.cpp

2. jpg画像をデコードして2枚の画像の差分を取る

下記Tiny JPEG Decompressorはjpg画像をArduino内蔵メモリでもデコードできます。
http://elm-chan.org/fsw/tjpgd/en/appnote.html
これを使って、連続した2枚のjpg画像をデコードし、ピクセル毎に比較することにしました。

上記Exampleのstruct IODEVを、ファイルのポインタではなくArduCAMで撮ったjpg画像(char型の配列)のポインタをInput stream *jbufとして渡せるように、そのサイズもlbyteとして渡せるように修正してます。加えて、デコード時に、前回デコードされた画像とのピクセル間の差分の和を保持するdiffというメンバも追加しています。

// TJpgDec Session identifier for input/output functions (name, members and usage are as user defined)
typedef struct {
    char *jbuf;             /* Input stream */
    uint8_t *fbuf;          /* Output frame buffer */
    unsigned int wfbuf;     /* Width of the frame buffer [pix] */
    uint32_t lbyte;         /* Number bytes left in the input stream */
    int diff;               /* difference between current and previous frame buffers */
} IODEV;

同様にinput functionを、ファイル操作でなく上記struct IODEVで渡されるjpg画像(*jbuf)をmemcpyでread buffer buffnbyte分コピーしするよう修正しています。

// TJpgDec User defined input function
size_t in_func (    /* Returns number of bytes read (zero on error) */
    JDEC* jd,       /* Decompression object */
    uint8_t* buff,  /* Pointer to the read buffer (null to remove data) */
    size_t nbyte    /* Number of bytes to read/remove */
)
{
    IODEV *dev = (IODEV*)jd->device;   /* Session identifier (5th argument of jd_prepare function) */

    /* Copy input stream, dev->jbuf, to read buffer, buff */
    if (nbyte > dev->lbyte)
      nbyte = dev->lbyte;
    if (buff) /* Read data from imput stream */
      memcpy(buff, dev->jbuf, nbyte);
    dev->lbyte -= nbyte;
    dev->jbuf += nbyte;

    return nbyte;
}

output functionは、入力jpg画像をデコードしたビットマップ画像bitmapを出力frame buffer wfbufにコピーする際に、wfbufに残っている前回のピクセル値とbitmapの同じピクセルの値の差分の二乗和平方根の和を上記struct IODEVのメンバdiffに保持します。

// TJpgDec User defined output function
unsigned int out_func (      /* Returns 1 to continue, 0 to abort */
    JDEC* jd,       /* Decompression object */
    void* bitmap,   /* Bitmap data to be output */
    JRECT* rect     /* Rectangular region of output image */
)
{
    IODEV *dev = (IODEV*)jd->device;   /* Session identifier (5th argument of jd_prepare function) */
    uint8_t *src, *dst;
    uint16_t y, bws, i;
    unsigned int bwd;

    /* Progress indicator */
    if (rect->left == 0) {
        if(Serial)
          Serial.printf("\r%lu%%. ", (rect->top << jd->scale) * 100UL / jd->height);
    }
    /* Copy the output image rectangle to the frame buffer */
    src = (uint8_t*)bitmap;                           /* Output bitmap */
    dst = dev->fbuf + N_BPP * (rect->top * dev->wfbuf + rect->left);  /* Left-top of rectangle in the frame buffer */
    bws = N_BPP * (rect->right - rect->left + 1);     /* Width of the rectangle [byte] */
    bwd = N_BPP * dev->wfbuf;                         /* Width of the frame buffer [byte] */
    for (y = rect->top; y <= rect->bottom; y++) {
      for (i = 0; i < bws/N_BPP; i++){  /* Calculate the difference between output bitmap and previous frame buffer before copy */
        dev->diff += sq((int)dst[i*3] - (int)src[i*3]);
        dev->diff += sq((int)dst[i*3 + 1] - (int)src[i*3 + 1]);
        dev->diff += sq((int)dst[i*3 + 2] - (int)src[i*3 + 2]);
      }
      memcpy(dst, src, bws);   /* Copy a line */
      src += bws; dst += bwd;  /* Next line */
    }

    return 1;    /* Continue to decompress */
}

3. jpg画像をFTPサーバに送る

下記で対象をFTPサーバにコピーできます。
https://playground.arduino.cc/Code/FTP/

上記で計算した連続した2枚のjpg画像の差分diffが、ある一定値(ここでは20000000)以上だと、FTPで新しい方の画像をftpサーバに保存してます。

  if (devid.diff > 20000000) { // ftp the current jpg image if the difference between current and previous and images is more than this value
    doFTP(jpeg_buffer, jpeg_size);
    ...
  }

4. まとめ

上記三つのサンプルを下記の通り組み合わせて、所望の(連続した2画像のうち差分の大きい)jpg画像をFTPサーバに送れました。
https://github.com/kamotsuru/arducam2ftp/blob/main/arducam2ftp.ino

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?