4.17. Controles del sensor

Más allá de pixformat() y framesize(), la clase CSI expone un puñado de controles por sensor que casi cualquier aplicación acaba necesitando tarde o temprano: orientación de montaje, exposición, ganancia, balance de blancos y algunas ayudas para la depuración. Cada uno se corresponde directamente con un concepto del sensor tratado antes; la API simplemente proporciona un manejador en Python para la escritura de registro que realiza el controlador por debajo.

Todos los métodos a continuación actúan sobre el sensor subyacente. Todos ellos envían escrituras de registro a través del bus de control I2C del sensor, por lo que su coste es de microsegundos y el nuevo ajuste surte efecto en la siguiente exposición, normalmente la siguiente snapshot().

4.17.1. Orientación

La cámara no sabe en qué orientación se ha montado. Dos indicadores de volteo aplicados en el sensor enderezan la imagen antes de que cualquier píxel salga del chip:

csi0.hmirror(True)
csi0.vflip(True)

hmirror() voltea de izquierda a derecha y vflip() voltea de arriba a abajo. Juntos cubren los casos que surgen en la práctica: una placa montada al revés (ambos indicadores True), una placa detrás de un espejo de superficie frontal (solo hmirror), o una que observa una escena reflejada desde abajo (solo vflip).

Como el volteo ocurre en la lógica de lectura del sensor, no hay coste de CPU ni sobrecarga de memoria: el fotograma llega al framebuffer ya orientado.

4.17.2. Exposición

La exposición es el tiempo de integración: cuánto tiempo recoge carga el fotodiodo de cada píxel antes de que la fila se lea, en microsegundos. El controlador arranca con el bucle de exposición automática del sensor en marcha, de modo que la cámara intenta mantener el valor medio de los píxeles cerca de un objetivo. Deshabilitar el bucle fija la exposición a un valor que elige la aplicación:

csi0.auto_exposure(False, exposure_us=8000)

Una exposición fija es la opción correcta cuando el brillo de la escena es estable y la aplicación necesita un desenfoque de movimiento predecible o una intensidad coherente de fotograma a fotograma para la umbralización. Leer la exposición actual, ya sea la que estableció el bucle o la aplicación, es una llamada aparte:

us = csi0.exposure_us()

Llamar a auto_exposure() con True y sin un valor de exposición devuelve el control al bucle.

4.17.3. Ganancia

La ganancia es la amplificación aplicada al voltaje del píxel antes de que llegue al ADC, en decibelios. Al igual que la exposición, el controlador arranca con el bucle de ganancia automática activado. Surgen a menudo dos patrones. Limitar el techo permite que el bucle se adapte a la iluminación pero le impide amplificar el ruido indefinidamente en escenas con poca luz:

csi0.auto_gain(True, gain_db_ceiling=16)

Fijar una ganancia es lo adecuado cuando la aplicación también fija la exposición: la estabilidad de la ganancia importa para aplicaciones que comparan valores de píxeles de fotograma a fotograma, como el seguimiento de color:

csi0.auto_gain(False, gain_db=0)

La ganancia actual se lee con gain_db(). Siempre que la aplicación deshabilite la ganancia automática, también debería deshabilitar el balance de blancos automático y la exposición automática; de lo contrario, los bucles de control que sigan activos alterarán la imagen de formas que anulan la ganancia fija.

4.17.4. Balance de blancos

El balance de blancos es la ganancia por canal que el ISP aplica a los canales rojo, verde y azul que salen de la etapa de debayer para que un objeto blanco parezca blanco bajo cualquier color de luz. El bucle de balance de blancos automático calcula esas tres ganancias a partir de las estadísticas por región que el ISP recopila en cada fotograma y las aplica en el siguiente fotograma.

La mayoría de las aplicaciones dejan el bucle en marcha. El seguimiento de color es la excepción habitual: las ganancias son también lo que el bucle modificará para perseguir un objeto coloreado, así que si la aplicación intenta encontrar una mancha (blob) roja, el bucle atenuará discretamente el canal rojo y la mancha (blob) dejará de coincidir. Bloquear el bucle lo soluciona:

csi0.auto_whitebal(False)

Pasa una tupla (r, g, b) explícita en decibelios para una calibración de color repetible: las mismas ganancias en todas las placas y sesiones:

csi0.auto_whitebal(False, rgb_gain_db=(0.0, 0.0, 0.0))

Las ganancias actuales se leen como una tupla con rgb_gain_db().

4.17.5. Límite de velocidad de fotogramas

Los sensores funcionan a su velocidad de fotogramas nativa de forma predeterminada: de 30 a 60 fotogramas por segundo en la mayoría de los modelos, y mucho más alta en los sensores de alta velocidad cuando el framesize es lo bastante pequeño. Limitar la velocidad permite que la aplicación regule la cámara al ritmo que el procesamiento posterior pueda seguir:

csi0.framerate(15)

En los sensores que admiten un control de velocidad por hardware, la llamada también alarga el presupuesto de exposición por fotograma, lo que puede ayudar con poca luz; en los demás, el controlador simplemente descarta los fotogramas adicionales a nivel del framebuffer.

4.17.6. Patrón de prueba

El patrón de prueba de barras de color está integrado en la mayoría de los sensores y resulta útil para separar un problema de captura de imagen de un problema de salida. Activarlo omite la matriz de fotodiodos y envía un patrón fijo por la misma ruta de datos de píxeles:

csi0.colorbar(True)

Si el patrón de prueba se ve correcto pero la imagen en vivo no, el fallo está en la óptica o en la etapa analógica de entrada del sensor; si incluso el patrón de prueba está corrupto, el problema está en algún punto del bus de datos de píxeles o en la configuración de pixformat() / framesize(). Pasa False para volver a la imagen en vivo.

Consulta csi.CSI para conocer la API completa, incluidos los comandos ioctl() específicos del sensor que exponen controles propios de determinadas familias de sensores.