En la primera parte de este tutorial destinado a aprender a utilizar la ESP32-CAM en Micropython te expliqué como grabar un custom firmware en la placa. En esta segunda entrega veremos en detalle los objetos y métodos que agrega este firmware y que nos permiten tener acceso a las funciones de la cámara.
Control de la cámara
Una vez que tenemos el firmware instalado en nuestra ESP32-CAM podemos comenzar a programarla desde Micropython. (La instalación del firmware está explicada en este artículo anterior)
El primer paso es importar el módulo camera que incluye un objeto del mismo nombre que cuenta con 12 métodos para configurar la cámara y capturar imágenes.
Estos métodos son los siguientes:
- init
- deinit
- flip
- mirror
- framesize
- quality
- contrast
- saturation
- brightness
- speffect
- whitebalance
- capture
Veamos a continuación cada uno de ellos en detalle
init
Método: init
Activa e inicializa la cámara
Formato: camera.init (0, parámetro=valor, …)
Los parámetros aceptados en init son los siguientes, con sus valores posibles entre corchetes.
xclk_freq_hz: Frecuencia de reloj de la cámara en Hz. [10000000, 20000000 ]
frame_size: Tamaño de la imagen capturada (ver método framesize mas abajo)
pixel_format: Formato de la imagen capturada [JPEG, YUV422, GRAYSCALE, RGB565]
jpeg_quality: Calidad de la imagen capturada [10..63]. Los valores menores representan mayor calidad
fb_location: Ubicación de la imagen capturada [DRAM, PSRAM]. Es conveniente usar PSRAM.
Ejemplo:
camera.init (0, format=camera.JPEG, fb_location=camera.PSRAM)
deinit
Método: deinit ()
Desactiva la cámara
Parámetros:
No tiene
Ejemplo:
camera.deinit ()
flip
Método: flip (orientación)
Cambia la orientación vertical de la imagen
Parámetros:
Orientación = 0 > Imagen normal
Orientación = 1 > Imagen invertida
Ejemplo:
camera.flip (0) #Sin invertir
mirror
Método: mirror (orientación)
Cambia la orientación horizontal de la imagen
Parámetros:
Orientación = 0 > Imagen normal
Orientación = 1 > Imagen invertida
Ejemplo:
camera.mirror (1) #Invertida
framesize
Método: framesize (tamaño)
Especifica el tamaño y resolución de la imagen capturada
Parámetros:
tamaño debe tener alguno de los siguientes valores:
FRAME_96X96 = 96*96
FRAME_QQVGA = 160*120
FRAME_QCIF = 176*144
FRAME_HQVGA = 240*160
FRAME_240X240 = 240*240
FRAME_QVGA = 320*240
FRAME_CIF = 352*288
FRAME_HVGA = 480*320
FRAME_VGA = 640*480
FRAME_SVGA = 800*600
FRAME_XGA = 1024*768
FRAME_HD = 1280*720
FRAME_SXGA = 1280*1024
FRAME_UXGA = 1600*1200
FRAME_FHD = 1920*1080
FRAME_P_HD = 2048*1152
FRAME_P_3MP = 2048*1536
FRAME_QXGA = 2048*1536
FRAME_QHD = 2560*1440
FRAME_WQXGA = 2560*1600
FRAME_P_FHD
FRAME_QSXGA = 2560*2048
Ejemplo:
camera.framesize (camera.FRAME_CIF)
quality
Método: quality (calidad)
Especifica la calidad de la imagen capturada.
Parámetros:
calidad puede variar entre 10 (calidad alta) y 63 (calidad baja)
Ejemplo:
camera.quality (10)
contrast
Método: contrast (contraste)
Especifica el contraste de la imagen
Parámetros:
contraste puede variar entre -2 (contraste bajo) y 2 (contraste alto). Por omisión vale 0.
Ejemplo:
camera.contrast (1)
saturation
Método: saturation (saturación)
Especifica la saturación (intensidad de los colores) de la imagen
Parámetros:
saturación puede variar entre -2 (baja intensidad) y 2 (alta intensidad). Por omisión vale 0.
Ejemplo:
camera.saturation (-1)
brightness
Método: brightness (brillo)
Especifica el brillo de la imagen
Parámetros:
brillo puede variar entre -2 (mas bajo) y 2 (mas alto). Por omisión vale 0.
Ejemplo:
camera.brightness (1)
speffect
Método: speffect (efecto)
Aplica un efecto a la imagen
Parámetros:
efecto puede ser uno de los siguientes:
EFFECT_NONE (por omisión)
EFFECT_NEG = negativo
EFFECT_BW = ByN (escala de grises)
EFFECT_RED = Rojizo
EFFECT_GREEN = Verdoso
EFFECT_BLUE = Azulado
EFFECT_RETRO = Sepia
Ejemplo:
camera.speffect (camera.EFFECT_NONE)
whitebalance
Método: whitebalance (modo)
Equilibra los niveles de los colores básicos (Rojo, Verde y Azul).
Parámetros:
modo puede ser uno de los siguientes:
WB_NONE = sin compensación
WB_SUNNY = compensa días soleados
WB_CLOUDY = compensa días nublados
WB_OFFICE = compensa iluminación fría
WB_HOME = compensa iluminación cálida
Ejemplo:
camera.whitebalance (camera.WB_NONE)
capture
Método: capture ()
Captura una imagen
Parámetros:
No tiene.
Ejemplo:
img = camera.capture()
Programa
El siguiente es un ejemplo sencillo que toma imágenes cada 10 segundos y las almacena como archivos en la memoria Flash del ESP32. Es una modificación del programa de ejemplo que se puede encontrar en el repositorio del firmware.
Como se puede ver, en las líneas 1, 2 y 3 se importan los módulos necesarios, empezando por camera.
En la línea 7 se define led en el pin 4, donde está conectado el flash de la cámara.
En la línea 9 se inicializa la variable foto a 1, para contar las imágenes que se van capturando e incluirlo en el nombre del archivo cuando las mismas se graben en la memoria.
A continuación, en la línea 11 se inicia un bucle para capturar las imágenes cada 10 segundos. Lo primero es generar el nombre del archivo que se va a guardar como “Capx.jpg” donde x será reemplazado por el valor de la variable foto.
Luego desde la línea 15, dentro de un bloque try se hace la inicialización y configuración de la cámara y luego la captura de la imagen (línea 50).
import camera from time import sleep import machine #Pin del led de flash led = machine.Pin(4, machine.Pin.OUT) foto=1 while (True): nombre = "Cap"+str(foto)+".jpg" print (nombre) try: camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM) #Establece el brillo camera.brightness(-1) #Orientacion normal camera.flip(0) #Orientación normal camera.mirror (0) #Resolución camera.framesize(camera.FRAME_XGA) #contraste camera.contrast(2) #saturacion camera.saturation (-2) #calidad camera.quality(10) # special effects camera.speffect(camera.EFFECT_NONE) # white balance camera.whitebalance(camera.WB_NONE) #Enciende flash #led.value(1) sleep (0.5) #Captura la imagen img = camera.capture() print ("Tamaño=",len(img)) #Apaga flash led.value(0) #desactivar cámara camera.deinit () #Guardar la imagen en el sistema de archivos imgFile = open(nombre, "wb") imgFile.write(img) imgFile.close() foto+=1 sleep (10) except Exception as err: print ("Error= "+str (err)) sleep (2)
En la línea 46 está comentado el encendido del flash. Si lo necesitas debes descomentar esta línea.
El print de la línea 51 muestra el tamaño de la imagen. Este programa está pensado sólo como un ejemplo del uso de los métodos de la cámara y por esta razón las imágenes se graban en la flash del ESP32 y no en la tarjeta SD. La idea es tomar unas pocas imágenes y descargarlas luego a una computadora para verlas, y no que funcione como un time lapse, por ejemplo. Si tomas muchas imágenes (depende de la resolución) puede que obtengas un Error 28 (memoria llena).
Usando Thonny es muy fácil descargar las imágenes a la computadora. Debes activar la visualización de los archivos, hacer click derecho sobre la imagen que quieras descargar y seleccionar Descargar a (carpeta).
Siguiendo con el análisis del programa de ejemplo, en las líneas 61, 62 y 63 se graba la imagen en la memoria como un archivo binario. Si quieres puedes aprender como trabajar con este tipo de archivos en este artículo anterior.
En la línea 65 se incrementa el contador de imágenes y en la 67 se realiza el retardo de 10 segundos.
Si hubiera algún error dentro del bloque try, desde la línea 69 se captura el error en el bloque exception donde se muestra el mensaje del error producido y se espera 2 segundos.
Ejemplos y observaciones
Las siguientes son algunas imágenes de ejemplo tomadas con distintas configuraciones, calidades y resoluciones.







