chrmlinux03のアイコン画像
chrmlinux03 2024年02月06日作成 (2024年02月06日更新) © MIT
セットアップや使用方法 セットアップや使用方法 閲覧数 3013
chrmlinux03 2024年02月06日作成 (2024年02月06日更新) © MIT セットアップや使用方法 セットアップや使用方法 閲覧数 3013

【SPRESENSE】液晶にカメラ画像の動画再生に成功したよっ

【SPRESENSE】液晶にカメラ画像の動画再生に成功したよっ

おつかれさまでございます

リナちゃん X@chrmlinux03 です

動画で液晶に再生出来たよ

Spresense の カメラで撮った写真をパラパラ漫画で動画に出来たよっ

使用部品

部品 御提供品
SPRESENSE本基板
SPRESENSE拡張基板
SPRESENSEカメラ一式
カメラと拡張基板を繋ぐ配線 後日公開される
はま寿司 お寿司は4皿まで

spresense用"spreGraphics.hpp"

#ifndef __GRAPHIC_HPP__ #define __GRAPHIC_HPP__ #define SPI4_SCLK (13) #define SPI4_MISO (12) #define SPI4_MOSI (11) #define SPI4_CS (10) #define SPI4_DC ( 9) #define SPI4_RST ( 8) #define SPI4_CS2 ( 7) #define IO_SW4 ( 7) #define IO_SW3 ( 6) #define IO_SW2 ( 5) #define IO_SW1 ( 4) #define ROT0 (0) #define ROT90 (1) #define ROT180 (2) #define ROT270 (3) #define MEGA (1000 * 1000) #define LGFX_AUTODETECT #define LGFX_USE_V1 #include <LovyanGFX.hpp> class LGFX : public lgfx::LGFX_Device { lgfx::Panel_ILI9341 _panel_instance; lgfx::Bus_SPI _bus_instance; public: LGFX(void) { { auto cfg = _bus_instance.config(); cfg.spi_mode = 0; cfg.spi_port = 4; cfg.freq_write = (20 * MEGA); cfg.freq_read = (16 * MEGA); cfg.pin_dc = SPI4_DC; _bus_instance.config(cfg); _panel_instance.setBus(&_bus_instance); } { auto cfg = _panel_instance.config(); cfg.pin_cs = SPI4_CS; cfg.pin_rst = SPI4_RST; cfg.pin_busy = -1; cfg.panel_width = 240; cfg.panel_height = 320; cfg.bus_shared = true; _panel_instance.config(cfg); } setPanel(&_panel_instance); } }; static LGFX lcd; static LGFX_Sprite spr; static bool useGraphics = false; static uint16_t _w, _h, _hw, _hh; int16_t setupGraphics(int16_t rot) { lcd.init(); lcd.setRotation(rot); spr.setColorDepth(16); spr.createSprite(lcd.width(), lcd.height()); _w = spr.width(); _h = spr.height(); _hw = _w >> 1; _hh = _h >> 1; useGraphics = true; return 0; } //================================== // getfps //================================== uint32_t getfps(void) { static uint32_t psec = 0; static uint32_t cnt = 0; static uint32_t fps = 0; uint32_t sec = 0; sec = millis() / 1000; ++cnt; if (psec != sec) { psec = sec; fps = cnt; cnt = 0; } return fps; } //================================== // drawAst //================================== void drawAst(LGFX_Sprite *spr, int gx, int gy) { static int cnt = 0; char ast[4] = "|/-\\"; spr->setTextColor(TFT_WHITE, TFT_BLACK); spr->setCursor(gx, gy); spr->printf("[%c] %3d fps\n", ast[cnt], getfps()); cnt = (cnt + 1) % 4; } #endif

cam2.ino

