sexta-feira, 11 de março de 2011

Criação de imagem anaglífica

Este será um post mais técnico, que os computeiros irão adorar. Irei disponibilizar o código que desenvolvi em OpenCV para criação de uma imagem anaglífica (vermelho-ciano) a partir de um par estéreo de imagens. O OpenCV é uma ótima biblioteca escrita em C que possui várias funções otimizadas para visão computacional e processamento de imagens. Ele tem sido utilizado em diversos projetos, inclusive para hacking do Kinect. Mais para frente, farei um ou mais posts somente para detalhar a biblioteca e seu uso.

Sobre o código

A utilização do OpenCV deixa o código bem simples e facilita o trabalho com imagens. Há uma estrutura já pronta para imagens chamada de IplImage , na qual podemos definir vários parâmetros, tais como dimensões (altura e comprimento), espaço de cores (grayscale, RGB, YCbCr, etc.), densidade de bits para cada canal de cor (isto é, número de bits para armazenar os valores de cada canal de cor), dentre outros descritos na documentação.

O código lê dois argumentos da linha de comando (argv[1] e argv[2]) como sendo o caminho para as duas imagens do par estéreo, sendo argv[1] a imagem correspondente ao lado direito e argv[2] a imagem correspondente ao lado esquerdo. Logo após, faço um tratamento de erros bem simples, verificando se os arquivos puderam ser abertos e se as imagens possuem mesma dimensão. Uma ressalva para o carregamento das imagens: o OpenCv as carrega no formato RGB, porém, com ordem alterada dos canais, ficando de fato sendo BGR. Isto é importante na hora de percorrermos a matriz que representa a imagem.

Partimos então para dois loops for, percorrendo coluna a coluna e depois linha a linha. Para cada linha, utilizam-se dois ponteiros, um para cada imagem. Observem que o valor atribuído aos ponteiros é feito através de um cálculo mais complexo do que um row++. É um pouco difícil de explicar isso sem detalhar a estrutura do IplImage, então peço para que tenham fé :-) pois é desse jeito que tem que ser feito para se ter certeza de ter passado corretamente para a próxima linha.

A estrutura do IplImage armazena em apenas uma matriz os valores associados a cada canal, diferente de estruturas clássicas que criam uma matriz para cada canal. Sendo assim, a cada três colunas teremos as informações correspondentes a um pixel, ou seja, teremos sempre os valores dessa maneira: B1G1R1, B2G2R2, B3G3R3, e assim por diante. Tendo isso em vista, zeramos os valores dos canais azul e verde na imagem correspondente ao lado direito (primeira e segunda colunas de cada pixel) e zeramos também os valores do canal vermelho na imagem correspondente ao lado esquerdo (terceira coluna de cada pixel).

Feito isso, criamos uma nova estrutura IplImage para armazenar a junção do par estéreo, copiando as propriedades de dimensão, densidade de bits e número de canal de uma das imagens. Logo após, utilizamos a função cvAdd, cujos parâmetros são a imagem direita, esquerda e a nova, e por fim, salvamos a nova imagem, em formato BMP. Mantendo uma boa prática de programação, liberamos os ponteiros utilizados antes de sair do programa.

Captura das imagens

O ideal seria ter duas câmeras acopladas e calibradas para fazer a captura de uma cena. Como isso é caro e demanda tempo, usamos o "jeitinho brasileiro". O problema com isso é a imperfeição de não conseguir capturar duas imagens ao mesmo tempo, ou seja, o lugar e os elementos dos quais queremos tirar a foto devem ser estáticos. Outro problema é com relação à posição da câmera: ela deve deslocar-se apenas horizontalmente, mantendo a mesma altura e ângulo de visão. Além disso, temos que levar em conta a qualidade da imagem criada pela câmera e se internamente já não é feita alguma compressão, como por exemplo, conversão para JPEG, o que pode interferir na transformação. Isso torna a conversão para anaglífico um pouco difícil e de baixa qualidade, porém, com teimosia você obtém uma imagem com bom efeito.

Sugiro utilizar uma câmera com tripé em um piso plano. Faça uma linha reta no chão e marque as duas posições onde a câmera deve ficar na hora de bater a foto. Durante o deslocamento da câmera, tenha o máximo de cuidado para não movimentá-la no eixo vertical, alterando o ângulo de visão.

Outra solução para os preguiçosos é utilizar o Google e fazer uma busca de imagens por “estereo pair”.

Utilização do programa