No es fácil obtener imágenes de buena calidad. Las variaciones de iluminación entre ambientes abiertos y cerrados hace necesario ajustar los distintos parámetros de configuración de la cámara, como brillo, contraste o saturación.
A mayor tamaño de imagen es necesaria una mayor iluminación. En interiores se obtienen mejores resultados con resoluciones bajas.
No se pueden lograr simultáneamente resoluciones altas y calidad de imagen alta. Si se aumenta la resolución, sobre todo en los valores mas elevados, hay que comenzar a disminuir la calidad. Por ejemplo en formato XGA se puede tener la calidad mas alta (el valor de 10) pero en SXGA la calidad debe disminuirse (un valor de 20) y mas aún en UXGA (un valor de 30).
En exteriores es habitual que las imágenes contengan zonas “quemadas” es decir blancas debido a la cantidad de luz. Tal vez esto podria evitarse reduciendo el tiempo de exposición, pero esta función no esta disponible en este firmware.
Si bien el firmware admite valores de resolución muy elevados, con mi ESP32-CAM con una cámara OV2640, siempre obtuve error para valores superiores a UXGA (1600*1200 = 1.8 MPx). Los valores de resolución mayores tal vez estén reservados para otros modelos de cámara.
Conclusión
El firmware de lemariva nos permite programar la ESP32-CAM en Micropython y pone a nuestra disposición una serie de métodos para controlar las funciones mas comunes de la cámara de una forma sumamente sencilla. En este artículo te mostré como utilizar cada uno de ellos y como emplearlos en un ejemplo sencillo que toma imágenes con la cámara a intervalos de tiempo regulares. Esta es una base que puede emplearse para proyectos mucho mas ambiciosos y complejos. En otros artículos iré compartiendo mas ideas y mas aplicaciones de esta interesante placa, siempre programados en Micropython.
Cualquier duda o sugerencia, puedes dejarla en la sección de comentarios. Hasta la próxima!
Como siempre un excelente trabajo !!!
Lo he seguido al pie de la letra y me ha funcionado.
Muchas gracias Profe !!!
Saludos desde México.
Gracias Fredy! Que bueno que te ha funcionado!
Es posible tomar videos con este dispositivo?
Hola Lalo, hasta donde yo he podido ver, solo para imagenes fijas.