#include <SDHCI.h> SDClass theSD; #include <Camera.h> #define CIMG_H CAM_IMGSIZE_QVGA_H #define CIMG_V CAM_IMGSIZE_QVGA_V //#define CIMG_FMT CAM_IMAGE_PIX_FMT_JPG #define CIMG_FMT CAM_IMAGE_PIX_FMT_RGB565 #include <spreGraphics.hpp> void printError(enum CamErr err) { Serial.print("Error: "); switch (err) { case CAM_ERR_NO_DEVICE: Serial.println("No Device"); break; case CAM_ERR_ILLEGAL_DEVERR: Serial.println("Illegal device error"); break; case CAM_ERR_ALREADY_INITIALIZED: Serial.println("Already initialized"); break; case CAM_ERR_NOT_INITIALIZED: Serial.println("Not initialized"); break; case CAM_ERR_NOT_STILL_INITIALIZED: Serial.println("Still picture not initialized"); break; case CAM_ERR_CANT_CREATE_THREAD: Serial.println("Failed to create thread"); break; case CAM_ERR_INVALID_PARAM: Serial.println("Invalid parameter"); break; case CAM_ERR_NO_MEMORY: Serial.println("No memory"); break; case CAM_ERR_USR_INUSED: Serial.println("Buffer already in use"); break; case CAM_ERR_NOT_PERMITTED: Serial.println("Operation not permitted"); break; default: break; } } void CamCB(CamImage img) {} void setup(void) { CamErr err; Serial.begin( 115200 ); while (!Serial); while (!theSD.begin()); err = theCamera.begin(); if (err != CAM_ERR_SUCCESS) printError(err); //err = theCamera.startStreaming(true, CamCB); if (err != CAM_ERR_SUCCESS) printError(err); err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT); if (err != CAM_ERR_SUCCESS) printError(err); err = theCamera.setStillPictureImageFormat(CIMG_H, CIMG_V, CIMG_FMT); if (err != CAM_ERR_SUCCESS) printError(err); setupGraphics(ROT90); } void loop(void) { spr.startWrite(); spr.clear(TFT_BLACK); CamImage img = theCamera.takePicture(); if (img.isAvailable()) { switch (CIMG_FMT) { case CAM_IMAGE_PIX_FMT_RGB565: spr.setSwapBytes(true); spr.pushImage(0, 0, CIMG_H, CIMG_V, (uint16_t*)img.getImgBuff(), img.getImgSize()); spr.setSwapBytes(false); break; case CAM_IMAGE_PIX_FMT_JPG: spr.drawJpg(img.getImgBuff(), img.getImgSize(), 0, 0); break; } } drawAst(&spr, 8, _h - 8); spr.pushSprite(&lcd, 0, 0); spr.endWrite(); }

ポイント1

RGB565 の並びが逆だった

img.getImgBuff() で返って来る イメージがどうも
上下バイト逆になってるっぽいので
spr.setSwapBytes(true);
:
この間は並びが逆に出来る
:
spr.setSwapBytes(false);

で回避した٩(ˊᗜˋ*)و

ポイント2

startStream しなくても動くっぽい

// err = theCamera.startStreaming(true, CamCB); if (err != CAM_ERR_SUCCESS) printError(err);

ポイント3

spr.drawJpgだと激重

RGB565であればなんとか使えるかなぁと言う感じ

ポイント4

イメージサイズは QVGA_H/ QVGA_V (320x240)

#define CIMG_H CAM_IMGSIZE_QVGA_H
#define CIMG_V CAM_IMGSIZE_QVGA_V
//#define CIMG_FMT CAM_IMAGE_PIX_FMT_JPG
#define CIMG_FMT CAM_IMAGE_PIX_FMT_RGB565
QQVGA_H/QQVGA_V(160x120) でも動くけどちょっと寂しい💕
デフォルトで書かれていたサイズだと色々重いっぽい

callback は空でも動く

無理に色々しなくてもOK

void CamCB(CamImage img) {}

最後に

これでやっとオブジェクトトラッキングが出来るようになる
ご清聴ありがとうございましたっ

1
chrmlinux03のアイコン画像
今は現場大好きセンサ屋さん C/php/SQLしか書きません https://arduinolibraries.info/authors/chrmlinux https://github.com/chrmlinux #リナちゃん食堂 店主 #シン・プログラマ
ログインしてコメントを投稿する