My idea is to use ESP32CAM for image processing projects. Since the ESP32 core is not powerful enough, I am planning to send the video (as images) from ESP32CAM into my python flask server and perform image processing over there using openCV.
I am aware that ESP32CAM is not powerful enough to stream video live into my cloud server, so I will be doing it image by image. Right now I have used the below code to get things working
Code: Select all
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#include "esp_camera.h"
const char* ssid = "CircuitDigest";
const char* password = "nnnnnn";
String serverName = "circuitdigestxxxxx.pythonanywhere.com"; // Replace with your PythonAnywhere domain
String serverPath = "/receive_image"; // Adjust path based on your Flask route
const int serverPort = 443; // Server port for HTTPS
int count = 0;
WiFiClientSecure client;
// Camera GPIO pins - adjust based on your ESP32-CAM board
#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 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
void setup() {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("ESP32-CAM IP Address: ");
Serial.println(WiFi.localIP());
// Configure camera
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.pixel_format = PIXFORMAT_GRAYSCALE;
if(psramFound()){
config.frame_size = FRAMESIZE_96X96;
config.jpeg_quality = 20; // Lower number means higher quality (0-63)
config.fb_count = 2;
Serial.printf("PSRAM found");
} else {
config.frame_size = FRAMESIZE_CIF;
config.jpeg_quality = 12; // Lower number means higher quality (0-63)
config.fb_count = 1;
}
// Initialize camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
delay(1000);
ESP.restart();
}
// Initial photo send
sendPhoto();
}
void loop() {
// Example: Send photo every 30 seconds
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
const int timerInterval = 10000;
if (currentMillis - previousMillis >= timerInterval) {
Serial.println("Lets send next image..");
sendPhoto();
previousMillis = currentMillis;
}
}
String sendPhoto() {
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
return "Camera capture failed";
}
Serial.println("Connecting to server: " + serverName);
client.setInsecure(); // Skip certificate validation (for simplicity, consider security implications in a production environment)
if (client.connect(serverName.c_str(), serverPort)) {
Serial.println("Connection successful!");
count=count+1;
Serial.println(count);
// Generate a unique filename using the current timestamp
//String filename = "esp32-cam-" + String(count) + ".jpg";
String filename = "esp32-cam-image.jpg";
String head = "--RandomNerdTutorials\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"" + filename + "\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--RandomNerdTutorials--\r\n";
uint32_t imageLen = fb->len;
uint32_t extraLen = head.length() + tail.length();
uint32_t totalLen = imageLen + extraLen;
// Send HTTP POST request with multipart/form-data
client.println("POST " + serverPath + " HTTP/1.1");
client.println("Host: " + serverName);
client.println("Content-Length: " + String(totalLen));
client.println("Content-Type: multipart/form-data; boundary=RandomNerdTutorials");
client.println();
client.print(head);
// Send image data in chunks
uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
for (size_t n = 0; n < fbLen; n = n + 1024) {
if (n + 1024 < fbLen) {
client.write(fbBuf, 1024);
fbBuf += 1024;
} else {
size_t remainder = fbLen % 1024;
client.write(fbBuf, remainder);
}
}
client.print(tail);
// Clean up
esp_camera_fb_return(fb);
// Wait for server response
String response;
long startTime = millis();
while (client.connected() && millis() - startTime < 10000) {
if (client.available()) {
char c = client.read();
response += c;
}
}
// Print server response
Serial.println(response);
client.stop();
return response;
} else {
Serial.println("Connection to server failed");
return "Connection to server failed";
}
}
On my flask server side I am saving the image using the below code
Code: Select all
# Ensure the 'mysite/static' directory exists
UPLOAD_FOLDER = 'mysite/static/'
if not os.path.exists(UPLOAD_FOLDER):
os.makedirs(UPLOAD_FOLDER)
# Path to save the image
IMAGE_FILE_PATH = os.path.join(UPLOAD_FOLDER, 'received_image.jpg')
@app.route('/mysite/static/<filename>')
def uploaded_file(filename):
return send_from_directory(UPLOAD_FOLDER, filename)
@app.route('/receive_image', methods=['POST'])
def receive_image():
if 'imageFile' not in request.files:
return jsonify({'error': 'No image file provided'}), 400
imageFile = request.files['imageFile']
if imageFile.filename == '':
return jsonify({'error': 'No selected file'}), 400
# Save the file to the specified directory
file_path = os.path.join(UPLOAD_FOLDER, imageFile.filename)
imageFile.save(file_path)
return jsonify({'message': 'Image received and saved successfully'}), 200
I have tried capturing images in grayscale but that did not improve the speed
I also tried reducing image size to 96x96 but then the code stopped working with error shown below
Code: Select all
ESP32-CAM IP Address: 192.168.29.178
PSRAM foundConnecting to server: circuitdigest.pythonanywhere.com
Connection successful!
1
[ 19876][E][ssl_client.cpp:37] _handle_error(): [send_ssl_data():382]: (-80) UNKNOWN ERROR CODE (0050)
Lets send next image..
Connecting to server: circuitdigest.pythonanywhere.com
Connection successful!
2
[ 24205][E][ssl_client.cpp:37] _handle_error(): [send_ssl_data():382]: (-80) UNKNOWN ERROR CODE (0050)
Lets send next image..
Connecting to server: circuitdigest.pythonanywhere.com