Alcance ou intervalo dinâmico (em inglês, dynamic range) em fotografia descreve a razão entre as intensidades mínimas e máximas mensuráveis de luz (preto e branco, respectivamente). Porém, no mundo real nunca encontramos preto ou branco verdadeiros, apenas graus diversos de intensidade das fontes de luz e reflectância dos objetos.
Uma imagem HDR (high dynamic range) é uma imagem capaz de representar um intervalo maior de luminosidade do que é possível com técnicas convencionais de imagens digitais ou fotografia. O objetivo é mostrar um alcance similar ao que experimentamos com a visão humana. Esta, através de adaptação da íris e outros mecanismos, se ajusta constantemente e automaticamente de acordo com a variação de iluminação presente nos ambientes. O cérebro humano interpreta continuamente essa informação, de forma que possamos enxergar em uma variedade enorme de condições de iluminação.
Por exemplo, uma imagem que pode se beneficiar dessa técnica é a que aparece abaixo: ela contém luz solar direta e muito intensa, mas também áreas de sombra. Ao capturarmos essa imagem com uma câmera digital, precisamos decidir se desejamos ajustar a exposição para a parte clara ou para a parte escura - nesta imagem, estamos expondo a parte clara.
Se decidirmos ajustar a exposição para a parte escura, a parte clara desaparecerá (dizemos que ficará "superexposta"):
Uma imagem HDR resolve esse problema, pois consegue capturar toda essa variação de intensidade luminosa. Mas como produzir imagens desse tipo? Uma técnica utilizada é combinar várias imagens obtidas com uma câmera (não HDR), mas com exposições diferentes (o que é denominado bracketing em fotografia). Por exemplo, a partir de 5 imagens do mesmo ambiente, geramos uma imagem HDR:
Porém, a maior parte das telas atuais de computador e TVs não têm a capacidade de exibir toda a variação luminosa em uma imagem HDR - apenas recentemente começaram a aparecer as TVs Ultra HD (4K) com HDR, bem como alguns modelos de tablets e celulares. Portanto, também é preciso desenvolver técnicas para exibir os resultados. Essas técnicas são chamadas, genericamente, de mapeamentos tonais (tone mapping). O objetivo é reduzir o contraste de uma imagem HDR, de forma a exibi-la em dispositivos com alcance dinâmico inferior.
Neste trabalho, você implementará um programa para ler uma imagem em um formato HDR e exibi-la usando um algoritmo de tonemapping. Um exemplo pode ser visto abaixo:
Ao ser iniciado, o programa deve carregar um arquivo de imagem. Essas imagens estão em um formato especial (sufixo .hdf). É importante entendermos a diferença entre esse formato e uma imagem convencional. Imagens são geralmente representadas por uma matriz de pontos (pixels)onde cada cor é definida por 3 componentes: vermelho (R), verde (G) e azul (B). Cada uma dessas componentes usualmente é codificada em um byte, o que produz 3 bytes por pixel (24 bits) - ou seja, 16 milhões de possíveis cores. Em outras palavras, as intensidades (R, G, B) variam de 0 a 255, onde 0 é escuro e 255 é claro.
Veja abaixo como diversas cores são representadas nesse formato - cada cor está expressa pelas componentes RGB em hexadecimal.
Já uma imagem HDR pode possuir valoresmaiores que esses limites, sendo geralmente representada em ponto flutuante (valores float, por exemplo). O formato HDF codifica as cores de forma diferente (ver seção 2.1↓), mas na prática o resultado é uma representação float.
Após a leitura da imagem, o usuário deverá definir o fator de exposição desejado, a fim de "clarear" ou "escurecer" a imagem. E finalmente, o programa deve aplicar o algoritmo de tonemapping e converter a imagem para 24 bits.
A imagem no formato HDF consiste primeiramente em um header, onde as informações estão organizadas da seguinte forma:
Os caracteres HDF, identificando a imagem nesse formato
A largura da imagem em pixels, armazenada como um inteiro sem sinal
A altura da imagem em pixels, armazenada como um inteiro sem sinal
Após a leitura do header, o programa deve alocar memória suficiente para armazenar o restante do arquivo, que contém os pixels da imagem. Cada pixel é codificado em 4 bytes:
Componente R da cor
Componente G da cor
Componente B da cor
Mantissa
Esse formato é capaz de representar dados em ponto flutuante de uma forma bastante econômica. Para obter os valores RGB float a partir dos 4 bytes do pixel, basta realizar o seguinte cálculo:
Onde é o fator de conversão calculado a partir da mantissa:
Por exemplo, supondo o trecho da imagem abaixo:
O primeiro pixel da imagem tem os valores hexa (0x80, 0x40, 0x20, 0x81) - ou em decimal (128,64,32,129). O fator de conversão é então .
Portanto, os pixels convertidos para float resultam em: (1.0, 0.5, 0.25)
Observe que por ser uma imagem HDR, não há limite superior definido. Ou seja, as componentes , e podem assumir qualquer valor.
Como já mencionado, mapeamento tonal ou tonemapping tem o objetivo de reduzir o alcance dinâmico de uma imagem, de forma que ela possa ser exibida em um disposito não HDR. Há duas categorias principais de algoritmos desse tipo: tonemapping global e tonemapping local. O primeiro tipo, onde está o algoritmo que será implementado, visa alterar todos os pixels da imagem seguindo um mesmo critério (ou algoritmo). Já o segundo tipo leva em consideração outras características da imagem, como bordas de objetos, etc. Esse tipo de algoritmo é muito mais sofisticado e geralmente produz resultados melhores.
Neste trabalho, implementaremos um algoritmo de tonemapping global, denominado tonemappingpor escala.
A ideia desse algoritmo é simples: o objetivo final é obter componentes de cor no intervalo 0...1, de forma que possam ser mapeadas diretamente para RGB de 24 bits (0...255). Portanto, uma forma de fazer isso é dividir cada componente pelo seu próprio valor acrescido de uma constante qualquer:
A constante k pode ser um valor entre 0 e 1, como 0.5.
Após a aplicação do fator de exposição e do algoritmo de tonemapping, o resultado ainda será uma imagem representada por floats, mas agora possivelmente dentro do invervalo 0...1. Portanto, para converter cada pixel de entrada já corrigido pelo passo anterior ( para RGB 24 bits , basta fazer:
Ou seja, limita-se o valor a 1 e multiplica-se por 255, convertendo o resultado para inteiro no final - tecnicamente, deve ser gerada um vetor de unsigned char (bytes sem sinal).
O arquivo hdr-base.zip contém o projeto completo do Code::Blocks para a implementação do trabalho. Esse código já implementa a exibição de uma imagem 24 bits na tela gráfica, usando a biblioteca OpenGL. O projeto pode ser compilado no Linux ou no Windows, bastando selecionar o target desejado no Code::Blocks.
Se for utilizado o Mac OSX, o projeto também pode ser compilado manualmente pelo terminal:
O arquivo imagens-hdf.zip contém diversas imagens que podem ser utilizadas para testar o programa. Cada imagem é oferecida em duas versões: formato .hdf e em JPEG, para conferência.
Os trabalhos são em duplas ou individuais. A pasta do projeto deve ser compactada em um arquivo .zip e este deve ser submetido pelo Moodle até a data e hora especificadas.
Não envie .rar, .7z, .tar.gz - apenas .zip.
O código deve estar identado corretamente (o Code::Blocksfazissoautomaticamente).
A nota do trabalho depende da apresentação deste no laboratório, na data marcada. Trabalhos entregues mas não apresentados terão sua nota anulada automaticamente. Durante a apresentação será avaliado o domínio da resolução do problema, podendo inclusive ser possível invalidar o trabalho quando constatada a falta de conhecimento sobre o código implementado.
A cópia parcial ou completa do trabalho terá como conseqüência a atribuição de nota ZERO ao trabalho dos alunos envolvidos. A verificação de cópias é feita inclusive entre turmas.
A cópia de código ou algoritmos existentes da Internet também não é permitida. Se alguma idéia encontrada na rede for utilizada na implementação, sua descrição e referência deve constar como comentários no código.