Caméra ESP32 S3 - Envoyer la vidéo en direct vers Python sur PC

L'ESP32 S3 est une petite carte. Elle peut très bien prendre des photos, mais elle ne peut pas reconnaître un visage, lire une plaque d'immatriculation ou trouver un chat dans l'image. Votre ordinateur peut faire tout cela facilement.

Alors on laisse chaque côté faire ce qu'il fait le mieux : l'ESP32 S3 envoie la vidéo en direct via WiFi, et un programme Python sur votre ordinateur la reçoit. Une fois l'image dans Python, vous pouvez en faire ce que vous voulez.

Le programme Python fait environ 20 lignes.

ESP32 S3 Camera - Send Live Video to Python on PC

Ce que vous allez construire :

  1. Une caméra ESP32 S3 qui envoie la vidéo en direct via WiFi
  2. Un court programme Python qui affiche la vidéo dans une fenêtre sur votre ordinateur
  3. Une touche pour enregistrer une image sous forme de fichier, quand vous le souhaitez
  4. Un second programme Python qui trouve les visages dans la vidéo, pour vous montrer comment aller plus loin

Matériel nécessaire

1×ESP32 S3 N16R8 OV5640 Camera
1×Alternativement: ESP32 S3 N16R8 OV2640 Camera
1×Câble USB Type-A vers Type-C (pour PC USB-A)
1×Câble USB Type-C vers Type-C (pour PC USB-C)
1×Optionnel: Connecteur d'alimentation DC
1×Recommandé: Screw Terminal Expansion Board for ESP32 S3
1×Recommandé: Breakout Expansion Board for ESP32 S3
1×Recommandé: Power Splitter for ESP32 S3

Ou vous pouvez acheter les kits suivants:

1×Kit de Capteurs DIYables (18 capteurs/écrans)
Divulgation : Certains des liens fournis dans cette section sont des liens affiliés Amazon. Nous pouvons recevoir une commission pour tout achat effectué via ces liens, sans coût supplémentaire pour vous. Nous vous remercions de votre soutien.

※ Note:

La carte caméra ESP32 S3 a 40 broches, mais le bornier à vis et la carte d'extension ont 44 broches. Elles fonctionnent quand même ensemble. Placez la carte caméra au centre de la carte à 44 broches, de sorte que 2 broches restent libres du côté gauche et 2 broches restent libres du côté droit.

Le bornier à vis vous permet de connecter des fils avec un tournevis, sans soudure. La carte d'extension vous donne des broches faciles à utiliser pour une breadboard.

Vous avez aussi besoin d'un ordinateur avec Python. Windows, Mac et Linux fonctionnent tous.

Comment ça fonctionne

L'ESP32 S3 envoie la vidéo de la même manière qu'une webcam, sous forme de flux MJPEG. C'est simplement une succession de nombreuses images JPEG.

La bonne nouvelle : Python comprend déjà ce format. La bibliothèque OpenCV ouvre la vidéo en une seule ligne, exactement comme elle ouvrirait un fichier vidéo ou une webcam USB :

camera = cv2.VideoCapture("http://192.168.0.2/stream")

Voici tout le trajet que parcourt une image :

ÉtapeOùCe qui se passe
1CaméraPrend une photo et l'encode en JPEG
2ESP32 S3Envoie le JPEG via WiFi
3Votre routeurLa transporte vers votre ordinateur
4PythonLa lit et la transforme en une image que vous pouvez utiliser
5Votre codeL'affiche, l'enregistre, ou cherche quelque chose dedans
How the Video Travels to Python

La carte possède aussi deux autres adresses, utiles pendant le développement :

AdresseCe qu'elle vous donne
http://<IP>/Une page web, pour tester la caméra d'abord dans un navigateur
http://<IP>/streamLa vidéo en direct. C'est celle que Python ouvre.
http://<IP>/photoUne seule image JPEG, si votre programme n'a besoin que d'une image

※ Note:

Testez toujours http://<IP>/ dans votre navigateur web avant de lancer Python. Si le navigateur affiche la vidéo, la carte fonctionne correctement, et tout problème après cela vient de la partie Python. Cette simple habitude fait gagner beaucoup de temps.

Schéma de câblage

Il n'y a pas de câblage dans ce projet. L'ESP32 S3 a seulement besoin d'alimentation et de WiFi.

ESP32 S3 Camera Python Wiring Diagram

Cette image a été créée avec Fritzing. Cliquez pour agrandir l'image.

※ Note:

Votre ordinateur et votre ESP32 S3 doivent être sur le même réseau WiFi. S'ils sont sur des réseaux différents, Python ne peut pas atteindre la carte.

Paramètres de l'Arduino IDE pour la caméra ESP32 S3

La caméra ne fonctionne pas avec les paramètres par défaut de l'Arduino IDE. Vous devez modifier certains éléments dans le menu Tools avant de téléverser le code.

Élément du menu ToolsSélectionnez ceci
BoardESP32S3 Dev Module
Flash Size16MB (128Mb)
PSRAMOPI PSRAM
Partition SchemeHuge APP (3MB No OTA/1MB SPIFFS)
CPU Frequency240MHz (WiFi)
USB ModeHardware CDC and JTAG
Upload ModeUART0 / Hardware CDC
Upload Speed921600
USB CDC On BootEnabled

