Table of Contents

Utiliser EasyAR dans un moteur 3D

Pour utiliser EasyAR dans un moteur 3D, il faut rendre l'image de la caméra et les objets virtuels. Les objets virtuels rendus doivent être alignés avec l'image de la caméra. Lors du rendu de l'image de la caméra, certains paramètres au moment de la génération de l'image et de l'affichage peuvent ne pas correspondre. Par exemple, la position, l'orientation, la taille de frame, l'aspect ratio et d'autres paramètres de la caméra physique peuvent différer de l'image affichée, et il faut les prendre en compte pendant le rendu. Si vous devez intégrer EasyAR à un moteur 3D non pris en charge, faites particulièrement attention aux détails suivants.

Recadrer le padding des bordures de l'image de la caméra

Le recadrage, la transposition et l'encodage d'image nécessitent tous beaucoup de calcul. Pour réduire le calcul et la latency, des formats relativement raw sont généralement utilisés. Pour faciliter le video encoding, les images produites par les caméras physiques sont souvent alignées sur des grilles comme 8x8, 16x16, 32x32 ou 64x64. Par exemple, lorsque la résolution 1920x1080 est sélectionnée sur certains téléphones, l'image de sortie peut devenir 1920x1088, car 1080 n'est pas un multiple de 64.

image with padding

Il faut donc retirer ces parties de padding supplémentaires pendant le rendu. Plusieurs approches sont possibles. L'une consiste à spécifier la largeur lors de l'upload de l'image dans la mémoire vidéo, par exemple avec glPixelStorei(GL_PACK_ROW_LENGTH, ...) dans OpenGL. Une autre consiste à calculer manuellement les coordonnées UV dans le fragment shader et à tronquer la partie excédentaire lors du sampling de l'image.

Rendre en suivant la rotation de l'écran

Sur les téléphones mobiles, l'image enregistrée par la caméra physique est généralement fixe par rapport au corps de l'appareil et ne change pas avec l'orientation d'affichage de l'écran. Toutefois, les changements d'orientation du corps du téléphone influencent la manière dont nous définissons les directions haut, bas, gauche et droite de l'image. Pendant le rendu, l'orientation d'affichage actuelle de l'écran influence également la direction de l'image affichée.

En général, pendant le rendu, il faut déterminer l'angle de rotation de l'image de la caméra par rapport à l'orientation d'affichage de l'écran.

Si \(\theta_{screen}\) représente les radians de rotation horaire de l'image de l'écran par rapport à l'orientation naturelle de l'écran, \(\theta_{phycam}\) représente les radians de rotation horaire nécessaires pour que l'image de la caméra physique s'affiche correctement sur un écran en orientation naturelle, et \(\theta\) représente les radians de rotation horaire nécessaires pour que l'image de la caméra physique s'affiche sur l'écran actuel.

Pour la caméra arrière:

\[ \theta = \theta_{phycam} - \theta_{screen} \]

Par exemple, sur un téléphone Android utilisé dans son orientation naturelle, \(\theta_{screen} = 0, \theta_{phycam} = \frac{\pi}{2}\), donc \(\theta = \frac{\pi}{2}\).

Pour la caméra avant, si un retournement horizontal est effectué après la rotation:

\[ \theta = \theta_{phycam} + \theta_{screen} \]
Note

Lorsque l'image de l'écran tourne, \(\theta\) doit être recalculé immédiatement sur la première frame après la rotation; sinon, la direction de l'image à l'écran peut être brièvement incorrecte.

Rendu de l'arrière-plan caméra et des objets virtuels

Lors du rendu d'objets virtuels sur un téléphone mobile, les objets virtuels doivent être alignés avec l'image de la caméra. Cela nécessite de placer la render camera et les objets dans un espace virtuel correspondant exactement à l'espace réel, et de rendre avec le même field of view et aspect ratio que la caméra physique. Les perspective projection transforms appliquées à l'image de la caméra et aux objets virtuels sont presque identiques. La seule différence est que la majeure partie de la perspective projection transform de l'image de la caméra se produit dans la caméra physique, tandis que la perspective projection transform des objets virtuels est entièrement un processus de calcul.

Les conventions OpenGL sont utilisées ci-dessous. Si d'autres conventions sont utilisées, une correspondance appropriée des axes de coordonnées est nécessaire. Supposons que les axes du système de coordonnées de la caméra soient définis ainsi: l'axe x pointe vers la droite, l'axe y vers le haut et l'axe z vers l'extérieur de l'écran. Les axes du clip coordinate system sont définis ainsi: l'axe x pointe vers la droite, l'axe y vers le haut, l'axe z vers l'extérieur de l'écran, et l'axe w est un axe virtuel.

