# CAMA : ma03 Matrice Camera
# Cours du 30 / 03
:::info
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$
:::
:::danger
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
:::danger
On représente la focale comme la distance entre l'origine est la position virtuelle de l'image 2D.
:::
![](https://i.imgur.com/FW5BVZV.png)
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}
$$
:::warning
C'est presque le resultat recherche, on a $x$ a un facteur $X_z$ pret.
:::
:::success
Pour garantir $x_z = 1$ on ajoute une normalisation :
:::
```python=
f = 0.5 # focale
F = lambda f: np.array([[f, 0, 0, 0], [0, f, 0, 0], [0, 0, 1, 0]])
```
```
F = array([[0.5, 0. , 0. , 0. ],
[0. , 0.5, 0. , 0. ],
[0. , 0. , 1. , 0. ]])
```
```python=
def normalize(x):
x[0,:] /= x[2,:]
x[1,:] /= x[2,:]
return x[:2,:]
```
## Changement de repère
:::danger
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}$.
:::
:::info
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
:::info
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.
:::danger
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$
:::info
$$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}
$$
:::
```python=
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
```