Para usuários Windows: Abra uma janela de comando e vá até a pasta onde você descompactou o pacote RAR. Digite então o nome do programa, o caminho para a imagem da direita e o caminho para a imagem da esquerda e aperte ENTER. Uma dica é deixar as duas imagens na mesma pasta em que se encontra o programa, desse jeito, basta apenas digitar o nome das imagens. Veja a Figura 1 para ter um exemplo de execução.

Figura 1 - Exemplo de execução do código (clique para aumentar)


Para usuários Linux, sorry, mas eu não uso. Se você usa, tenho certeza que já tem conhecimento suficiente para usar os comandos de extrair e executar. Caso contrário, deixe um comentário e a gente sofre junto.

Seguem abaixo duas imagens que eu fiz com a minha câmera aqui em casa. Notem que sou pobre, e a qualidade da minha câmera é péssima. Mesmo assim, obtive imagens com efeito estereoscópico, porém de baixíssima qualidade, admito.





Para dúvidas no código ou execução, deixe um comentário.

Referência

Utilizo bastante o livro Learning OpenCV, escrito pelos próprios criadores da biblioteca.

Download do código

Faça o dowload clicando aqui.

sexta-feira, 4 de março de 2011

Informações de Profundidade - Disparidade e Paralaxe

Duas informações importantíssimas para a percepção e reprodução de vídeos estereoscópicos, muito exploradas para passar a sensação de profundidade. O conceito de ambas é semelhante, sendo diferenciadas pelo meio em que ocorrem.

Vamos falar primeiro da disparidade. Como já mencionado no primeiro post desse blog, possuímos visão binocular, o que faz com que cada um de nossos olhos enxerguem a mesma imagem sob uma perspectiva diferente, devido ao fato de eles estarem cerca de 6,5cm distantes horizontalmente. Com isso, ao olharmos uma paisagem, por exemplo, os diversos elementos presentes na cena ocupam posições muitas vezes diferentes em cada retina. A distância entre as posições de um elemento em cada retina é chamada de disparidade. Podemos enganar os nossos olhos com um simples exemplo para observar a disparidade. Observe a imagem abaixo.

Imagem para exemplificar o conceito de disparidade
Posicione seu polegar entre você e a imagem, de forma que ela ainda continue sendo vista por você.  Agora foque sua atenção no polegar, isto é, concentre seus olhos nele. Você percebe que a imagem começa a ficar como que duplicada. E esse efeito aumenta se você aproximar ainda mais seu polegar para perto de você. A disparidade é a distância entre essas duplicatas. Obtemos o mesmo efeito fazendo o reverso: focalizando o olhar na imagem e vendo o polegar sendo duplicado.

A paralaxe segue o mesmo conceito de distância, mas agora ao invés de ser observado no olho, a paralaxe ocorre em dispositivos de reprodução, como telas ou monitores. Para vídeos estereoscópicos, uma das formas de captura é utilizando um dispositivo especial que possui duas câmeras acopladas horizontalmente e calibradas para fazer a captura de maneira simultânea, simulando a nossa visão. Com isso, é gerado um par de vídeos, denominado par estéreo. Ao sobrepormos estes vídeos, podemos notar o deslocamentos de alguns elementos. A distância de tal deslocamento é a paralaxe.

Pode-se dividir a paralaxe em quatro tipos, sendo que para cada um obtemos um efeito diferente na visualização estereoscópica.

  • Paralalaxe Zero: quando a distância entre os pontos correspondentes em uma imagem é zero. Isso significa que o foco das câmeras estava nesse ponto (do mesmo jeito quando focamos no polegar).
  • Paralaxe Positiva: A distância entre os pontos está entre 0 e uma constante t, dando a sensação de que os objetos estão distantes.
  • Paralaxe Negativa: o inverso da positiva, a distância entre os pontos gera um valor negativo. É com ela que temos a sensação de objetos “saltando” da tela.
  • Paralaxe Divergente: é quando a distância entre os pontos ultrapassa a constante t, causando um efeito que não é similar a nenhum outro na visão humana, e com isso, causando desconforto na visualização.

That's all, folks! Fim de semana com o feriadão de Carnaval chegando. Vou aproveitar bastante.... jogando Playstation 3 :-) Até mais!

Referências:


StereoGraphics Developers' Handbook – Stereographics Corporation. Escrito em inglês, pode ser utilizado como introdução para estereoscopia, explica as variadas informações de profundidade, bem como formatos de reprodução.

Imagem do cisne negro