Usar EasyAR em um engine 3D
Para usar EasyAR em um engine 3D, é necessário renderizar a imagem da câmera e os objetos virtuais. Os objetos virtuais renderizados precisam estar alinhados com a imagem da câmera. Ao renderizar a imagem da câmera, alguns parâmetros durante a geração da imagem e durante a exibição podem não corresponder. Por exemplo, posição, orientação, tamanho do frame, aspect ratio e outros parâmetros da câmera física podem ser diferentes da imagem do display, e isso deve ser considerado durante o rendering. Se for necessário integrar EasyAR a um engine 3D não suportado, preste atenção especial aos detalhes a seguir.
Recortar o padding das bordas da imagem da câmera
Cropping, transposição e encoding de imagem exigem bastante computação. Para reduzir computação e latency, geralmente são usados formatos relativamente raw. Para facilitar o video encoding, imagens geradas por câmeras físicas frequentemente são alinhadas a grids como 8x8, 16x16, 32x32 ou 64x64. Por exemplo, quando uma resolução de 1920x1080 é selecionada em alguns celulares, a imagem de saída pode se tornar 1920x1088, porque 1080 não é múltiplo de 64.

Isso exige remover essas partes extras de padding durante o rendering. Existem várias abordagens possíveis. Uma é especificar a largura ao fazer upload da imagem para a memória de vídeo, por exemplo usando glPixelStorei(GL_PACK_ROW_LENGTH, ...) em OpenGL. Outra é calcular manualmente as coordenadas UV no fragment shader e truncar a parte excedente ao fazer sampling da imagem.
Renderizar acompanhando a rotação da tela
Em celulares, a imagem registrada pela câmera física geralmente é fixa em relação ao corpo do dispositivo e não muda com a orientação de exibição da tela. Porém, mudanças na orientação do corpo do celular afetam como definimos as direções cima, baixo, esquerda e direita da imagem. Durante o rendering, a orientação atual de exibição da tela também afeta a direção da imagem exibida.
Normalmente, durante o rendering, é necessário determinar o ângulo de rotação da imagem da câmera em relação à orientação de exibição da tela.
Se \(\theta_{screen}\) representar os radianos de rotação no sentido horário da imagem da tela em relação à orientação natural da tela, \(\theta_{phycam}\) representar os radianos de rotação no sentido horário necessários para que a imagem da câmera física seja exibida corretamente em uma tela na orientação natural, e \(\theta\) representar os radianos de rotação no sentido horário necessários para que a imagem da câmera física seja exibida na tela atual.
Para a câmera traseira:
Por exemplo, em um celular Android, quando o telefone é usado na orientação natural, \(\theta_{screen} = 0, \theta_{phycam} = \frac{\pi}{2}\), portanto \(\theta = \frac{\pi}{2}\).
Para a câmera frontal, se após a conclusão da rotação for feito um flip horizontal:
Nota
Quando a imagem da tela gira, \(\theta\) precisa ser recalculado imediatamente no primeiro frame após a rotação ocorrer; caso contrário, a direção da imagem na tela pode ficar temporariamente incorreta.
Rendering do fundo da câmera e dos objetos virtuais
Ao renderizar objetos virtuais em um celular, os objetos virtuais precisam estar alinhados com a imagem da câmera. Isso exige colocar tanto a render camera quanto os objetos em um espaço virtual que corresponda exatamente ao espaço real, e renderizar com o mesmo field of view e aspect ratio da câmera física. As perspective projection transforms aplicadas à imagem da câmera e aos objetos virtuais são quase idênticas. A única diferença é que a maior parte da perspective projection transform da imagem da câmera ocorre dentro da câmera física, enquanto a perspective projection transform dos objetos virtuais é inteiramente um processo computacional.
A seguir são usadas convenções OpenGL. Se outras convenções forem usadas, será necessário fazer o mapeamento correspondente dos eixos de coordenadas. Suponha que os eixos do sistema de coordenadas da câmera sejam definidos assim: o eixo x aponta para a direita, o eixo y aponta para cima e o eixo z aponta para fora da tela. Os eixos do clip coordinate system são definidos assim: o eixo x aponta para a direita, o eixo y aponta para cima, o eixo z aponta para fora da tela e o eixo w é um eixo virtual.
Neste momento, a matriz de perspective projection transform necessária para renderizar a imagem da câmera é a seguinte:
Aqui, flip indica se a imagem é invertida horizontalmente. O valor é 1 quando há flip e 0 quando não há. \(\theta\) é o ângulo de rotação da imagem no sentido horário, em radianos. \(s_x\) e \(s_y\) são fatores de escala usados para proportional scaling ou proportional filling, e variam com \(\theta\). Essa matriz de transform primeiro escala a imagem da câmera, depois a gira e, por fim, aplica o flip. Durante o rendering, deve-se usar um retângulo que preencha a tela. Por exemplo, em OpenGL, os vértices do retângulo podem ser colocados em \((-1, -1, 0)\), \((1, -1, 0)\), \((1, 1, 0)\) e \((-1, 1, 0)\), com coordenadas UV definidas nos quatro cantos correspondentes, e então renderizar usando essa matriz de perspective projection.
A matriz de perspective projection necessária para renderizar objetos virtuais é a seguinte:
Aqui, \(n\) e \(f\) são os parâmetros de near clipping e far clipping normalmente usados em matrizes de perspective projection de rendering 3D. \(w\) e \(h\) são a largura e a altura em pixels da imagem da câmera. \(f_x\), \(f_y\), \(c_x\) e \(c_y\) são parâmetros intrínsecos comuns no modelo de câmera, onde \(f_x\) e \(f_y\) são focal lengths em pixels, e \(c_x\) e \(c_y\) são as posições em pixels do principal point. Essa projection matrix realiza as seguintes transforms em ordem: a perspective projection transform dos intrinsics da câmera (como as direções dos eixos y e z no sistema de coordenadas de imagem do OpenCV são opostas ao sistema de coordenadas da câmera OpenGL, duas transformações de sistema de coordenadas são realizadas), a transformação do sistema de coordenadas de pixels da imagem para o sistema de coordenadas do retângulo da imagem, a transformação de near clipping e far clipping, e a perspective projection transform usada ao renderizar a imagem da câmera.
Após a simplificação, obtém-se:
Pelo processo acima, o rendering geralmente precisa ser feito em duas passagens: uma passagem renderiza a imagem da câmera e outra renderiza os objetos virtuais, com os objetos virtuais sobrepostos à imagem da câmera.
Alguns engines 3D representam a perspective projection matrix com parâmetros como horizontal field of view e aspect ratio. Se rotação e flip não forem considerados e o offset do principal point for ignorado, é possível calculá-los, onde o horizontal field of view é \(\alpha=2 arctan{\frac{w}{2 f_x}}\) e o aspect ratio é \(r=\frac{w}{h}\).
Observe que a camera distortion não é considerada nesse processo, porque atualmente a camera distortion da maioria dos celulares é muito pequena.