Calibração de câmera a partir de um padrão colocado na cena - Parte I

Download

Requer MS Visual Studio 2005 e OpenCV 1.0. Recomendo usar o .vcproj do trabalho 1.

Este programa é capaz de reconhecer os cantos internos de um tabuleiro quadriculado. Os cantos encontrados são representados na tela com indicadores vermelhos. Quando todos os cantos previstos são encontrados, os indicadores são interligados e recebem coloração diferenciada.

Para encontrar os cantos do tabuleiro, a função cvFindChessboardCorners é chamada, recebendo a imagem e as dimensões esperadas do tabuleiro. Ela retorna o número de cantos encontrados e a posição de cada um.

Dois métodos são utilizados. O primeiro é efetuar a busca de cantos diretamente sobre o vídeo de entrada. O segundo utiliza uma etapa intermediária para aumentar o contraste da imagem. Isto é feito da seguinte forma:

1. Obtém-se a área retangular mínima que engloba todos os cantos encontrados no último frame;
2. Calcula-se a média do valor dos pixels contidos nessa área;
3. Um filtro de threshold binário é aplicado. Os pixels com valor inferior à média tornam-se pretos, e os demais tornam-se brancos.

A aplicação desse filtro mostrou-se vantajosa em alguns vídeos, enquanto que em outros houve uma degradação dos resultados. Portanto, uma boa maneira de utilizá-lo é fazer um "OU" lógico entre os resultados com e sem filtro, aproveitando o que tiver conseguido detectar o tabuleiro corretamente.


Calibração de câmera a partir de um padrão colocado na cena - Parte II

Download

Requer MS Visual Studio 2005 e OpenCV 1.0. Recomendo usar o .vcproj do trabalho 1.

Partindo da detecção do tabuleiro descrita na Parte I, o algoritmo de Zhang 2D, disponível no OpenCV, é aplicado para encontrar os parâmetros intrínsecos da câmera. Este algoritmo exige que pelo menos seis capturas com o tabuleiro em ângulos diferentes sejam feitas para encontrar os valores corretos. Para isso, um sistema automático de calibração com duas etapas é acionado durante a parte inicial do vídeo, conforme descrito a seguir.

1. Detecção
Durante o andamento inicial do vídeo, quadros cuja detecção de tabuleiro foi bem sucedida são periodicamente armazenados numa lista interna do OpenCV (CvSequence). Quando o número de quadros armazenados é maior que 6, uma tentativa de calibração é feita com uma chamada ao cvCalibrateCamera2, que retorna a matriz instrínseca da câmera. Em seguida, calcula-se a média do erro de reprojeção dos pontos do tabuleiro, que é a diferença entre a posição verdadeira e a retornada pelo cvProjectPoints2 com a matriz intrínseca obtida. Caso o erro seja maior que o esperado, mais quadros são adicionados à lista e uma nova tentativa é feita. O processo continua até que a média de erro atinja um valor suficientemente pequeno. Então, o programa passa para a etapa de otimização.

2. Otimização
A função cvCalibrateCamera2 é novamente chamada, utilizando a matriz intrínseca obtida no passo anterior como chute de convergência inicial (CV_CALIB_USE_INTRINSIC_GUESS), com o intuito de melhorar ainda mais a precisão dos seus valores. O erro de reprojeção é calculado mais uma vez e, caso tenha diminuído, a nova matriz intrínseca é adotada. Finalmente, a câmera está calibrada.

Em posse dos parâmetros intrínsecos (distância focal e centro óptico), podemos montar a matriz Projection do OpenGL. Os valores escolhidos para os parâmetros near e far foram 0.1 e 100, respectivamente. A matriz está ilustrada abaixo:

Projection

Depois, calculamos a cada quadro a matriz extrínseca, composta pela rotação e translação da câmera no dado instante. Para isso, chamamos a função cvFindExtrinsicCameraParams2. Ela recebe a matriz intrínseca e o conjunto de pontos encontrados para os cantos do tabuleiro no quadro atual. São retornados o vetor de translação e o de rotação, na forma de ângulos de Rodrigues.

Precisamos então montar a matriz Modelview do OpenGL a partir dos parâmetros de translação e rotação obtidos. O vetor de rotação é transformado numa matriz 3x3 convencional através da função cvRodrigues2. Em seguida, a matriz Modelview é preenchida com o auxílio das funções glTranslate e glRotate, resultando nesta forma:

Modelview

Os objetos são então desenhados na cena considerando que a origem dos eixos de coordenadas está situada num dos cantos do tabuleiro. Porém, o programa poderia se confundir durante uma rotação do tabuleiro, fazendo-o escolher o canto diagonalmente oposto do tabuleiro, o que quebraria a continuidade do movimento. Para evitar isso, é feito um teste de distância entre a origem encontrada no quadro atual e no quadro anterior. Se esta distância for quase igual ou maior que o comprimento da menor diagonal do tabuleiro, conclui-se que outro canto foi detectado como origem, tornando-se necessária uma inversão na ordenação dos pontos para que o canto correto seja escolhido e o movimento fique contínuo.

Para demonstrar o funcionamento, o programa desenha os eixos xyz na origem e um teapot com uma certa translação. Atualmente, ele desenha apenas quando todos os cantos do tabuleiro são encontrados com sucesso. Uma possível melhoria é a de tentar encontrar os cantos que faltam a partir dos que foram encontrados, e assim haveria menos falhas durante a execução de vídeos de má qualidade.


Voltar ao índice