À ce stade, la matrice de perspective projection transform nécessaire pour rendre l'image de la caméra est la suivante:

\[ P_i=\left( \begin{array}{cccc} (-1)^{\text{flip}} & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & 1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} \cos (-\theta ) & -\sin (-\theta ) & \phantom{0} & \phantom{0} \\ \sin (-\theta ) & \cos (-\theta ) & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} s_x & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & s_y & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right) \]

Ici, flip indique si l'image est retournée horizontalement. Sa valeur est 1 en cas de retournement et 0 sinon. \(\theta\) est l'angle de rotation horaire de l'image, en radians. \(s_x\) et \(s_y\) sont des facteurs d'échelle utilisés pour proportional scaling ou proportional filling, et varient avec \(\theta\). Cette matrice de transform met d'abord l'image de la caméra à l'échelle, puis la fait tourner, et enfin la retourne. Pendant le rendu, il faut utiliser un rectangle remplissant l'écran. Par exemple, dans OpenGL, les sommets du rectangle peuvent être placés en \((-1, -1, 0)\), \((1, -1, 0)\), \((1, 1, 0)\) et \((-1, 1, 0)\), avec les coordonnées UV définies aux quatre coins correspondants, puis rendre avec cette matrice de perspective projection.

La matrice de perspective projection nécessaire pour rendre les objets virtuels est la suivante:

\[ P=P_i\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & 1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -\frac{f+n}{f-n} & -\frac{2 f n}{f-n} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \end{array} \right)\left( \begin{array}{cccc} \frac{2}{w} & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & \frac{2}{h} & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & -1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} f_x & \phantom{0} & c_x & \phantom{0} \\ \phantom{0} & f_y & c_y & \phantom{0} \\ \phantom{0} & \phantom{0} & 1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right)\left( \begin{array}{cccc} 1 & \phantom{0} & \phantom{0} & \phantom{0} \\ \phantom{0} & -1 & \phantom{0} & \phantom{0} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \phantom{0} & \phantom{0} & \phantom{0} & 1 \\ \end{array} \right) \]

Ici, \(n\) et \(f\) sont les paramètres de near clipping et far clipping habituellement utilisés dans les matrices de perspective projection du rendu 3D. \(w\) et \(h\) sont la largeur et la hauteur en pixels de l'image de la caméra. \(f_x\), \(f_y\), \(c_x\) et \(c_y\) sont des paramètres intrinsèques courants dans le modèle de caméra, où \(f_x\) et \(f_y\) sont les focal lengths en pixels, et \(c_x\) et \(c_y\) les positions en pixels du principal point. Cette projection matrix effectue successivement les transformations suivantes: la perspective projection transform des intrinsics de caméra (comme les directions des axes y et z du système de coordonnées image dans OpenCV sont opposées à celles du système de coordonnées caméra OpenGL, deux transformations de système de coordonnées sont effectuées), la transformation du système de coordonnées pixel de l'image vers le système de coordonnées rectangle de l'image, la transformation de near clipping et far clipping, et la perspective projection transform utilisée lors du rendu de l'image de la caméra.

Après simplification, on obtient:

\[ P=P_i\left( \begin{array}{cccc} \frac{2 f_x}{w} & \phantom{0} & 1-\frac{2 c_x}{w} & \phantom{0} \\ \phantom{0} & \frac{2 f_y}{h} & -1+\frac{2 c_y}{h} & \phantom{0} \\ \phantom{0} & \phantom{0} & -\frac{f+n}{f-n} & -\frac{2 f n}{f-n} \\ \phantom{0} & \phantom{0} & -1 & \phantom{0} \\ \end{array} \right) \]

Le processus ci-dessus montre que le rendu doit généralement être effectué en deux passes: une passe rend l'image de la caméra, et une autre rend les objets virtuels, les objets virtuels étant superposés à l'image de la caméra.

Certains moteurs 3D représentent la perspective projection matrix avec des paramètres tels que horizontal field of view et aspect ratio. Si l'on ne tient pas compte de la rotation et du retournement, et que l'on ignore le décalage du principal point, ces paramètres peuvent être calculés: le horizontal field of view est \(\alpha=2 arctan{\frac{w}{2 f_x}}\), et l'aspect ratio est \(r=\frac{w}{h}\).

Notez que la camera distortion n'est pas prise en compte dans ce processus, car elle est actuellement très faible sur la plupart des téléphones mobiles.