Lien de la note Hackmd
Cours du 30 / 03
Calculons l’image que genere une camera :
- positionnee en $(c_x, c_y, c_z)$
- regardant dans la direction $(v_x, v_y, v_z)$
- avec un angle de rotation $c_\theta$ (que l’on prend = 0 pour commencer)
- avec une focale $f$
On a pour tout point $X$ de l’espace sa position $x$ sur l’image donnée par
\[x = P X\]- $P$ : matrice qui représente l’action de la caméra.
Le but est de trouver $P$.
Dimensions
- $X$ : point en 3D
- on rajoute une dimension pour les translations (cf ma02) : $X = (X_x, X_y, X_z, 1)$
- $x$ : point en 2D
- pour les translation : $x = (x_x, x_y, 1)$
- $P$ matrice de dimensions $3*4$
Repères
3 reperes :
- celui du monde en en 3D
- celui de l’image en 2D
- celui de la camera en 3D
Focale
On représente la focale comme la distance entre l’origine est la position virtuelle de l’image 2D.
Dans le repere de la camera : $x = \frac{f}{X_z} X = f \frac{X}{X_z}$.
Si on bouge uniquement la focale, et que le repere de la camera est le meme que celui du monde alors : \(\textrm{si }\quad P = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \quad \textrm{ on a }\quad P X = \begin{bmatrix} f X_x \\ f X_y \\ X_z \\ \end{bmatrix}\)
C’est presque le resultat recherche, on a $x$ a un facteur $X_z$ pret.
1
2
3
f = 0.5 # focale
F = lambda f: np.array([[f, 0, 0, 0], [0, f, 0, 0], [0, 0, 1, 0]])
1
2
3
F = array([[0.5, 0. , 0. , 0. ],
[0. , 0.5, 0. , 0. ],
[0. , 0. , 1. , 0. ]])
1
2
3
4
def normalize(x):
x[0,:] /= x[2,:]
x[1,:] /= x[2,:]
return x[:2,:]
Changement de repère
L’axe principal de la camera est $z$, soit $x$ dans le repere du monde 3D. On choisit comme repère inital de la caméra : $(x,y,z){cam} = (y, z, x){3D}$.
La matrice de passage est: \(X_{cam} = \begin{bmatrix} 0 & 1 & 0 \\ 0 & 0 & 1 \\ 1 & 0 & 0 \\ \end{bmatrix} \, X_{3D}\)
Pour respecter la notation $(x, y, z, 1)$ : \(P = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \quad \begin{bmatrix} 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}\)
Translation de la caméra
Si la camera est en $(c_x, c_y, c_z)$ et non en $(0, 0, 0)$, c’est une translation :
\(T = \begin{bmatrix} 1 & 0 & 0 & -c_x \\ 0 & 1 & 0 & -c_y \\ 0 & 0 & 1 & -c_z \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}\)
Axe principal de la caméra
On change la direction de la camera et son axe principal n’est plus $x$ du monde 3D.
Pour pointer un vecteur 3D dans une direction, il faut 2 rotations autour de 2 axes orthogonaux a notre vecteur. En 2D il suffit d’une rotation autour de $z$.
Pour diriger la camera dans une direction $v$, les rotations se font autour des axes $z$ et $y$ du monde:
- la rotation horizontale $\psi$ tourne autour de $z$
- la rotation verticale $\phi$ tourne autour de $y$
\(D = \begin{bmatrix} cos(\phi) & 0 & sin(\phi) & 0 \\ 0 & 1 & 0 & 0 \\ -sin(\phi) & 0 & cos(\phi) & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} \; \begin{bmatrix} cos(\psi) & -sin(\psi) & 0 & 0 \\ sin(\psi) & cos(\psi) & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix}\)
1
2
3
4
5
6
7
def D(ah, av):
if type(ah) == int:
ah = ah * 2 * np.pi / 360
av = av * 2 * np.pi / 360
rh = np.array([[np.cos(ah), -np.sin(ah), 0, 0], [np.sin(ah), np.cos(ah), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])
rv = np.array([[np.cos(av), 0, np.sin(av), 0], [0, 1, 0, 0], [-np.sin(av), 0, np.cos(av), 0], [0, 0, 0, 1]])
return rv @ rh