En este tutorial aprenderás a detectar y clasificar objetos usando el módulo ESP32-CAM y YOLO, un sistema de deep learning para detección de objetos.
Te guiaré para construir un proyecto donde el ESP32-CAM captura imágenes, funciona como servidor web y envía las imágenes a un ordenador para su análisis. El ordenador usará YOLO para detectar y clasificar objetos. Aprenderás a montar el hardware, configurar la cámara y servir imágenes JPEG vía HTTP.
Al final, tendrás una interfaz web funcional para ver las instantáneas capturadas por tu ESP32-CAM y un sistema de detección de objetos para 80 tipos diferentes de objetos.
Piezas necesarias
A continuación encontrarás los componentes necesarios para construir el proyecto. En lugar del programador FTDI también podrías usar un Shield de programación para el ESP32-CAM, pero recomiendo el primero.

ESP32-CAM

Adaptador FTDI USB-TTL

Cable de datos USB

Arduino IDE
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Arquitectura del sistema
El sistema que vamos a construir está compuesto por dos componentes principales. 1) un módulo ESP32-CAM que captura imágenes y funciona como servidor web que envía las imágenes vía WiFi. 2) un PC donde el YOLO sistema de detección de objetos está en funcionamiento. Analiza las imágenes y anota los objetos detectados. El diagrama a continuación te da una visión general de la arquitectura del sistema:

La siguiente imagen muestra un ejemplo de detección del sistema. En mi escritorio desordenado, YOLO pudo detectar una taza con un 88% de confianza, unas tijeras con un 68% y un portátil con un 59%. Puedes ver los cuadros delimitadores alrededor de los objetos con sus nombres y la confianza de detección anotados en la esquina superior izquierda:

En las siguientes secciones aprenderás a programar el servidor web en el ESP32-CAM y cómo configurar el sistema de detección YOLO en un PC.
La placa de desarrollo ESP32-CAM
La placa de desarrollo ESP32-CAM es un módulo compacto que combina un chip ESP32-S, una cámara, un flash incorporado y una ranura para tarjeta microSD. La placa tiene Wi-Fi y Bluetooth integrados y soporta una cámara OV2640 o OV7670 con hasta 2 megapíxeles de resolución.

En el tutorial nos referiremos a la placa original AI-Thinker model del ESP32-CAM pero existen muchos clones con exactamente las mismas especificaciones. Se programan y usan de la misma manera, incluyendo el que listamos en Piezas necesarias.
Conectando el programador FTDI
Puedes programar el ESP32-CAM vía un Programming Shield o vía un FTDI Programmer. Este último es más fácil de usar y más flexible. Convierte señales USB a señales seriales y permite programar microcontroladores como Arduino y ESP32 vía la interfaz UART. La siguiente imagen muestra cómo conectar el programador FTDI al módulo ESP32-CAM.

Las conexiones son simples. Comienza conectando GND del programador con GND del módulo ESP32-CAM (cable azul). Luego haz lo mismo con la alimentación de 5V (cable rojo). Ten en cuenta que algunos programadores FTDI tienen jumpers o interruptores para cambiar entre 3.3V y 5V. Asegúrate de usar 5V, si es posible.
Luego conectamos el pin U0T (U0TXD) del ESP32-CAM al pin RXD del programador (cable amarillo). De forma similar, U0R se conecta a TXD (cable verde). Con esto se establece la comunicación serial.
Para poner el ESP32-CAM en modo programación, el pin IO0 debe conectarse a tierra (GND). Pero si quieres ejecutar el programa, el pin IO0 debe quedar desconectado. Por eso añadí un interruptor entre IO0 y GND (cable morado) que me permite cambiar entre modo programación y modo ejecución. La foto abajo muestra mi conexión del ESP32-CAM con el interruptor y el programador FTDI:

Instalando el Core ESP32
Si es tu primer proyecto con cualquier placa de la serie ESP32, primero debes instalar la placa. Si ya tienes las placas ESP32 instaladas en tu Arduino IDE, puedes saltarte esta sección.
Comienza abriendo el diálogo de Preferencias seleccionando “Preferences…” en el menú “File”. Esto abrirá el diálogo de Preferencias mostrado abajo.
En la pestaña Settings encontrarás un cuadro de edición al final del diálogo etiquetado como “Additional boards manager URLs”:

En este campo copia la siguiente URL: «https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json«
Esto permitirá que el Arduino IDE sepa dónde encontrar las librerías core del ESP32. A continuación instalaremos las librerías core del ESP32 usando el Boards Manager.
Abre el Boards Manager vía «Tools -> Boards -> Board Manager». Verás el Boards Manager en la barra lateral izquierda. Escribe «ESP32» en el campo de búsqueda arriba y deberías ver dos tipos de placas ESP32; las «Arduino ESP32 Boards» y las placas «esp32 by Espressif». Queremos las librerías esp32 de Espressif. Haz clic en el botón INSTALL y espera a que la descarga e instalación terminen.

Seleccionando la placa ESP32-CAM
Haz clic en el menú desplegable y luego en «Select other board and port…»:

Esto abrirá un diálogo donde debes escribir «ESP32-CAM» en la barra de búsqueda. Verás la placa «AI Thinker ESP32-CAM» bajo Boards. Haz clic en ella y selecciona el puerto COM para activarla, luego haz clic en OK:

Si no puedes seleccionar un puerto a pesar de tener el ESP32-CAM conectado a un puerto USB vía el programador FTDI, entonces falta el driver CP210X. Ve a SILICON LABS Software Downloads y descarga el driver CP210x para tu sistema operativo, por ejemplo para Windows es «CP210x VCP Windows»:

Esto descargará un archivo ZIP. Descomprímelo y ejecuta el instalador. Después de eso tu ESP32-CAM debería aparecer conectado a un puerto USB. Si aún tienes problemas, puede que también necesites instalar un FTDI Driver.
Instalando la librería ESP32-CAM
Para nuestro servidor web vamos a usar la esp32cam library. Ve a github repo, haz clic en el botón verde CODE y luego en «Download ZIP» para descargar la librería:

Luego haz clic en «Sketch->Include Library->Add .Zip Library»:

y selecciona la ruta al archivo ZIP que acabas de descargar para instalar la librería. En la siguiente sección escribiremos y explicaremos el código para ejecutar un servidor web en el ESP32-CAM.
Código para servidor web ESP32-CAM
El siguiente código configura un módulo ESP32-CAM para enviar imágenes a través de una red Wi-Fi. Captura imágenes y las sirve como archivos JPEG a los clientes que las soliciten. El servidor corre en el puerto 80, que es el puerto HTTP por defecto.
#include "WebServer.h"
#include "WiFi.h"
#include "esp32cam.h"
const char* WIFI_SSID = "SSID";
const char* WIFI_PASS = "PASSWORD";
const char* URL = "/cam.jpg";
static auto RES = esp32cam::Resolution::find(800, 600);
WebServer server(80);
void serveJpg() {
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("CAPTURE FAILED!");
server.send(503, "", "");
return;
}
Serial.printf("CAPTURE OK %dx%d %db\n",
frame->getWidth(), frame->getHeight(),
static_cast<int>(frame->size()));
server.setContentLength(frame->size());
server.send(200, "image/jpeg");
WiFiClient client = server.client();
frame->writeTo(client);
}
void handleJpg() {
if (!esp32cam::Camera.changeResolution(RES)) {
Serial.println("CAN'T SET RESOLUTION!");
}
serveJpg();
}
void initCamera() {
{
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RES);
cfg.setBufferCount(2);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
}
void initWifi() {
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED)
;
Serial.printf("http://%s%s\n",
WiFi.localIP().toString().c_str(), URL);
}
void initServer() {
server.on(URL, handleJpg);
server.begin();
}
void setup() {
Serial.begin(115200);
initWifi();
initCamera();
initServer();
}
void loop() {
server.handleClient();
}
Vamos a desglosar el código en sus componentes para entender cómo funciona.
Librerías y constantes
Al inicio del código, incluimos las librerías necesarias para el servidor web, funcionalidad Wi-Fi y control de la cámara.
#include "WebServer.h" #include "WiFi.h" #include "esp32cam.h"
También definimos constantes para las credenciales Wi-Fi y el endpoint URL para acceder a la imagen de la cámara.
const char* WIFI_SSID = "SSID"; const char* WIFI_PASS = "PASSWORD"; const char* URL = "/cam.jpg";
Obviamente, tendrás que reemplazar las credenciales con el SSID y la contraseña de tu red Wi-Fi.
Resolución de la cámara
Establecemos la resolución deseada para la cámara. En este caso, buscamos una resolución de 800×600 píxeles.
static auto RES = esp32cam::Resolution::find(800, 600);
Inicialización del servidor web
Luego creamos una instancia del servidor web que escucha en el puerto 80.
WebServer server(80);
Función para servir JPEG
La función serveJpg()captura una imagen de la cámara y la envía al cliente como un archivo JPEG. Si la captura falla, envía una respuesta «503 Service Unavailable».
void serveJpg() {
auto frame = esp32cam::capture();
if (frame == nullptr) {
Serial.println("CAPTURE FAILED!");
server.send(503, "", "");
return;
}
Serial.printf("CAPTURE OK %dx%d %db\n",
frame->getWidth(), frame->getHeight(),
static_cast<int>(frame->size()));
server.setContentLength(frame->size());
server.send(200, "image/jpeg");
WiFiClient client = server.client();
frame->writeTo(client);
}
Aquí, primero intentamos capturar un frame. Si tiene éxito, registramos las dimensiones y tamaño de la imagen, establecemos la longitud del contenido y enviamos la imagen al cliente.
Función para manejar JPEG
La función handleJpg() cambia la resolución de la cámara y llama a serveJpg() para servir la imagen.
void handleJpg() {
if (!esp32cam::Camera.changeResolution(RES)) {
Serial.println("CAN'T SET RESOLUTION!");
}
serveJpg();
}
Esta función asegura que la cámara esté configurada a la resolución deseada antes de servir la imagen.
Inicialización de la cámara
La función initCamera() configura los ajustes de la cámara, incluyendo asignación de pines, resolución, número de buffers y calidad JPEG.
void initCamera() {
{
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(RES);
cfg.setBufferCount(2);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
}
Creamos un objeto de configuración, establecemos los parámetros necesarios e inicializamos la cámara. Se imprime un mensaje en el monitor serial indicando si la inicialización fue exitosa.
Inicialización Wi-Fi
La función initWifi() conecta el ESP32 a la red Wi-Fi especificada.
void initWifi() {
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED)
;
Serial.printf("http://%s%s\n",
WiFi.localIP().toString().c_str(), URL);
}
Desactivamos conexiones Wi-Fi persistentes, establecemos el modo estación y tratamos de conectar a la red Wi-Fi. Una vez conectado, imprimimos la URL para acceder a la imagen de la cámara.
Inicialización del servidor
La función initServer() configura el servidor para manejar solicitudes de la imagen de la cámara.
void initServer() {
server.on(URL, handleJpg);
server.begin();
}
Definimos el endpoint URL y lo asociamos con la función handleJpg(), luego iniciamos el servidor.
Función setup
La función setup() inicializa la comunicación serial, Wi-Fi, cámara y servidor.
void setup() {
Serial.begin(115200);
initWifi();
initCamera();
initServer();
}
Función loop
Finalmente, la función loop() maneja continuamente las solicitudes entrantes de los clientes.
void loop() {
server.handleClient();
}
Esta función asegura que el servidor responda a las solicitudes de los clientes, permitiendo que estos recuperen imágenes capturadas por la cámara.
Prueba del servidor web ESP32-CAM
Ahora, probemos el servidor web. Compila y sube el código anterior. Para subir código al ESP32-CAM, cambia la placa a modo programación activando el interruptor, luego presiona brevemente el botón Reset en la placa y después haz clic en el botón Upload en el Arduino IDE.
Si necesitas más ayuda para subir código al ESP32-CAM, echa un vistazo al Programming the ESP32-CAM tutorial, que ofrece más detalles.
Después de una subida exitosa verás la URL para las imágenes de la cámara impresa en el Monitor Serial y también deberías ver el texto «CAMERA OK»:
http://192.168.1.146/cam.jpg CAMERA OK
Copia esta URL en la barra de direcciones de tu navegador web y deberías ver la imagen que la cámara ha tomado:

Cada vez que presionas el botón de recargar en tu navegador, el servidor web recibe esta solicitud, pide al ESP32-CAM que tome una nueva foto y envía esta nueva imagen a tu navegador. Abajo una foto de mi escritorio tomada de esta manera:

En la siguiente sección enviaremos las imágenes al modelo de detección de objetos YOLO para reconocer los objetos en la escena.
Detección de objetos con YOLO
YOLO(You Only Look Once) es un modelo de deep learning para detección de objetos conocido por su velocidad y precisión. Fue presentado por primera vez por Joseph Redmon et al. in 2016. Desde entonces ha habido muchas versiones mejoradas, siendo YOLO11 by Ultralytics la más reciente (a febrero de 2025).
Sin embargo, usaremos un modelo más antiguo YOLOv3v, ya que es más pequeño y fácil de usar, aunque su precisión no es tan alta como la de los modelos más recientes.

El modelo YOLO es una red convolucional profunda que toma una imagen RGB de dimensiones 448x448x3 como entrada y produce los cuadros delimitadores y las puntuaciones de confianza para los objetos detectados en un tensor 7×7×30. Usaremos una versión del modelo entrenada para detectar 80 different objects, tales como:
- persona
- bicicleta
- coche
- moto
- …
- tijeras
- oso de peluche
- secador de pelo
- cepillo de dientes
No entraremos en detalles del modelo aquí, pero si quieres aprender más, aquí tienes enlaces a la publicación original de YOLO, una descripción de las mejoras en la versión 3 de YOLO y un artículo de aplicación con información útil:
- YOLOv3: An Incremental Improvement
- You Only Look Once: Unified, Real-Time Object Detection
- YOLO v3: Visual and Real-Time Object Detection Model for Smart Surveillance Systems(3s)
Estructura de carpetas del proyecto
Para ejecutar el sistema de detección YOLO en un PC necesitamos crear una carpeta de proyecto, digamos «esp32-cam-yolo-object-detection». Dentro de esta carpeta crea una subcarpeta llamada «YOLO» y un archivo python llamado «detect.py». La estructura de carpetas debería ser la siguiente:

Descargar archivos YOLO
Luego debes descargar los archivos necesarios de YOLO (pesos, configuración de arquitectura, nombres de clases) y colocarlos en la carpeta «YOLO» del proyecto. Aquí están los enlaces a estos archivos:
- https://pjreddie.com/media/files/yolov3.weights
- https://github.com/pjreddie/darknet/blob/master/cfg/yolov3.cfg
- https://github.com/pjreddie/darknet/blob/master/data/coco.names
El contenido de tu carpeta «YOLO» debería verse así:

Creando entorno virtual
También tenemos que instalar algunas librerías de Python y las instalaremos en un entorno virtual usando venv. Abre una consola y ejecuta los siguientes comandos:
cd esp32-cam-object-detection python -m venv venv venv\Scripts\activate.bat pip install opencv-python opencv-python-headless numpy torch torchvision
El comandocdnos mueve a la carpeta del proyecto. El comando ven crea el entorno virtual y dentro de este instalamos las librerías necesarias vía pip install. Esto creará una carpeta «venv» en la carpeta del proyecto que contiene las librerías:

Código de detección de objetos
Finalmente, como último paso copia el siguiente código en el archivo detect.pyde tu carpeta de proyecto.
import cv2
import numpy as np
import urllib.request
# Camera URL
url = "http://192.168.1.146/cam.jpg"
# YOLO model files
weights_path = r"./YOLO/yolov3.weights"
config_path = r"./YOLO/yolov3.cfg"
names_path = r"./YOLO/coco.names"
# Load the YOLO model and COCO class names
net = cv2.dnn.readNet(weights_path, config_path)
with open(names_path, "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = net.getLayerNames()
# Handling the return value of getUnconnectedOutLayers()
out_layers = net.getUnconnectedOutLayers()
if isinstance(out_layers[0], list):
output_layers = [layer_names[i[0] - 1] for i in out_layers]
else:
output_layers = [layer_names[i - 1] for i in out_layers]
# Generate random colors for each class
colors = np.random.uniform(0, 255, size=(len(classes), 3))
def detect_objects(frame):
height, width, _ = frame.shape
blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
layer_outputs = net.forward(output_layers)
boxes = []
confidences = []
class_ids = []
for output in layer_outputs:
for detection in output:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.3:
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.3, 0.4)
# Draw detections on the frame
if len(indexes) > 0 and isinstance(indexes, np.ndarray):
indexes = indexes.flatten()
for i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
confidence = confidences[i]
color = colors[class_ids[i]]
print(f"Detected: {label} with confidence {confidence:.2f}")
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
cv2.putText(
frame,
f"{label} {confidence:.2f}",
(x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
color,
2,
)
return frame
def main():
cv2.namedWindow("Object Detection", cv2.WINDOW_AUTOSIZE)
while True:
try:
img_resp = urllib.request.urlopen(url)
imgnp = np.array(bytearray(img_resp.read()), dtype=np.uint8)
frame = cv2.imdecode(imgnp, -1)
frame = detect_objects(frame)
cv2.imshow("Object Detection", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
except Exception as e:
print(f"Error occurred: {e}")
break
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
El código anterior implementa un sistema de detección de objetos usando el modelo YOLO con OpenCV. Captura imágenes de una fuente de cámara y detecta objetos en tiempo real, mostrando los resultados en pantalla.
Importando librerías
Comenzamos importando las librerías necesarias:cv2para tareas de visión por computadora,numpypara operaciones numéricas, yurllib.requestpara manejar solicitudes URL.
import cv2 import numpy as np import urllib.request
URL de la cámara
Aquí definimos la URL del feed de la cámara desde donde capturaremos imágenes. Tendrás que reemplazar esta constante con la URL que tu servidor web entrega imágenes:
url = "http://192.168.1.146/cam.jpg"
Archivos del modelo YOLO
Luego especificamos las rutas a los archivos del modelo YOLO: el archivo de pesos, el archivo de configuración y los nombres de los objetos que el modelo puede detectar.
weights_path = r"./YOLO/yolov3.weights" config_path = r"./YOLO/yolov3.cfg" names_path = r"./YOLO/coco.names"
Cargando el modelo YOLO
Cargamos el modelo YOLO usando el módulo dnn de OpenCV y leemos los nombres de las clases desde el archivo especificado. También obtenemos los nombres de las capas para uso posterior.
net = cv2.dnn.readNet(weights_path, config_path)
with open(names_path, "r") as f:
classes = [line.strip() for line in f.readlines()]
layer_names = net.getLayerNames()
Capas de salida
Determinamos las capas de salida de la red. Esto es crucial para saber qué capas proporcionan las detecciones finales.
out_layers = net.getUnconnectedOutLayers()
if isinstance(out_layers[0], list):
output_layers = [layer_names[i[0] - 1] for i in out_layers]
else:
output_layers = [layer_names[i - 1] for i in out_layers]
Generando colores para las clases
Para visualizar y distinguir los objetos detectados, generamos colores aleatorios para los cuadros delimitadores.
colors = np.random.uniform(0, 255, size=(len(classes), 3))
Función de detección de objetos
La función detect_objects() toma un frame de imagen como entrada, lo procesa y detecta objetos usando el modelo YOLO. Devuelve el frame con cuadros delimitadores y etiquetas dibujadas.
def detect_objects(frame):
height, width, _ = frame.shape
blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
layer_outputs = net.forward(output_layers)
boxes = []
confidences = []
class_ids = []
En esta función, primero creamos un blob a partir del frame de entrada, que es una versión preprocesada de la imagen adecuada para el modelo. Luego realizamos un pase hacia adelante para obtener la salida del modelo.
Procesando detecciones
Recorremos las salidas para extraer cuadros delimitadores, puntuaciones de confianza e IDs de clase para los objetos detectados. Solo se consideran válidas las detecciones con confianza mayor a 0.3. Puedes cambiar este parámetro (0…1) para mostrar detecciones menos o más confiables.
for output in layer_outputs:
for detection in output:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.3:
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
Supresión de no máximos
Para eliminar cuadros superpuestos redundantes, aplicamos Non-Maximum Suppressio (NMS) para mantener solo los mejores cuadros delimitadores.
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.3, 0.4)
Dibujando detecciones
Dibujamos los cuadros delimitadores y etiquetas en el frame para cada objeto detectado. Se muestra el nombre de la clase/objeto detectado y la puntuación de confianza.
if len(indexes) > 0 and isinstance(indexes, np.ndarray):
indexes = indexes.flatten()
for i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
confidence = confidences[i]
color = colors[class_ids[i]]
print(f"Detected: {label} with confidence {confidence:.2f}")
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
cv2.putText(
frame,
f"{label} {confidence:.2f}",
(x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
color,
2,
)
Función principal
La función main() configura una ventana para mostrar las detecciones y captura continuamente frames del feed de la cámara. Procesa cada frame con la función detect_objects() y muestra el resultado.
def main():
cv2.namedWindow("Object Detection", cv2.WINDOW_AUTOSIZE)
while True:
try:
img_resp = urllib.request.urlopen(url)
imgnp = np.array(bytearray(img_resp.read()), dtype=np.uint8)
frame = cv2.imdecode(imgnp, -1)
frame = detect_objects(frame)
cv2.imshow("Object Detection", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
except Exception as e:
print(f"Error occurred: {e}")
break
cv2.destroyAllWindows()
Se abrirá una ventana y si presionas «q» mientras la ventana está activa, la aplicación terminará.
Punto de entrada de ejecución
Finalmente, verificamos si el script se está ejecutando directamente y llamamos a la función main() para iniciar el programa.
if __name__ == "__main__":
main()
En la siguiente sección juntamos todo y ejecutamos nuestro sistema de detección de objetos.
Ejecutando el detector de objetos
Primero, enciende tu módulo ESP32-CAM con el código del servidor web y asegúrate de que el ESP32-CAM capture imágenes y las muestre en un navegador web bajo la URL impresa en el Monitor Serial. También asegúrate de que esta URL se use en detect.py, por ejemplo, en mi caso esta URL es:
url = "http://192.168.1.146/cam.jpg"
Luego iniciamos el detector de objetos YOLO. Ve a tu carpeta de proyecto («esp32-cam-object-detection»), activa el entorno virtual y ejecuta el código del detector detect.py:
cd esp32-cam-object-detection venv\Scripts\activate.bat python detect.py
Ten en cuenta que puedes desactivar el entorno virtual llamando a:
venv\Scripts\deactivate.bat
Si el código está corriendo deberías ver los nombres de los objetos detectados con la puntuación de confianza impresa en la consola:
Detected: cup with confidence 0.76 Detected: laptop with confidence 0.39 Detected: cup with confidence 0.51 Detected: laptop with confidence 0.33 Detected: cup with confidence 0.44 Detected: cup with confidence 0.65 Detected: cup with confidence 0.63
También se abrirá una ventana llamada «Object Detection» que muestra la imagen actual que la cámara ve con cuadros delimitadores alrededor de los objetos que el sistema pudo detectar. Abajo un ejemplo donde el sistema detecta correctamente una taza, un mando a distancia y un portátil:

Si quieres ver más ejemplos de las capacidades de detección del modelo YOLO visita el siguiente YOLO Demo Video.
Conclusiones
En este tutorial aprendiste a construir un sistema de detección de objetos. El módulo ESP32-CAM se usó para capturar imágenes y ejecutar un servidor web para esas imágenes. Luego las imágenes se enviaron vía Wi-Fi a un PC que ejecuta un software de detección de objetos basado en el modelo de deep learning YOLO.
Compilar y subir código al ESP32-CAM puede ser bastante complicado. Si tienes problemas, echa un vistazo al Programming the ESP32-CAM tutorial, que ofrece instrucciones más detalladas.
Ten en cuenta que nuestro pequeño sistema de detección de objetos está limitado a 80 objetos predefinidos (o clases). Sin embargo, puedes entrenar el modelo YOLO con tus propios objetos. El How to Train YOLOv3 to Detect Custom Objects?tutorial puede ayudarte si quieres hacer esto.
Si tienes más preguntas, no dudes en dejarlas en la sección de comentarios.
¡Feliz bricolaje ; )