Installer la bibliothèque DIYables ESP32 WebServer

  1. Ouvrez l'Arduino IDE.
  2. Cliquez sur l'icône Libraries dans la barre de gauche.
  3. Tapez DIYables ESP32 WebServer dans le champ de recherche.
  4. Trouvez la bibliothèque de DIYables.io et cliquez sur INSTALL.
  • Search for DIYables ESP32 WebServer created by DIYables.io and click the Install button.
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Library Manager
Type:
All
Topic:
All
DIYables ESP32 WebServer by DIYables.io
DIYables ESP32 WebServer library designed for ESP32 boards. It includes multi-page web server capabilities and WebSocket support for real-time communication, perfect for IoT projects and DIYables ESP32 boards. More info
1.0.1
INSTALL
Newbiely.ino
···
1 void setup() {
Output
Serial Monitor
Ln 1, Col 1
ESP32S3 Dev Module on COM15
1

Code ESP32 S3

Modifiez WIFI_SSID et WIFI_PASSWORD en haut. Rien d'autre n'a besoin d'être changé.

/* * Ce code ESP32 S3 a été développé par newbiely.fr * Ce code ESP32 S3 est mis à disposition du public sans aucune restriction. * Pour des instructions complètes et des schémas de câblage, veuillez visiter: * https://newbiely.fr/tutorials/esp32-s3/esp32-s3-camera-send-live-video-to-python-on-pc */ #include <WiFi.h> #include <DIYables_ESP32_WebServer.h> // DIYables ESP32 WebServer library #include "esp_camera.h" const char *WIFI_SSID = "YOUR_WIFI_SSID"; // CHANGE IT const char *WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"; // CHANGE IT // The picture size. Bigger is nicer, but slower over WiFi. // FRAMESIZE_QVGA (320x240) is the fastest, FRAMESIZE_SVGA (800x600) is the biggest useful one. #define FRAME_SIZE FRAMESIZE_VGA // 640x480 #define JPEG_QUALITY 12 // 0 to 63. A bigger number makes a smaller file. // Camera pins of the ESP32-S3-N16R8 camera board. // The same pins work for the OV2640, OV3660 and OV5640 versions. #define PWDN_GPIO_NUM -1 #define RESET_GPIO_NUM -1 #define XCLK_GPIO_NUM 15 #define SIOD_GPIO_NUM 4 #define SIOC_GPIO_NUM 5 #define Y9_GPIO_NUM 16 #define Y8_GPIO_NUM 17 #define Y7_GPIO_NUM 18 #define Y6_GPIO_NUM 12 #define Y5_GPIO_NUM 10 #define Y4_GPIO_NUM 8 #define Y3_GPIO_NUM 9 #define Y2_GPIO_NUM 11 #define VSYNC_GPIO_NUM 6 #define HREF_GPIO_NUM 7 #define PCLK_GPIO_NUM 13 DIYables_ESP32_WebServer server(80); // The text that separates one picture from the next one in the stream #define BOUNDARY "diyablesframe" const char INDEX_HTML[] = R"rawliteral( <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>ESP32 S3 Camera for Python</title> <style> body { background:#111; color:#eee; font-family:sans-serif; text-align:center; margin:0; padding:16px; } img { width:100%; max-width:640px; border-radius:8px; } code { background:#222; padding:2px 6px; border-radius:4px; } </style> </head> <body> <h2>ESP32 S3 Camera</h2> <p>The video below is the same one your Python code reads.</p> <img src="/stream"> <p>Address for Python: <code>/stream</code></p> </body> </html> )rawliteral"; // Returns the name of the camera sensor that is installed on the board const char *getSensorName(int pid) { switch (pid) { case OV2640_PID: return "OV2640 (2 MP, max UXGA 1600x1200)"; case OV3660_PID: return "OV3660 (3 MP, max QXGA 2048x1536)"; case OV5640_PID: return "OV5640 (5 MP, max QSXGA 2592x1944)"; default: return "Unknown sensor"; } } bool initCamera() { 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; config.frame_size = FRAME_SIZE; config.jpeg_quality = JPEG_QUALITY; config.fb_count = 1; config.fb_location = CAMERA_FB_IN_DRAM; config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; if (psramFound()) { config.fb_location = CAMERA_FB_IN_PSRAM; config.fb_count = 2; // two buffers, so the video is smoother config.grab_mode = CAMERA_GRAB_LATEST; } else { config.frame_size = FRAMESIZE_QVGA; Serial.println("WARNING: PSRAM not found. Please set PSRAM to OPI PSRAM in the Tools menu."); } esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { Serial.printf("Camera init failed with error 0x%x\n", err); return false; } sensor_t *s = esp_camera_sensor_get(); Serial.printf("Camera sensor: %s\n", getSensorName(s->id.PID)); // Each sensor needs slightly different settings switch (s->id.PID) { case OV2640_PID: s->set_vflip(s, 0); s->set_hmirror(s, 0); break; case OV3660_PID: s->set_vflip(s, 1); // the OV3660 image is upside down by default s->set_brightness(s, 1); // make the image a little brighter s->set_saturation(s, -2); // make the colors a little softer break; case OV5640_PID: s->set_vflip(s, 0); s->set_hmirror(s, 0); break; default: break; } return true; } // Shows a small web page, so you can test the camera in a browser first void handleHome(WiFiClient &client, const String &method, const String &request, const QueryParams &params, const String &jsonData) { server.sendResponse(client, INDEX_HTML, "text/html"); } // Sends one JPEG picture. Good for Python code that wants single images. void handlePhoto(WiFiClient &client, const String &method, const String &request, const QueryParams &params, const String &jsonData) { camera_fb_t *fb = esp_camera_fb_get(); if (!fb) { Serial.println("Photo capture failed"); server.sendResponse(client, "Photo capture failed", "text/plain"); return; } client.print("HTTP/1.1 200 OK\r\n"); client.print("Content-Type: image/jpeg\r\n"); client.printf("Content-Length: %u\r\n", fb->len); client.print("Connection: close\r\n\r\n"); client.write(fb->buf, fb->len); esp_camera_fb_return(fb); } // Sends the live video. This is the address the Python code opens. void handleStream(WiFiClient &client, const String &method, const String &request, const QueryParams &params, const String &jsonData) { Serial.println("A program opened the video stream"); client.print("HTTP/1.1 200 OK\r\n"); client.print("Content-Type: multipart/x-mixed-replace; boundary=" BOUNDARY "\r\n"); client.print("Access-Control-Allow-Origin: *\r\n"); client.print("Connection: close\r\n\r\n"); while (client.connected()) { camera_fb_t *fb = esp_camera_fb_get(); if (!fb) { Serial.println("Frame capture failed"); break; } size_t len = fb->len; client.print("--" BOUNDARY "\r\n"); client.print("Content-Type: image/jpeg\r\n"); client.printf("Content-Length: %u\r\n\r\n", len); size_t sent = client.write(fb->buf, len); client.print("\r\n"); esp_camera_fb_return(fb); if (sent != len) { // the program on the PC stopped break; } } Serial.println("The video stream was closed"); } void setup() { Serial.begin(115200); delay(1000); if (!initCamera()) { Serial.println("Stopped"); while (true) delay(1000); } WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); Serial.print("Connecting to WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); WiFi.setSleep(false); // keep WiFi fast for the video server.addRoute("/", handleHome); server.addRoute("/photo", handlePhoto); server.addRoute("/stream", handleStream); server.begin(); Serial.print("Camera is ready. Put this address into your Python code: http://"); Serial.print(WiFi.localIP()); Serial.println("/stream"); } void loop() { server.handleClient(); }

Étapes rapides

  • Nouveau sur l'ESP32 S3 ? Suivez d'abord notre guide ESP32 S3 - Premiers pas.
  • Installez la bibliothèque DIYables ESP32 WebServer.
  • Copiez le code ci-dessus et collez-le dans l'Arduino IDE.
  • Changez WIFI_SSID et WIFI_PASSWORD pour votre propre WiFi.
  • Changez les paramètres dans le menu Tools. Voir le tableau ci-dessus.
  • Compilez et téléversez le code sur la carte ESP32 S3 en cliquant sur le bouton Upload dans l'Arduino IDE.
Arduino IDE Upload Code
  • Ouvrez le Serial Monitor dans l'Arduino IDE.
How to open serial monitor on Arduino IDE
  • Appuyez une fois sur le bouton RESET.
  • Notez l'adresse que le Serial Monitor affiche. Vous en aurez besoin dans le code Python.
  • Ouvrez cette adresse dans votre navigateur web et vérifiez que vous voyez la vidéo.

Serial Monitor

∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32S3 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32S3 Dev Module' on 'COM15')
New Line
9600 baud
[2026-09-28 16:00:01] Camera sensor: OV5640 (5 MP, max QSXGA 2592x1944) [2026-09-28 16:00:01] Connecting to WiFi... [2026-09-28 16:00:04] Camera is ready. Put this address into your Python code: http://192.168.0.2/stream [2026-09-28 16:00:31] A program opened the video stream [2026-09-28 16:01:58] The video stream was closed
Ln 11, Col 1
ESP32S3 Dev Module on COM15
2

※ Note:

La ligne A program opened the video stream apparaît lorsque votre code Python démarre. Si vous ne la voyez jamais, Python n'atteint pas la carte, et le problème vient de l'adresse ou du réseau.

Installer Python et OpenCV

  1. Installez Python depuis python.org. Sous Windows, cochez la case Add python.exe to PATH pendant l'installation.
  2. Ouvrez un terminal, et installez OpenCV avec une seule commande :
pip install opencv-python
  1. Vérifiez que cela a fonctionné :
python -c "import cv2; print(cv2.__version__)"

Vous devriez voir un numéro de version, par exemple 4.12.0.

※ Note:

OpenCV est la bibliothèque la plus utilisée au monde pour travailler avec des images. Elle est gratuite, et elle sait déjà lire un flux MJPEG, donc vous n'avez rien à écrire vous-même concernant le JPEG ou le WiFi.

Code Python - Exemple 1 : Afficher la vidéo

Voici le programme complet. Il ouvre la vidéo, l'affiche dans une fenêtre, et enregistre une image lorsque vous appuyez sur la touche s.

/* * Ce code ESP32 S3 a été développé par newbiely.fr * Ce code ESP32 S3 est mis à disposition du public sans aucune restriction. * Pour des instructions complètes et des schémas de câblage, veuillez visiter: * https://newbiely.fr/tutorials/esp32-s3/esp32-s3-camera-send-live-video-to-python-on-pc */ import cv2 CAMERA_URL = "http://192.168.0.2/stream" # CHANGE IT to the address of your ESP32 S3 camera = cv2.VideoCapture(CAMERA_URL) if not camera.isOpened(): print("Cannot open the camera.") print("Check the address, and try it in your web browser first.") exit() print("The video is open.") print("Press ESC to stop, or press s to save a picture.") photo_number = 1 while True: ok, frame = camera.read() if not ok: print("No picture. Is the ESP32 S3 still on?") break # frame is a normal OpenCV picture. You can do anything you like with it here. cv2.imshow("ESP32 S3 Camera", frame) key = cv2.waitKey(1) & 0xFF if key == 27: # the ESC key break if key == ord("s"): file_name = "photo_%05d.jpg" % photo_number cv2.imwrite(file_name, frame) print("Saved", file_name) photo_number += 1 camera.release() cv2.destroyAllWindows() print("Stopped.")

Changez une ligne pour indiquer l'adresse de votre Serial Monitor :

CAMERA_URL = "http://192.168.0.2/stream" # CHANGE IT

Étapes rapides

  • Enregistrez le code sous le nom camera_pc_view.py sur votre ordinateur.
  • Changez CAMERA_URL pour l'adresse de votre carte.
  • Ouvrez un terminal dans le même dossier et exécutez-le :
python camera_pc_view.py
  • Une fenêtre s'ouvre et affiche la vidéo en direct.
  • Appuyez sur s pour enregistrer une image. Appuyez sur ESC pour arrêter.
The video is open. Press ESC to stop, or press s to save a picture. Saved photo_00001.jpg Saved photo_00002.jpg Stopped.
ESP32 S3 Camera Video in a Python Window

La ligne importante

Tout ce qui est intéressant se passe ici :

ok, frame = camera.read()

frame est maintenant l'image, sous forme d'un tableau de nombres. C'est le même type d'image que celui utilisé par tous les exemples OpenCV sur internet. Donc à partir de cette ligne, vous ne faites plus un projet ESP32. Vous faites un projet de vision par ordinateur classique, et tous les tutoriels, tous les exemples et toutes les bibliothèques d'IA fonctionnent avec.

Code Python - Exemple 2 : Trouver des visages

Pour montrer ce que signifie « vous pouvez maintenant tout faire », voici le même programme avec la détection de visages. Il ne nécessite aucun téléchargement supplémentaire, car OpenCV inclut déjà un détecteur de visages.

/* * Ce code ESP32 S3 a été développé par newbiely.fr * Ce code ESP32 S3 est mis à disposition du public sans aucune restriction. * Pour des instructions complètes et des schémas de câblage, veuillez visiter: * https://newbiely.fr/tutorials/esp32-s3/esp32-s3-camera-send-live-video-to-python-on-pc */ import cv2 CAMERA_URL = "http://192.168.0.2/stream" # CHANGE IT to the address of your ESP32 S3 # OpenCV brings a ready-made face finder with it. Nothing to download. face_finder = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") camera = cv2.VideoCapture(CAMERA_URL) if not camera.isOpened(): print("Cannot open the camera.") print("Check the address, and try it in your web browser first.") exit() print("Looking for faces. Press ESC to stop.") while True: ok, frame = camera.read() if not ok: print("No picture. Is the ESP32 S3 still on?") break # The face finder works on a black and white picture gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_finder.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60)) # Draw a green box around every face for (x, y, width, height) in faces: cv2.rectangle(frame, (x, y), (x + width, y + height), (0, 255, 0), 2) cv2.putText(frame, "%d face(s)" % len(faces), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2) cv2.imshow("ESP32 S3 Camera - Faces", frame) if cv2.waitKey(1) & 0xFF == 27: # the ESC key break camera.release() cv2.destroyAllWindows() print("Stopped.")

Seulement trois choses ont été ajoutées :

# 1. Load the ready-made face finder face_finder = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") # 2. Look for faces in the picture gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = face_finder.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(60, 60)) # 3. Draw a green box around every face for (x, y, width, height) in faces: cv2.rectangle(frame, (x, y), (x + width, y + height), (0, 255, 0), 2)

Exécutez-le de la même manière :

python camera_pc_face.py
ESP32 S3 Camera Face Detection in Python

※ Note:

Ce détecteur de visages est ancien et simple, mais il est rapide et ne nécessite rien de plus. Il ne trouve que les visages qui regardent directement la caméra. Pour de meilleurs résultats, voir la liste ci-dessous.

Que pouvez-vous faire d'autre en Python ?

Une fois que l'image est dans frame, la partie ESP32 S3 de votre projet est terminée. Voici ce que les gens ajoutent habituellement ensuite :

Ce que vous voulezCe qu'il faut utiliserNiveau de difficulté
Trouver des visagesOpenCV, déjà installéFacile
Trouver des personnes, voitures, animaux, 80 autres chosesYOLO (pip install ultralytics)Facile
Reconnaître qui est une personnebibliothèque face_recognitionMoyen
Lire du texte et des chiffres dans l'imageTesseract OCR (pip install pytesseract)Moyen
Lire un QR code ou un code-barresOpenCV, déjà installéFacile
Suivre les mains, les corps et les visagesMediaPipe (pip install mediapipe)Facile
Demander à une IA ce qu'elle voitUn service d'IA avec une API imageMoyen
Enregistrer la vidéo dans un fichierVideoWriter d'OpenCVFacile
Envoyer une alerte sur Telegram ou par emailrequests ou smtplib en PythonFacile

Par exemple, trouver des personnes avec YOLO tient en environ cinq lignes :

from ultralytics import YOLO model = YOLO("yolov8n.pt") # downloads itself the first time results = model(frame) # look at the picture frame = results[0].plot() # draw the boxes

※ Note:

C'est votre ordinateur qui fait le travail difficile, pas l'ESP32 S3. C'est pourquoi cette approche est si efficace : une petite carte bon marché devient l'œil, et votre ordinateur devient le cerveau. La carte ne sait même pas que quelqu'un cherche des visages.

Dépannage

Python affiche Cannot open the camera.

  • Ouvrez d'abord http://<IP>/ dans votre navigateur web. Aucune vidéo là-bas signifie que le problème vient de la carte, pas de Python.
  • Votre ordinateur et la carte doivent être sur le même réseau WiFi.
  • Vérifiez que l'adresse dans CAMERA_URL se termine par /stream.
  • Utilisez http://, pas https://.

La fenêtre s'ouvre mais reste grise ou noire.

Attendez quelques secondes. La première image peut prendre un moment. Si elle reste noire, la pièce est peut-être trop sombre.

Python affiche ModuleNotFoundError: No module named 'cv2'.

OpenCV n'est pas installé. Exécutez à nouveau pip install opencv-python, et assurez-vous d'utiliser le même Python que celui qui exécute votre fichier.

La vidéo dans Python est en retard sur celle du navigateur.

OpenCV garde quelques images dans une file d'attente. Assurez-vous que votre boucle n'a pas de time.sleep(), et gardez votre propre traitement court. Une image plus petite aide aussi : changez FRAME_SIZE en FRAMESIZE_QVGA dans le code ESP32 S3.

La vidéo est lente, seulement quelques images par seconde.

  • Changez FRAME_SIZE en FRAMESIZE_QVGA (320 x 240) dans le code ESP32 S3.
  • Changez JPEG_QUALITY de 12 à 16, afin que les images soient plus petites.
  • Rapprochez la carte du routeur.

La vidéo s'arrête après quelques minutes.

Un seul programme peut lire la vidéo à la fois. Fermez l'onglet du navigateur qui affiche la vidéo, puis relancez Python.

Le Serial Monitor n'affiche jamais A program opened the video stream.

Python n'atteint pas la carte. C'est un problème de réseau, pas de code. Vérifiez l'adresse et le WiFi.

Le Serial Monitor n'affiche rien après les messages de démarrage.

Si votre câble USB est branché sur le port nommé UART, réglez USB CDC On Boot sur Disabled. S'il est branché sur le port nommé USB, réglez-le sur Enabled.

Applications

Une carte bon marché comme œil, et un ordinateur comme cerveau. Voici des projets pratiques que vous pouvez construire avec ce code :

  1. Caméra de porte avec détection de visage : votre ordinateur voit un visage et ouvre la porte, ou écrit l'heure dans un fichier.
  2. Compteur de personnes pour un magasin : comptez combien de personnes passent au cours de la journée.
  3. Lecteur de plaque d'immatriculation : lisez la plaque avec l'OCR et ouvrez un portail pour les voitures connues.
  4. Détecteur de colis : laissez YOLO voir quand un colis est déposé à votre porte, puis envoyez un message sur votre téléphone.
  5. Surveillance d'animaux domestiques : sachez quand votre chat ou votre chien entre dans la pièce, et n'enregistrez que ces moments.
  6. Surveillance de machine et d'imprimante 3D : arrêtez une impression quand l'image montre qu'un problème est survenu.
  7. Contrôle qualité sur un établi : regardez chaque pièce qui passe devant la caméra et marquez celles qui sont défectueuses.
  8. Caméra de mangeoire à oiseaux : découvrez quels oiseaux viennent, avec un modèle de reconnaissance animale.
  9. Télécommande par geste de la main : faites un signe de la main et laissez l'ordinateur allumer une lampe.
  10. Apprentissage de la vision par ordinateur : un moyen très bon marché d'intégrer une vraie caméra en direct dans vos cours de Python.

Vidéo

Regardez le tutoriel vidéo étape par étape pour ce projet ESP32 S3 ci-dessous.

Défis

  1. Débutant : rendez l'image noir et blanc en Python avec cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) avant de l'afficher.
  2. Intermédiaire : enregistrez une image à part chaque fois qu'un visage est trouvé, avec l'heure dans le nom du fichier.
  3. Avancé : envoyez une commande en retour vers l'ESP32 S3 lorsque Python voit quelque chose. Ajoutez une adresse comme /led_on à la carte, et appelez-la depuis Python avec requests.get(). Consultez le tutoriel ESP32 S3 - Bot Telegram pour savoir comment ajouter vos propres adresses.

Connaissances avancées - Pourquoi HTTP est suffisant ici

Beaucoup de gens regardent ce projet et posent une question légitime : Python utilise HTTP. Ne demande-t-il pas encore et encore une nouvelle image à la carte ? Cela doit être lent.

La réponse est non, et cela vaut la peine de comprendre pourquoi.

Il n'y a qu'une seule requête

Python demande une seule fois, et la connexion reste ensuite ouverte pour toujours. La carte continue d'écrire de nouvelles images dans cette même connexion ouverte jusqu'à ce que vous arrêtiez le programme.

Cela fonctionne grâce à une réponse spéciale de la carte :

Content-Type: multipart/x-mixed-replace; boundary=diyablesframe

multipart/x-mixed-replace indique à l'autre côté : *« d'autres images arrivent sur cette même connexion, et chaque nouvelle remplace la précédente »*. Ainsi, la carte écrit simplement image après image :

while (client.connected()) { // one connection, it stays open camera_fb_t *fb = esp_camera_fb_get(); client.print("--" BOUNDARY "\r\n"); // a line to separate the pictures client.write(fb->buf, len); // the picture itself }

Vous pouvez le constater vous-même dans le Serial Monitor. La ligne A program opened the video stream apparaît une seule fois au démarrage de Python, pas dix fois par seconde. Si HTTP redemandait vraiment une image à chaque fois, cette ligne défilerait sans cesse sur votre écran.

Combien est gaspillé ?

Entre deux images, la carte envoie seulement un séparateur et deux courtes lignes :

--diyablesframe 17 bytes Content-Type: image/jpeg 26 bytes Content-Length: 30000 25 bytes (empty line) 2 bytes = 70 bytes

Une image en 640 × 480 pèse environ 30000 octets. Le texte supplémentaire représente donc environ 0,2 % de ce qui est envoyé. Deux octets sur mille. Il n'y a rien à gagner à le supprimer.

※ Note:

Une autre méthode d'envoi, sans HTTP du tout, économiserait ces 70 octets par image. Sur un flux de 10 images par seconde, cela représente 700 octets par seconde, sur environ 300000. Vous ne verriez jamais la différence.

Qu'est-ce qui coûte vraiment quelque chose ?

Le gaspillage ne vient pas de HTTP. Il vient de deux autres endroits :

Coût réelPourquoiPouvez-vous le corriger ?
Chaque image est un JPEG completL'ESP32 S3 n'a pas d'encodeur vidéo, donc il ne peut pas envoyer seulement « ce qui a changé » comme le fait un filmNon. C'est le matériel.
Votre ordinateur garde d'anciennes images dans une file d'attenteOpenCV conserve quelques images, donc ce que vous voyez peut être en léger retardOui, voir ci-dessous
Un seul programme peut regarderLe petit serveur web ne répond qu'à un seul programme à la foisOui, avec un serveur plus gros

Le deuxième point est le seul problème que les gens remarquent vraiment. La correction se fait du côté Python, pas sur la carte : lire les images en arrière-plan et toujours prendre la plus récente.

import cv2, threading class Camera: def __init__(self, url): self.capture = cv2.VideoCapture(url) self.frame = None threading.Thread(target=self.loop, daemon=True).start() def loop(self): while True: ok, frame = self.capture.read() # keep reading, never stop if ok: self.frame = frame # always keep only the newest one

※ Note:

Votre propre code lit ensuite camera.frame dès qu'elle est prête. Les anciennes images sont jetées au lieu d'attendre dans une file, donc la vidéo redevient fluide et en direct. Cela aide beaucoup lorsque votre programme effectue un traitement lent, par exemple de la détection d'objets.

Pourquoi HTTP est un bon choix ici

En plus d'être assez rapide, HTTP vous offre des choses qu'une méthode d'envoi privée n'offrirait jamais :

Bonne chosePourquoi c'est important
Votre navigateur web peut l'ouvrirVous pouvez tester la caméra avant d'écrire la moindre ligne de Python
VLC peut l'ouvrirUn lecteur vidéo gratuit affiche le flux sans aucun code
OpenCV l'ouvre en une seule lignecv2.VideoCapture(url) et c'est fait
Home Assistant et d'autres programmes le connaissentVotre caméra s'intègre dans une maison connectée sans travail supplémentaire
Il passe par votre routeurPas de redirection de port, pas de paramètres spéciaux
Il est facile à examiner en cas de panneTout problème est visible dans un navigateur

※ Note:

C'est la vraie raison de choisir HTTP. Pas la vitesse, mais le fait que tout le monde le parle déjà. Une méthode plus rapide que seul votre programme comprend est généralement un mauvais compromis.

Quand devriez-vous utiliser autre chose ?

Il existe de vraies raisons de changer, mais elles ne concernent pas les 70 octets :

Méthode d'envoiChoisissez-la quandCoût
MJPEG sur HTTP (ce tutoriel)Presque toujoursRien
TCP brut, votre propre formatLe PC est le cerveau et vous voulez un contrôle totalVous écrivez les deux côtés vous-même
UDPVous avez besoin du délai le plus faible possible, et une image cassée vaut mieux qu'une image en retardLes images arrivent cassées ou pas du tout
RTSPVous voulez intégrer la caméra dans un système de sécurité ou un NVRUne bibliothèque et plus de code
WebSocketUne page web doit afficher la vidéo et renvoyer des commandesPlus de code des deux côtés

※ Note:

Pour un projet où un ordinateur regarde les images, MJPEG sur HTTP est la bonne réponse. Changez seulement quand vous avez mesuré un vrai problème, pas parce que HTTP semble lent.

Commentaires

※ NOS MESSAGES

  • N'hésitez pas à partager le lien de ce tutoriel. Cependant, veuillez ne pas utiliser notre contenu sur d'autres sites web. Nous avons investi beaucoup d'efforts et de temps pour créer ce contenu, veuillez respecter notre travail !