4.13. Formatos de pixel

O estágio final do pipeline do ISP empacota cada pixel em um layout de bytes específico na memória. O formato escolhido equilibra qualidade de imagem, tamanho em memória e como o código subsequente lê os bytes de volta. Um punhado de formatos predomina.

4.13.1. RAW (Bayer)

A saída padrão é Bayer bruto – o mesmo mosaico de um canal por pixel que o sensor produz. Um byte por pixel, disposto no padrão Bayer: vermelho e verde se alternando nas linhas pares, verde e azul se alternando nas linhas ímpares. Nenhum debayer foi aplicado, então cada célula ainda guarda apenas o valor que seu filtro de cor deixou passar.

O Bayer bruto ocupa um terço da memória de uma imagem RGB de três canais finalizada – um byte por pixel contra três – e nenhum ciclo do ISP foi gasto fazendo o debayer ou convertendo-o. O custo é que o código do usuário precisa fazer o debayer por conta própria antes que qualquer processamento ciente de cor possa rodar.

4.13.2. RGB888

RGB888 é o formato finalizado natural para uma imagem colorida: três bytes por pixel, um para cada um dos canais vermelho, verde e azul, a 8 bits por canal. Vinte e quatro bits por pixel e pouco menos de dezessete milhões de cores distintas.

RGB888 é a referência conceitual para imagens coloridas finalizadas e a maioria dos softwares fora da placa o entende. Em hardware embarcado, sua principal desvantagem é o tamanho de pixel de 24 bits – que não é múltiplo do tamanho de palavra do processador, é incômodo para alinhamento de memória e é 50% maior que o próximo formato abaixo.

4.13.3. RGB565

RGB565 empacota cada pixel em dois bytes: cinco bits de vermelho, seis bits de verde, cinco bits de azul. O bit extra de verde reflete a maior sensibilidade do olho ao verde, e corresponde ao peso dobrado do canal verde no padrão Bayer.

RGB565 é o formato de cor padrão na OpenMV Cam. Dois bytes por pixel é alinhado a 16 bits, o que se encaixa nas larguras de dados naturais do MCU – cargas, armazenamentos e aritmética de pixels todos rodam em velocidade máxima, e muitas operações podem processar um par de pixels de uma vez. Os pixels de 24 bits do RGB888 não se alinham dessa forma e pagam um custo em cada acesso. A economia de memória de 33% sobre o RGB888 também se acumula: QVGA (320 x 240) ocupa 150 KB em RGB565 contra 225 KB em RGB888, e a diferença cresce com a resolução.

O compromisso é 65 mil cores distintas em vez de dezessete milhões. Para a maioria das tarefas de visão de máquina a diferença é invisível, porque os algoritmos reduzem o quadro a representações limiarizadas ou com detecção de bordas que de qualquer forma descartam a maior parte do detalhe de cor. Para visualização humana, os bits faltantes aparecem como leve banding em gradientes de cor suaves, mas não como algo que o olho perceba de imediato.

4.13.4. YUV422

YUV422 divide a cor de cada pixel em um valor de luminância (Y) e dois valores de crominância (U e V), e então subamostra a crominância porque a visão humana é muito menos sensível à variação de cor do que à variação de brilho. Cada pixel carrega seu próprio Y, mas pares de pixels adjacentes compartilham um U e um V. O layout de bytes para cada par é de quatro bytes – Y0, U, Y1, V – o que dá, em média, dois bytes por pixel, idêntico ao RGB565.

Os dois bytes, porém, significam coisas diferentes dos do RGB565. O canal Y sozinho já é uma imagem em escala de cinza de 8 bits pronta para uso, que é o que a maioria dos algoritmos clássicos de visão de máquina (detecção de bordas, casamento de modelos, análise de blobs) realmente consome; os canais U e V carregam a informação de cor para o pequeno número de algoritmos que precisam dela.

YUV422 é a escolha certa quando o pipeline precisa de ambos – um algoritmo de estágio inicial que lê apenas Y seguido de um estágio posterior que usa a croma para decisões de cor mais finas – porque os valores de Y já estão ali prontos para uso, sem precisar de conversão de espaço de cor.

4.13.5. Escala de cinza

A escala de cinza usa um byte por pixel: apenas o valor de luminância, sem cor alguma. É o menor formato finalizado – metade do tamanho de RGB565 e YUV422, um terço do tamanho de RGB888.

A maioria dos algoritmos clássicos de visão de máquina trabalha em escala de cinza de qualquer forma, então descartar o canal de cor diretamente na saída do sensor costuma ser a escolha mais simples e mais eficiente em memória. Detecção de bordas, busca de linhas, análise de blobs, decodificação de QR-code, casamento de modelos e detecção de AprilTag todos rodam em escala de cinza e se beneficiam do buffer menor.

4.13.6. Outros formatos

Alguns formatos que a OpenMV Cam pode produzir não saem do pipeline do ISP como parte do fluxo normal.

BINARY é um bit por pixel – a menor representação possível. Usado para imagens limiarizadas, buffers de máscara e a saída de qualquer operação que distingue apenas entre correspondência e não-correspondência em cada pixel.

JPEG é um formato de cor comprimido. Alguns sensores incluem um codificador JPEG no próprio chip e podem entregar quadros comprimidos em JPEG diretamente; para sensores sem ele, o MCU executa um codificador JPEG sobre um quadro RGB ou em escala de cinza finalizado após o ISP. De qualquer modo, a saída é um fluxo de bits JPEG, útil para salvar quadros em armazenamento ou enviá-los por um enlace de largura de banda limitada.

PNG é um formato comprimido sem perdas. Os sensores não produzem PNG diretamente; o MCU comprime um quadro RGB ou em escala de cinza finalizado sob demanda. Útil quando a largura de banda ou o armazenamento importa, mas a compressão com perdas que o JPEG aplica descartaria informação que a aplicação precisará depois.