4.17. Ajustes do sensor

Além de pixformat() e framesize(), a classe CSI expõe um punhado de controles por sensor que quase toda aplicação acaba precisando mais cedo ou mais tarde – orientação de montagem, exposição, ganho, balanço de branco e alguns recursos de depuração. Cada um deles mapeia diretamente para um conceito de sensor abordado anteriormente; a API apenas fornece um handle Python para a escrita de registrador que o driver faz por baixo dos panos.

Todos os métodos abaixo atuam sobre o sensor subjacente. Todos eles realizam escritas de registrador pelo barramento de controle I2C do sensor, então o custo é da ordem de microssegundos e a nova configuração passa a valer na próxima exposição – tipicamente o próximo snapshot().

4.17.1. Orientação

A câmera não sabe em que posição foi montada. Dois sinalizadores de inversão aplicados no sensor colocam a imagem na orientação correta antes que qualquer pixel deixe o chip:

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

hmirror() inverte da esquerda para a direita e vflip() inverte de cima para baixo. Juntos, eles cobrem os casos que surgem na prática: uma placa montada de cabeça para baixo (ambos os sinalizadores True), uma placa atrás de um espelho de primeira superfície (apenas hmirror) ou uma olhando para uma cena refletida vista de baixo (apenas vflip).

Como a inversão acontece na lógica de leitura do sensor, não há custo de CPU nem sobrecarga de memória – o quadro chega ao frame buffer já orientado.

4.17.2. Exposição

A exposição é o tempo de integração – quanto tempo o fotodiodo em cada pixel coleta carga antes de a linha ser lida, em microssegundos. O driver começa com a malha de exposição automática do sensor em execução, de modo que a câmera tenta manter o valor médio dos pixels próximo de um alvo. Desabilitar a malha fixa a exposição em um valor escolhido pela aplicação:

csi0.auto_exposure(False, exposure_us=8000)

Uma exposição fixa é a escolha certa quando o brilho da cena é estável e a aplicação precisa de um borrão de movimento previsível ou de intensidade consistente de quadro a quadro para limiarização. Ler de volta a exposição atual – seja ela definida pela malha ou pela aplicação – é uma chamada separada:

us = csi0.exposure_us()

Chamar auto_exposure() com True e sem valor de exposição devolve o controle para a malha.

4.17.3. Ganho

O ganho é o amplificador aplicado à tensão do pixel antes de ela chegar ao ADC, em decibéis. Assim como a exposição, o driver começa com a malha de ganho automático ligada. Dois padrões aparecem com frequência. Limitar o teto permite que a malha se adapte à iluminação, mas a impede de amplificar ruído indefinidamente em cenas escuras:

csi0.auto_gain(True, gain_db_ceiling=16)

Fixar um ganho é a jogada certa quando a aplicação também fixa a exposição – a estabilidade do ganho importa para aplicações que comparam valores de pixel de quadro a quadro, como rastreamento de cor:

csi0.auto_gain(False, gain_db=0)

O ganho atual é lido de volta por gain_db(). Sempre que a aplicação desabilitar o ganho automático, ela também deve desabilitar o balanço de branco automático e a exposição automática – caso contrário, as malhas de controle ainda ativas puxarão a imagem de formas que anulam o ganho fixo.

4.17.4. Balanço de branco

O balanço de branco é o ganho por canal que o ISP aplica aos canais vermelho, verde e azul que saem do estágio de debayer para que um objeto branco pareça branco sob qualquer cor de luz. A malha de balanço de branco automático calcula esses três ganhos a partir das estatísticas por região que o ISP coleta em cada quadro e os aplica no quadro seguinte.

A maioria das aplicações deixa a malha em execução. O rastreamento de cor é a exceção comum – os ganhos são também o que a malha vai ajustar para perseguir um objeto colorido, então, se a aplicação está tentando encontrar um blob vermelho, a malha vai discretamente atenuar o canal vermelho e o blob deixará de corresponder. Travar a malha resolve isso:

csi0.auto_whitebal(False)

Passe uma tupla (r, g, b) explícita em decibéis para calibração de cor repetível – os mesmos ganhos entre placas e sessões:

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

Os ganhos atuais são lidos de volta como uma tupla por rgb_gain_db().

4.17.5. Limite de taxa de quadros

Por padrão, os sensores operam em sua taxa de quadros nativa – de 30 a 60 quadros por segundo na maioria dos componentes, muito mais alta nos sensores de alta velocidade quando o framesize é pequeno o suficiente. Limitar a taxa permite que a aplicação restrinja a câmera a qualquer ritmo que o processamento subsequente consiga acompanhar:

csi0.framerate(15)

Em sensores que suportam um controle de taxa por hardware, a chamada também alonga o orçamento de exposição por quadro, o que pode ajudar com pouca luz; nos demais, o driver simplesmente descarta os quadros extras no nível do frame buffer.

4.17.6. Padrão de teste

O padrão de teste de barras de cor está embutido na maioria dos sensores e é útil para separar um problema de captura de imagem de um problema de saída. Ligá-lo contorna o arranjo de fotodiodos e envia um padrão fixo pelo mesmo caminho de dados de pixel:

csi0.colorbar(True)

Se o padrão de teste parece correto mas a imagem ao vivo não, a falha está na óptica ou no front-end analógico do sensor; se até o padrão de teste estiver corrompido, o problema está em algum lugar no barramento de dados de pixel ou na configuração de pixformat() / framesize(). Passe False para voltar à imagem ao vivo.

Consulte csi.CSI para a API completa, incluindo os comandos ioctl() específicos do sensor que expõem controles exclusivos de famílias de sensores específicas.