En el presente artículo nos enfocaremos en una aplicación sencilla, pero muy práctica, de OpenCV.
¿Cuál?
Como habrás adivinado a partir del título, usaremos OpenCV para transmitir imágenes desde nuestra webcam al navegador de tu preferencia (Chrome, Firefox, Edge, entre otros).
Aunque en principio parezca trivial hacer esto, descubrirás en breve que hay varias “piezas movibles” y conceptos de bajo nivel a tener en cuenta para poder lograr con éxito nuestro cometido.
Al final de este artículo sabrás:
¿Preparado? De ser así, pongámonos en acción.
Streaming de Imágenes de OpenCV a tu Navegador
Antes de continuar, lo más sensato es que discutamos brevemente, a alto nivel, cómo funcionará nuestra solución.
A grandes rasgos, estos son los pasos que nuestro algoritmo seguirá para cada frame proveniente de la webcam:- 1Leerá el frame actual y lo redimensionará manteniendo la relación de aspecto.
- 2Estampará el frame con el día de la semana, fecha y hora.
- 3Codificará la imagen en formato JPEG usando OpenCV.
- 4Servirá los bytes de la imagen al navegador mediante una llamada al servidor web implementado en Flask.
Facilito, ¿no?
Creación del Entorno de Desarrollo con Anaconda
Abajo puedes ver la estructura de nuestro proyecto. Como has de notar, los archivos más relevantes son:
Si gustas descargar el proyecto, simplemente llena este formulario:
Para crear el entorno de desarrollo con Anaconda, primero ubícate en la raíz del proyecto, y después ejecuta la siguiente instrucción en la consola:
conda env create -f opencv-document-alignment-registration
La configuración del ambiente (opencv-html-video-stream) es esta:
Para activar el ambiente, corre este comando:
conda activate opencv-html-video-stream
¡Listo! Continuemos.
Transmisión de Imágenes con OpenCV y Flask
El primer archivo que tienes que abrir es datasmarts/templates/index.html, cuyo contenido verás a continuación:
Como puedes notar, consiste de una plantilla muy sencilla, en la cual insertaremos el live feed de la webcam mediante el URL de la función video_feed().
El siguiente paso es abrir el archivo datasmarts/stream.py, e insertar estas líneas para importar las dependencias del proyecto:
Para impedir condiciones de carrera cada vez que leemos frames de la cámara web, obtendremos un “lock” o candado que nos permitiré bloquear el acceso a la misma cuando lo necesitemos; esto lo logramos mediante la función thread.lock():
Inicializamos la aplicación de Flask, así como el lector de frames:
La primera función auxiliar que constuiremos es timestamp_feed(), la cual aplica una estampa de tiempo a cada frame proveniente de un stream (webcam):
Después de obtener referencias a las variables globales, iteramos infinitamente para obtener cada frame, redimensionarlo y estamparle la fecha actual:
Fíjate que la última instrucción del extracto anterior lo que hace es asignar la imagen estampada a la variable global output_frame, si y solo sí tenemos el lock sobre dicho recurso:
La próxima función auxiliar (generate()) se encarga de generar imágenes codificadas en formato JPEG:
Si y solo si tenemos el lock sobre output_frame, usamos la función cv2.imencode() para codificar su contenido en formato JPEG:
Finalmente, generamos el contenido de la imagen como un arreglo de bytes:
Creamos el controlador index(), correspondiente a la ruta /, el cual simplemente renderiza el template ubicado en datasmarts/templates/index.html:
El siguiente controlador, video_feed(), correspondiente a la ruta /video_feed, genera una respuesta por cada llamada al generador generate(), asociando el MIME Type apropiado:
Para culminar, corremos la función timestamp_feed() en su propio hilo, y desplegamos el servidor Flask en la ruta https://127.0.0.0.1:4747
¡ATENTO!
Antes de ejecutar el código, asegúrate de hallarte en la raíz del proyecto para que los comandos funcionen correctamente.
Para correr el programa, simplemente ejecuta:
python datasmarts/stream.py
En el resultado se verá así:
Genial, ¿no?
El lado bueno es que, a pesar de que lo que hicimos es trivial, puedes sustituir el estampado de tiempo con cualquier otra operación (por ejemplo, detección facial, procesamiento de imágenes, clasificación, etcétera) ya que las demás piezas permanecen constantes.
Resumen
Hoy aprendimos a extraer imágenes de nuestra webcam, transformarla, y luego mostrar el resultado en el navegador.
Concretamente, nuestra transformación consiste meramente de añadir una estampa de tiempo a la imagen.
No obstante, usando este framework podemos crear programas mucho más interesantes que ejecuten tareas más serias, como detección de objetos, clasificación, detección de movimiento, entre un sinfín de opciones.
Lo importante es saber que para poder darle vida a este tipo de aplicaciones requerimos estos elementos:
¡Hasta pronto!