Exercices Computer Vision Appliquer une transformation affine
🎉

Bravo!

Avancé 🧠 Fondamentaux 30 XP 0 personnes ont réussi

Appliquer une transformation affine

Les transformations affines sont au coeur de la réalité augmentée, de la stabilisation vidéo et du recalage d'images médicales. Quand une application AR superpose un meuble virtuel sur ta caméra, elle applique des transformations affines pour aligner l'objet 3D avec la perspective de la scène. Quand un scanner de documents redresse une photo prise de travers, c'est une transformation affine. Quand on aligne deux IRM prises à des moments différents pour comparer l'évolution d'une tumeur, c'est encore une transformation affine.

Imagine que tu poses une photo sur une table. Tu peux la déplacer (translation), l'agrandir ou la réduire (mise à l'échelle), la tourner (rotation), ou même la déformer en tirant un coin (cisaillement). Toutes ces opérations sont des transformations affines, et elles peuvent toutes être exprimées par une seule matrice 2x3.

En pratique, tu utiliserais cv2.warpAffine(image, M, (largeur, hauteur)) qui fait ça de manière optimisée. Pour les rotations, cv2.getRotationMatrix2D() te génère la matrice automatiquement. Ici on implémente le mécanisme à la main pour comprendre comment une matrice transforme les coordonnées des pixels.

La matrice de transformation est un array 2x3 :

M = [[a, b, tx],
[c, d, ty]]

Pour chaque pixel de l'image de destination, on calcule sa position dans l'image source :

x_source = a * x_dest + b * y_dest + tx
y_source = c * x_dest + d * y_dest + ty

Quelques exemples de matrices :

Translation de (dx, dy) : [[1, 0, dx],
[0, 1, dy]]

Mise à l'échelle sx, sy : [[sx, 0, 0],
[0, sy, 0]]

La matrice identité (pas de changement) est [[1, 0, 0], [0, 1, 0]].

Écris une fonction appliquer_transformation(image, matrice, hauteur_sortie, largeur_sortie) qui prend une image (2D ou 3D), une matrice de transformation (array 2x3), et les dimensions de sortie. Pour chaque pixel de sortie, elle calcule la position source et copie la valeur (interpolation plus proche voisin). Les pixels hors de l'image source sont laissés à 0.

Exemple :
M = np.array([[1, 0, 5], [0, 1, 10]], dtype=np.float64)
Cette matrice translate l'image de 5 pixels à droite et 10 pixels vers le bas.

Ce que tu devrais voir sur ta machine : une photo translatée, agrandie ou déformée selon la matrice choisie.

Tests (5/5)

Identite ne change rien
import numpy as np
img = np.array([[10, 20], [30, 40]], dtype=np.uint8)
M = np.array([[1, 0, 0], [0, 1, 0]], dtype=np.float64)
result = appliquer_transformation(img, M, 2, 2)
assert np.array_equal(result, img), 'La matrice identite ne doit rien changer'
Translation
import numpy as np
img = np.zeros((5, 5), dtype=np.uint8)
img[0, 0] = 255
M = np.array([[1, 0, -2], [0, 1, -2]], dtype=np.float64)
result = appliquer_transformation(img, M, 5, 5)
assert result[2, 2] == 255, 'Le pixel (0,0) doit etre translate en (2,2)'
Forme de sortie
import numpy as np
img = np.zeros((10, 10, 3), dtype=np.uint8)
M = np.array([[1, 0, 0], [0, 1, 0]], dtype=np.float64)
result = appliquer_transformation(img, M, 20, 30)
assert result.shape == (20, 30, 3), f'Forme attendue (20, 30, 3), obtenue {result.shape}'
Pixels hors limites a zero
import numpy as np
img = np.full((3, 3), 100, dtype=np.uint8)
M = np.array([[1, 0, 10], [0, 1, 10]], dtype=np.float64)
result = appliquer_transformation(img, M, 3, 3)
assert np.all(result == 0), 'Tous les pixels source sont hors limites, le résultat doit etre noir'
Echelle x2
import numpy as np
img = np.array([[100, 200], [150, 250]], dtype=np.uint8)
M = np.array([[0.5, 0, 0], [0, 0.5, 0]], dtype=np.float64)
result = appliquer_transformation(img, M, 4, 4)
assert result[0, 0] == 100, 'Le coin superieur gauche doit rester identique'

Indices (3 disponibles)

solution.py