В текущей реализации веб-сервер Flask настроен на получение изображений JPEG с камеры ESP32. Сервер использует Tesseract OCR для извлечения текста из изображений, а затем преобразует этот текст в речь с помощью библиотеки gTTS. Однако когда ESP32 пытается отправить изображения на сервер, он постоянно получает код ответа HTTP 400, указывающий на «неверный запрос». Эта проблема предполагает, что сервер неправильно обрабатывает входящие данные изображения.
КОД PYTHON:
from flask import Flask, request, jsonify, send_file, render_template
import pytesseract
from PIL import Image
import numpy as np
import cv2
from gtts import gTTS
import os
import time
app = Flask(__name__)
# Tesseract OCR path (Adjust this for your system)
pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe'
@app.route('/')
def index():
return render_template('index.html') # Serve the HTML page for uploading images
@app.route('/upload', methods=['POST'])
def upload_image():
print("Files received:", request.files) # Log received files
try:
if 'image' not in request.files:
return jsonify({'error': 'No image uploaded'}), 400
file = request.files['image']
if file.filename == '':
return jsonify({'error': 'No selected file'}), 400
# Check if the uploaded file is a JPEG image
if not file.content_type in ['image/jpeg', 'image/jpg']:
return jsonify({'error': 'File type not supported. Please upload a JPEG image.'}), 400
try:
# Open the image file
image = Image.open(file)
# Convert to JPEG format
image = image.convert('RGB')
jpeg_image_path = "uploaded_image.jpeg"
image.save(jpeg_image_path, "JPEG") # Save as JPEG
except Exception as e:
return jsonify({'error': f'Failed to process image: {str(e)}'}), 400
# Load the JPEG image for OCR processing
open_cv_image = cv2.imread(jpeg_image_path)
start_time_ocr = time.time()
extracted_text = pytesseract.image_to_string(open_cv_image)
end_time_ocr = time.time()
ocr_time = end_time_ocr - start_time_ocr
if not extracted_text.strip():
return jsonify({'error': 'No text could be extracted from the image'}), 400
start_time_tts = time.time()
tts = gTTS(extracted_text)
audio_file = "speech.mp3"
tts.save(audio_file)
end_time_tts = time.time()
tts_time = end_time_tts - start_time_tts
return jsonify({
'extracted_text': extracted_text,
'ocr_time': ocr_time,
'tts_time': tts_time,
'audio_url': '/play_audio',
'message': 'Audio generated successfully. Click to play.'
}), 200
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.route('/play_audio')
def play_audio():
try:
return send_file("speech.mp3", as_attachment=False)
except Exception as e:
return jsonify({'error': str(e)}), 500
@app.after_request
def after_request(response):
# Remove the audio file after serving
try:
if os.path.exists("speech.mp3"):
os.remove("speech.mp3") # Remove the file after serving
if os.path.exists("uploaded_image.jpeg"):
os.remove("uploaded_image.jpeg") # Remove the uploaded image after processing
except Exception as e:
print(f'Error removing file: {e}') # Log the error
return response
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
КОД ESP32
#include "esp_camera.h"
#include "WiFi.h"
#include "HTTPClient.h"
#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM
#include "camera_pins.h"
unsigned long lastCaptureTime = 0; // Last shooting time
int imageCount = 1; // File Counter
bool camera_sign = false; // Check camera status
const char* ssid = "PLDTHOMEFIBRazyjK"; // Replace with your network SSID
const char* password = "PLDTWIFIDCF6k!"; // Replace with your network password
const char* serverUrl = "http://192.168.1.29:5000/upload"; // Replace with your server URL
void setup() {
Serial.begin(115200);
while (!Serial); // Wait for the serial monitor to open
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to WiFi");
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_UXGA;
config.pixel_format = PIXFORMAT_JPEG; // for streaming
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 12;
config.fb_count = 1;
if (config.pixel_format == PIXFORMAT_JPEG) {
if (psramFound()) {
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
} else {
// Limit the frame size when PSRAM is not available
config.frame_size = FRAMESIZE_UXGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
} else {
config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
config.fb_count = 2;
#endif
}
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
camera_sign = true; // Camera initialized
Serial.println("Camera initialized successfully");
}
void sendPhoto(const char* filename, uint8_t* buf, size_t len) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(serverUrl); // Specify the URL
http.addHeader("Content-Type", "image/jpeg"); // Specify content-type header
// Send the HTTP POST request
int httpResponseCode = http.POST(buf, len);
if (httpResponseCode > 0) {
Serial.printf("HTTP Response code: %d\n", httpResponseCode);
} else {
Serial.printf("HTTP POST failed: %s\n", http.errorToString(httpResponseCode).c_str());
}
// Free resources
http.end();
} else {
Serial.println("WiFi not connected");
}
}
void loop() {
if (camera_sign) {
unsigned long now = millis();
// If it has been more than 10 seconds since the last shot, take a picture and send it
if ((now - lastCaptureTime) >= 10000) {
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("Failed to get camera frame buffer");
return;
}
char filename[32];
sprintf(filename, "/image.jpg");
Serial.printf("Image Size: %zu bytes\n", fb->len); // Debug image size
sendPhoto(filename, fb->buf, fb->len);
Serial.printf("Sent picture: %s\r\n", filename);
imageCount++;
lastCaptureTime = now;
// Release image buffer
esp_camera_fb_return(fb);
}
}
}
ESP32 должен успешно отправить изображения JPEG на сервер Flask, который затем обработает эти изображения, не возвращая ошибку 400.
Вывод в последовательном формате esp32 монитор
HTTP Response code: 400
Sent picture: /image.jpg
Image Size: 108403 bytes
HTTP Response code: 400
Sent picture: /image.jpg
Image Size: 110773 bytes
Вывод в Python
192.168.1.43 - - [20/Oct/2024 09:11:13] "POST /upload HTTP/1.1" 400 -
192.168.1.43 - - [20/Oct/2024 09:11:30] "POST /upload HTTP/1.1" 400 -
192.168.1.43 - - [20/Oct/2024 09:11:46] "POST /upload HTTP/1.1" 400 -
192.168.1.43 - - [20/Oct/2024 09:11:54] "POST /upload HTTP/1.1" 400 -
192.168.1.43 - - [20/Oct/2024 09:12:07] "POST /upload HTTP/1.1" 400 -
192.168.1.43 - - [20/Oct/2024 09:12:20] "POST /upload HTTP/1.1" 400 -
Подробнее здесь: https://stackoverflow.com/questions/791 ... ctionality
Интеграция камеры XIAO ESP32S3 с Flask для функций оптического распознавания символов и TTS ⇐ Python
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Предварительная обработка изображений для оптического распознавания символов (pytesseract)
Anonymous » » в форуме Python - 0 Ответы
- 116 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Предварительная обработка изображений в Python для оптического распознавания символов
Anonymous » » в форуме Python - 0 Ответы
- 18 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Предварительная обработка изображений в Python для оптического распознавания символов
Anonymous » » в форуме Python - 0 Ответы
- 20 Просмотры
-
Последнее сообщение Anonymous
-