گرفتن تصاویر خراب در راه‌اندازی دوربین OV2640 و ماژول ESP32S3

سلام به همگی دوستان، وقتتون بخیر باشه
من یه برد برای ماژول ESP32-S3-WROOM-1-N16R8 (این ماژول 8MB حافظه PSRAM و 16MB حافظه فلش داره) طراحی کرده بودم و می‌خواستم دوربین OV2640 رو باهاش راه اندازی کنم. می‌خواستم دوربین به مدت 10 ثانیه و هر 100m ثانیه یک فریم تصویر با رزولوشن XGA (1024*768) بگیره و روی SD Card ذخیره کنه. SD Card هم با رابط SDIO راه اندازی شده.
اما مشکلی که هست تصاویر ذخیره شده بسیار خراب و بد هستن. مثلا تصاویر بریده بریده، نصف تصویر رنگ سبز و باقی تصویر کاملا سیاه شده و…
.
خود دوربین ایرادی نداره و حتی از دوربین دیگه هم استفاده کردم ولی باز مشکل وجود داشت.
حتی گفتم شاید ذخیره کردن تصاویر روی SD Card مشکل داشته باشه برای همین نمونه کد camera_webserver که در خود آردوینو هست رو هم تست کردم، و وقتی تصاویر رو به صورت استریم آنلاین از طریق وای فای دریافت می‌کردم باز این مشکل وجود داشت و تصاویر خراب دریافت می‌کردم.
.
می‌خواستم بپرسم این مشکل می‌تونه از چی باشه؟ مثلا ایراد از استفاده نکردن صحیح از حافظه هست؟ آیا باید گزینه دیگه‌ای برای حافظه PSRAM انتخاب بشه؟ یا خود کد نویسی ایراداتی داره؟

کد استفاده شده:

#include "esp_camera.h"
#include "SD_MMC.h"

// Define Camera pins
#define PWDN_GPIO_NUM  -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM  10
#define SIOD_GPIO_NUM  4
#define SIOC_GPIO_NUM  5
#define Y9_GPIO_NUM    9
#define Y8_GPIO_NUM    11
#define Y7_GPIO_NUM    12
#define Y6_GPIO_NUM    14
#define Y5_GPIO_NUM    47
#define Y4_GPIO_NUM    45
#define Y3_GPIO_NUM    48
#define Y2_GPIO_NUM    21
#define VSYNC_GPIO_NUM 3
#define HREF_GPIO_NUM  46
#define PCLK_GPIO_NUM  13

// Define SDIO pins
#define MMCSCK 16
#define MMCCMD 17
#define MMCD0 15
#define MMCD1 7
#define MMCD2 8
#define MMCD3 18


// Frame settings
#define FRAME_RATE       10  // FPS
#define FRAME_DURATION   1000 / FRAME_RATE  // Duration of each frame in milliseconds

unsigned long now;
static unsigned long lastCapture = 0;

static int frameCount = 0;
static File file;


