Hello, I am working on a project where I need to take a picture, save it on my micro SD, and split the original image into 5 little squares.
But I get a "camera capture failed" with my code and I don't know why.
Can you help me pls ?
#include "esp_camera.h"
#include <WiFi.h>
#include <WebServer.h>
#include "Arduino.h"
#include "FS.h"
#include "SD_MMC.h"
#include "esp32-hal-ledc.h"
// Wi-Fi credentials
const char* ssid = "Khu S";
const char* password = "khu@s2022";
#define CAMERA_MODEL_AI_THINKER // Has PSRAM
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 2
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define LED_GPIO_NUM 4
#define LED_LEDC_CHANNEL 2
// Create a web server on port 80
WebServer server(80);
void handleRoot() {
Serial.println("Handle root request");
server.send(200, "text/html", "<form action=\"/capture\" method=\"POST\"><button type=\"submit\">Capture Image</button></form>");
}
camera_fb_t* crop_image(camera_fb_t* src_fb, int x_min, int y_min, int x_max, int y_max) {
int src_width = src_fb->width;
int src_height = src_fb->height;
// Assurez-vous que les valeurs de recadrage ne dépassent pas les dimensions de l'image capturée
if (x_min < 0) x_min = 0;
if (y_min < 0) y_min = 0;
if (x_max > src_width) x_max = src_width;
if (y_max > src_height) y_max = src_height;
int crop_width = x_max - x_min;
int crop_height = y_max - y_min;
Serial.printf("Cropping image: (%d, %d) to (%d, %d)\n", x_min, y_min, x_max, y_max);
uint8_t* src_data = src_fb->buf;
camera_fb_t* cropped_fb = (camera_fb_t*)malloc(sizeof(camera_fb_t));
if (!cropped_fb) {
Serial.println("Failed to allocate memory for cropped image");
return NULL;
}
cropped_fb->format = PIXFORMAT_RGB888;
cropped_fb->width = crop_width;
cropped_fb->height = crop_height;
cropped_fb->len = crop_width * crop_height * 3;
cropped_fb->buf = (uint8_t*)malloc(cropped_fb->len);
if (!cropped_fb->buf) {
Serial.println("Failed to allocate memory for cropped image buffer");
free(cropped_fb);
return NULL;
}
for (int y = y_min; y < y_max; y++) {
for (int x = x_min; x < x_max; x++) {
int src_index = (y * src_width + x) * 3;
int cropped_index = ((y - y_min) * crop_width + (x - x_min)) * 3;
cropped_fb->buf[cropped_index] = src_data[src_index];
cropped_fb->buf[cropped_index + 1] = src_data[src_index + 1];
cropped_fb->buf[cropped_index + 2] = src_data[src_index + 2];
}
}
Serial.println("Cropping completed");
return cropped_fb;
}
void enable_led(bool en) {
if (en) {
ledcWrite(LED_LEDC_CHANNEL, 100);
Serial.println("LED enabled");
} else {
ledcWrite(LED_LEDC_CHANNEL, 0);
Serial.println("LED disabled");
}
}
void handleCapture() {
camera_fb_t * fb = NULL;
Serial.println("Capture request received");
enable_led(true);
vTaskDelay(150 / portTICK_PERIOD_MS);
fb = esp_camera_fb_get();
enable_led(false);
if (!fb) {
Serial.println("Camera capture failed");
server.send(500, "text/plain", "Camera capture failed");
return;
}
Serial.println("Camera capture successful");
// Save the original image to the SD card
String path = "/captured_image.jpg";
fs::FS &fs = SD_MMC;
File file = fs.open(path.c_str(), FILE_WRITE);
if (!file) {
Serial.println("Failed to open file for writing");
server.send(500, "text/plain", "Failed to open file for writing");
esp_camera_fb_return(fb);
return;
}
file.write(fb->buf, fb->len);
file.close();
Serial.println("Image saved to SD card");
// Coordinates for the cropped area (100x100 pixels at the center)
const int crop_width = 100;
const int crop_height = 100;
const int crop_x = (fb->width - crop_width) / 2;
const int crop_y = (fb->height - crop_height) / 2;
Serial.printf("Cropping area: (%d, %d) to (%d, %d)\n", crop_x, crop_y, crop_x + crop_width, crop_y + crop_height);
uint8_t* rgb_buf = (uint8_t*)malloc(fb->width * fb->height * 3); // allocate memory for the RGB image
if (!rgb_buf) {
Serial.println("Memory allocation failed for RGB image");
server.send(500, "text/plain", "Memory allocation failed");
esp_camera_fb_return(fb);
return;
}
if (!fmt2rgb888(fb->buf, fb->len, PIXFORMAT_JPEG, rgb_buf)) {
Serial.println("JPEG decoding failed");
server.send(500, "text/plain", "JPEG decoding failed");
free(rgb_buf);
esp_camera_fb_return(fb);
return;
}
Serial.println("JPEG decoding successful");
camera_fb_t* cropped_fb = crop_image(fb, crop_x, crop_y, crop_x + crop_width, crop_y + crop_height);
if (!cropped_fb) {
Serial.println("Failed to crop image");
server.send(500, "text/plain", "Failed to crop image");
free(rgb_buf);
esp_camera_fb_return(fb);
return;
}
Serial.println("Cropping successful");
size_t jpeg_buf_len = 0;
uint8_t *jpeg_buf = NULL;
if (!fmt2jpg(cropped_fb->buf, cropped_fb->len, crop_width, crop_height, PIXFORMAT_RGB888, 80, &jpeg_buf, &jpeg_buf_len)) {
Serial.println("JPEG compression failed");
server.send(500, "text/plain", "JPEG compression failed");
free(cropped_fb->buf);
free(cropped_fb);
free(rgb_buf);
esp_camera_fb_return(fb);
return;
}
Serial.println("JPEG compression successful for cropped image");
String crop_path = "/cropped_image.jpg";
file = fs.open(crop_path.c_str(), FILE_WRITE);
if (!file) {
Serial.println("Failed to open cropped image file for writing");
server.send(500, "text/plain", "Failed to open cropped image file for writing");
free(jpeg_buf);
free(cropped_fb->buf);
free(cropped_fb);
free(rgb_buf);
esp_camera_fb_return(fb);
return;
}
file.write(jpeg_buf, jpeg_buf_len);
file.close();
Serial.println("Cropped image saved to SD card");
free(jpeg_buf);
free(cropped_fb->buf);
free(cropped_fb);
free(rgb_buf);
String htmlBuffer = "<div>Original Image:<br><img src=\"/captured_image.jpg\" /></div>";
htmlBuffer += "<div>Cropped Image:<br><img src=\"/cropped_image.jpg\" /></div>";
server.send(200, "text/html", htmlBuffer);
Serial.println("HTML response sent");
esp_camera_fb_return(fb);
Serial.println("Frame buffer returned to driver");
}
void handleFileRead(String path) {
Serial.println("handleFileRead: " + path);
if (path.endsWith("/")) {
path += "index.htm";
}
String contentType = "text/html";
if (path.endsWith(".jpg")) contentType = "image/jpeg";
if (SD_MMC.exists(path)) {
File file = SD_MMC.open(path, FILE_READ);
server.streamFile(file, contentType);
file.close();
Serial.println("File served: " + path);
} else {
Serial.println("File not found: " + path);
server.send(404, "text/plain", "File Not Found");
}
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println();
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.frame_size = FRAMESIZE_SVGA; // Reduced frame size
config.pixel_format = PIXFORMAT_JPEG; // Directly use JPEG
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
if (psramFound()) {
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
config.fb_location = CAMERA_FB_IN_DRAM;
}
Serial.println("Initializing camera...");
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x\n", err);
return;
}
Serial.println("Camera initialized");
if (!SD_MMC.begin()) {
Serial.println("SD Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD Card attached");
return;
}
Serial.println("SD Card initialized");
WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi...");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.on("/", HTTP_GET, handleRoot);
server.on("/capture", HTTP_POST, handleCapture);
server.onNotFound([]() {
handleFileRead(server.uri());
});
server.begin();
Serial.println("HTTP server started");
}
void loop() {
server.handleClient();
}