Aprende a programar la ESP32-CAM en Micropython. Parte 2

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).

Fig. 1: Descarga de una imagen a la computadora

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!

Más info

Completa información de la ESP32-CAM

Navegación de la serie<< Aprende a programar la ESP32-CAM en Micropython. Parte 1

16 comentarios en «Aprende a programar la ESP32-CAM en Micropython. Parte 2»

  1. Buenos días,
    Acabo de descubrir tu blog y me ha parecido genial, gran trabajo!

    He buscado mucho y no he encontrado, tengo el firmware de Shariltumin (1.18), al inicializar la cámara con:

    import camera
    camera.init(0, xclk_freq=20000000)

    (o con xclk_freq_hz, como pones tú)
    Me da el error: TypeError: function doesn’t take keyword arguments
    Como si la función init no admitiera parámetros (incluso probando con otros argumentos).

    Alguna idea?

    Muchas gracias.

    Responder
    • Hola Enrique, muchas gracias!
      Un keyword argument es el que se especifica como key=valor. En tu caso puede ser que camera.init no espere xclk_freq=20000000 sino simplemente 20000000.
      Cuando escribí este artículo probé el firmware de Shariltumin y me pareció que tenía poca funcionalidad. Veo que ahora hay una actualización del 2022. Ha mejorado en este tiempo?

      Responder
      • Gracias por responder tan rápido.
        Si no es parámetro con nombre, no sé en qué orden tendría que poner la frecuencia. No encuentro documentación. Me parecía raro que cambiaran los parámetros en la función camera.init de un custom firmware a otro.
        Intento ganar más FPS para hacer streaming y he leído que una forma puede ser cambiando la frecuencia.

        Empecé con el ESP32CAM con tu blog e instalé el firm de Lemariva, pero vi que el firm de Shariltumin se actualizaba más a menudo y me quedé con ese (además si no recuerdo mal el Lemariva, no tenía algo que el que tengo sí, creo que la versión de MP era la 1.14 en vez de la 1.18).

        Responder
        • Ah, ya entiendo… estás llamando a camera.init con el formato del firmware de lemariva en el firmware de Shariltumin. Estoy en lo correcto?
          Bueno, no necesariamente tienen que coincidir los parámetros, puede que cada programador lo haga a su manera. Dando un vistazo al repositorio de Shariltumin veo que la documentación es muy pobre (creo que por eso tambien decidi no utilizarlo) y en los pocos ejemplos que veo se invoca a camera.init sin parámetros. Puede que me equivoque pero tal vez no acepta parámetros y la configuración es fija, lo que explicaría el mensaje de error.

          Responder
          • Correcto. Es todo como dices.
            Eso me estaba temiendo, pero viendo el GitHub el .c del modulo, parece que tiene el parámetro, por eso me parecía raro. Tampoco tiene los nombres de las constantes… Así que está claro que iguales no son.
            Pero será lo que dices, pensaba que todos los módulos de camera eran iguales, independientemente de quien compilara todo el firm.
            Como veo que Lemariva ha actualizado al menos la versión de MP igual le doy otra oportunidad.
            Hay dos ficheros y parecen que los dos tienen cámara, sabes que diferencia hay entre ellos?

            micropython_cmake_9fef1c0bd_esp32_idf4.x_ble_camera.bin y micropython_camera_feeeb5ea3_esp32_idf4_4.bin

            Así mirando un poco rápido los nombres que uno tiene BT y la cámara y el otro no. Sabes si es la única diferencia?

            Un saludo

          • Hola Enrique. En mis pruebas, el que dice ble_camera no me funcionó, pero puede que exista una nueva versión. La verdad no sé en que se diferencian, como dices será que añade algo para BT…

  2. Intento cargar un programa en micropython con la ESP32 Cam pero la que tiene el sensor PiR incorporado, además de la OLED; el SP32, el micro ESP32 es el ESP32-WROER-BMe sale el siguiente error: Error= Camera Init Failed. No se que puede ser… Gracias.

    Responder
    • Hola Amado. Por lo que me describes me parece que tu cámara es la TTGO T-Camera de la marca Lilygo. Si es así, debe tener conexiones diferentes a la de la ESP32-CAM que utilicé yo y el firmware no está adaptado para ese modelo en particular.

      Responder
  3. Buenas profe, acabo de seguir los pasos que indicas y pude instalar firm y correr perfectamente el programa. El inconveniente que tengo es que cuando descargo las imagenes creadas no las puedo abrir me indica que están dañadas. que puede llegar a ser? estimo que debe ser un tema de formato…. agradeceria tu ayuda. saludos

    Responder

Responder a Fredy Cancelar la respuesta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Habilitar notificaciones OK No, gracias