void setup() {
    Serial.begin(115200);

    // Camera configuration
    camera_config_t config;
    config.ledc_channel = LEDC_CHANNEL_0;
    config.ledc_timer = LEDC_TIMER_0;
    config.pin_d0 = Y2_GPIO_NUM;
    config.pin_d1 = Y3_GPIO_NUM;
    config.pin_d2 = Y4_GPIO_NUM;
    config.pin_d3 = Y5_GPIO_NUM;
    config.pin_d4 = Y6_GPIO_NUM;
    config.pin_d5 = Y7_GPIO_NUM;
    config.pin_d6 = Y8_GPIO_NUM;
    config.pin_d7 = Y9_GPIO_NUM;
    config.pin_xclk = XCLK_GPIO_NUM;
    config.pin_pclk = PCLK_GPIO_NUM;
    config.pin_vsync = VSYNC_GPIO_NUM;
    config.pin_href = HREF_GPIO_NUM;
    config.pin_sccb_sda = SIOD_GPIO_NUM;
    config.pin_sccb_scl = SIOC_GPIO_NUM;
    config.pin_pwdn = PWDN_GPIO_NUM;
    config.pin_reset = RESET_GPIO_NUM;
    config.xclk_freq_hz = 20000000;
    config.pixel_format = PIXFORMAT_JPEG;

    // Set the resolution frame image
    config.frame_size = FRAMESIZE_XGA; //1024x768
    config.jpeg_quality = 12;
    config.fb_count = 1;

    // Use PSRAM for the frame buffer
    config.fb_location = CAMERA_FB_IN_PSRAM;

    if (psramFound()) {
      Serial.println("PSRAM FOUND"); // when run code alwayse PSRAM FOUND.
    }

    // Initialize the camera
    if (esp_camera_init(&config) != ESP_OK) {
        Serial.println("Failed to initialize camera.");
        return;
    }

    // Initialize SD card
    SD_MMC.setPins(MMCSCK, MMCCMD, MMCD0, MMCD1, MMCD2, MMCD3);
    if (!SD_MMC.begin()) {
        Serial.println("SD card mount failed.");
        return;
    }

    Serial.println("SD card initialized.");
}

void loop() {

    now = millis();

    if (now - lastCapture>=FRAME_DURATION) {
        lastCapture = now;
                
        // Capture a frame
        camera_fb_t *fb = esp_camera_fb_get();
        if (!fb) {
            Serial.println("Failed to capture image.");
            return;
        }
        
        // Save frame to SD card
        String path = "/frame" + String(frameCount) + ".jpg";
        
        file = SD_MMC.open(path, FILE_WRITE);
        if (!file) {
            Serial.println("Failed to open file for writing.");
            esp_camera_fb_return(fb);
            return;
        }

        file.write(fb->buf, fb->len);
        file.close();
        
        esp_camera_fb_return(fb);

        frameCount++;
    }

    // Capture frames for 10 seconds
    if (millis() - start_capture >= 10000) {
        Serial.println("Capture complete.");
        while (true);  // Stop the loop
    }
}

تنظیمات:

از وقتی که گذاشتین خیلی ممنونم، مرسی :pray: :pray:

سلام. اول از همه میخواستم صرفا این نکته رو بهتون بگم که کلا برای دوربین اونم با این رزولویشن اصلا روی این تراشه حساب نکنید و پردازش همچین تصویری و به علاوه ذخیره کردنش اصلا کار این تراشه نیست و در حقیقت شما باید از تراشه های قویتر و مخصوص این کار استفاده کنید که از معروف هاش میشه Allwinner v3s و Allwinner F1c100s رو نام برد که توی اینترنت در موردشون مطالبی هم وجود داره.

اما بعد گفتم بزار یه بررسی بکنم و ببینم که آیا خود esp هم این نکته رو گوشزد کرده یا نه که دیدم بله! خودش هم کاملا واقف و تسلیم هست.

یه سر به این لینک بزنید که مال خود شرکت esp هست و درحقیقت کتابخونه ای هست که شما ازش توی کدتون استفاده کردید


اینجا مشخصا گفته که استفاده از تصاویر با فرمت YUV یا RGB پردازش سنگینی روی ماژول قرار میده حتی ممکنه برخی مواقع تصویر از دست بره (یا همون خراب شدن تصویر)

البته شاید اگر تصویر رو با فرمت دیگه ای دریافت کنید و یا بیشتر بررسی بکنید بتونید یه خروجی از همین esp بگیرید ، اما فکر میکنم وجود دوربین صرفا برای عکس گرفتن یا فیلم با رزولویشن پایین کارآمد باشه

در نهایت توی کد فعلی خیلی دنبال مشکل نگردید. باید بیشتر روی بحث فرمت تصویر و نحوه ذخیره سازی و تبدیل و … تمرکز کنید

پیشنهاد میکنم یه نگاهی هم به این مطلب بندازید چون مسائل مرتبطی با همین نکاتی که گفتم داره
https://sisoog.com/ساخت-آیفون-تصویری-قسمت-دوم/

1 پسندیده