Сжатие изображения в оттенках серого с помощью ESP32-S3-WROOM Freenove
У меня есть модуль ESP32-S3-WROOM от Freenove, в котором есть камера и модуль карты micro SD. Я могу сделать снимок в формате PIXELFORMAT_JPEG.
Однако, когда я меняю формат пикселей на «PIXELFORMAT_GRAYSCALE», модуль захватывает необработанные данные (1 байт для каждого пикселя), что составляет константу 480 КБ для SVGA (600x800).
Как сжать эти необработанные данные в формат jpg? Я также попробовал сохранить фотографию в формате «.jpg». файл, однако это не сработало.
Это мой код захвата:
/********************************* *************************************
Имя файла: Камера и SD-карта.
Описание: Используйте встроенные кнопки, чтобы сделать фотографии и сохранить их на SD-карту.
Автор: freenove.com.
Модификация: 2022/11/02
**************************************************** ********************/
#include "esp_camera.h"
#define CAMERA_MODEL_ESP32S3_EYE
#include "camera_pins.h"
#include "ws2812.h"
#include "sd_read_write.h"
#define BUTTON_PIN 0
void setup() {
Serial.begin(500000);
Serial.setDebugOutput(false);
Serial.println();
pinMode(BUTTON_PIN, INPUT_PULLUP);
ws2812Init();
sdmmcInit();
//removeDir(SD_MMC, "/camera");
createDir(SD_MMC, "/camera");
listDir(SD_MMC, "/camera", 0);
if(cameraSetup()==1){
ws2812SetColor(2);
}
else{
ws2812SetColor(1);
return;
}
}
void loop() {
if (digitalRead(BUTTON_PIN)==LOW) {
delay(20);
if (digitalRead(BUTTON_PIN)==LOW) {
ws2812SetColor(3);
while (digitalRead(BUTTON_PIN)==LOW);
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if (fb != NULL) {
int photo_index = readFileNum(SD_MMC, "/camera");
if (photo_index!=-1) {
String path = "/camera/" + String(photo_index) +".jpg";
Serial.println(fb->len);
writejpg(SD_MMC, path.c_str(), fb->buf, fb->len);
}
esp_camera_fb_return(fb);
}
else {
Serial.println("Camera capture failed.");
}
ws2812SetColor(2);
}
}
}
int cameraSetup(void) {
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_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_SVGA;
config.pixel_format = PIXFORMAT_GRAYSCALE; // для потоковой передачи
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 20;
config.fb_count = 1;
// если присутствует микросхема PSRAM, инициализация с разрешением UXGA и более высоким качеством JPEG
// для большего заранее выделенного буфера кадра.
if (psramFound()) {
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Ограничиваем размер кадра, когда PSRAM недоступен
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
// инициализация камеры
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return 0;
}
sensor_t * s = esp_camera_sensor_get();
// начальные датчики перевернуты вертикально, а цвета немного насыщены
s->set_vflip(s, 1); // переворачиваем его обратно
s->set_brightness(s, 1); // немного увеличить яркость
s->set_saturation(s, 0); // уменьшаем насыщенность
Serial.println("Camera configuration complete!");
return 1;
}
Это функция writejpg()
, использованная во фрагменте кода:
void writejpg(fs::FS &fs, const char * path, const uint8_t *buf, size_t size){
File file = fs.open(path, FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
ws2812SetColor(1);
delay(100);
return;
}
file.write(buf, size);
// Define the chunk size
const size_t chunkSize = 2048;
// Write to serial in chunks
for (size_t i = 0; i < size; i += chunkSize) {
// Calculate the size of the current chunk
size_t currentChunkSize = ((i + chunkSize) <= size) ? chunkSize : (size - i);
// Write the current chunk in hex format to serial
for (size_t j = 0; j < currentChunkSize; ++j) {
Serial.printf("%02X ", buf[i + j]);
// if ((j + 1) % 128 == 0) { // Print a new line every 16 bytes for better readability
// Serial.println();
// }
}
}
Serial.println();
Serial.printf("Saved file to path: %s\r\n", path);
}
Эта функция также распечатывает шестнадцатеричные значения изображения для отладки.
Итак, есть ли у вас идеи, как сжать это изображение в файл jpg?
@BehicMV, 👍0
1 ответ
Лучший ответ:
Мне только что удалось решить эту проблему с помощью функции frame2jpg()
.
Надеюсь, это поможет!
- Камера esp32 и датчик PIR
- Видеокамера ESP32 и пробуждение от глубокого сна
- ESP32 сохранение данных на SD-карту в формате .csv не форматируется правильно
- Как использовать внешний кристалл 32 кГц для ESP32 S3 с Arduino IDE?
- Невозможно установить библиотеку esp_camera
- Подключение к WiFi на ESP32 с использованием учетных данных с SD-карты
- Как считывать аналоговое значение на ESP32-CAM с включенным считывателем SD-карт?
- Не удалось установить SD-карту с Waveshare ESP32 с использованием Arduino IDE
Возможно, вы хотели бы расширить этот ответ, включив в него немного больше деталей?, @sempaiscuba
Конечно! Существует код [to_jpg()](https://github.com/espressif/esp32-camera/blob/master/conversions/to_jpg.cpp), который находится в репозитории esp32 github. В нем вы можете найти функцию «frame2jpg()». Также использование будет похоже на «frame2jpg(fb,quality, &jpg_buf, &jpg_buf_len)», оно вернет логическое значение, указывающее на успешную ситуацию. Если вы не понимаете, я здесь, чтобы помочь!, @BehicMV