5.22. Correction d’objectif et de perspective

Deux catégories de correction géométrique déforment l’image d’une manière qu’un simple mappage rectangle-vers-rectangle ne peut pas réaliser. La correction d’objectif annule la distorsion radiale qu’introduit un véritable objectif grand-angle – le bombement en « œil de poisson » qui courbe les lignes droites de la scène en arcs visibles près des coins de la trame. La correction de perspective annule l’effet de trapèze qui survient lorsque l’objectif n’est pas pointé perpendiculairement à la scène – la déformation trapézoïdale qui transforme un rectangle connu du monde réel en un blob non rectangulaire dans l’image. Les deux corrections annulent, une fois la capture effectuée, des effets d’origine optique.

5.22.1. Distorsion radiale d’objectif

Le document real lens effects décrit la distorsion en barillet qu’introduisent les objectifs grand-angle bon marché. Les pixels proches du centre de la trame se trouvent approximativement là où le modèle sténopé le prédit ; les pixels proches des bords sont incurvés vers l’extérieur d’une quantité qui croît avec le carré de la distance radiale par rapport à l’axe optique. Une ligne droite de la scène qui passe près du bord de la trame se courbe visiblement dans l’image capturée, et tout algorithme classique de vision industrielle qui suppose que les lignes droites le restent – détection des coins AprilTag, suivi de contours, navigation par suivi de ligne – donne une réponse erronée près des coins.

lens_corr() annule la distorsion. La méthode applique le mappage inverse : chaque pixel de sortie est échantillonné à la position de l’entrée d’où l’objectif l’aurait incurvé vers l’extérieur, et le résultat est une image géométriquement droite.

img.lens_corr(strength=1.8)

Le paramètre strength est au cœur de la correction. C’est un nombre unique qui décrit la force avec laquelle l’objectif courbe l’image ; une valeur proche de 1.0 correspond à une correction légère pour un objectif modérément grand-angle, et des valeurs allant jusqu’à environ 2.0 sont raisonnables pour un fort œil de poisson. La valeur par défaut de 1.8 constitue un bon point de départ pour les objectifs d’origine des OpenMV Cam ; la valeur appropriée pour un objectif donné s’obtient en essayant quelques valeurs tout en observant l’image.

Les deux paramètres secondaires conviennent généralement à leurs valeurs par défaut. zoom (par défaut 1.0) met l’image de sortie à l’échelle – une valeur supérieure à un recadre vers l’extérieur pour compenser la manière dont la correction d’objectif repousse les coins davantage vers l’extérieur ; des valeurs plus petites laissent visible une plus grande partie de la scène corrigée, au prix de l’inclusion de pixels vides sur les bords de l’image. x_corr et y_corr décalent le centre de la correction par rapport au centre géométrique de l’image, ce qui est utile lorsque l’objectif n’est pas optiquement centré au-dessus du capteur (un cas inhabituel mais bon à connaître).

Une chaîne de traitement typique : capturer, exécuter une fois lens_corr() pour redresser la géométrie, puis exécuter ce que l’application fait réellement avec le résultat.

5.22.2. Correction de rotation 3D

L’autre catégorie de distorsion géométrique est la déformation de perspective qui survient lorsque le plan du capteur n’est pas parallèle au plan de la scène. Le cas classique est celui d’un panneau ou d’une plaque d’immatriculation vu d’en bas : le haut du panneau est plus éloigné de l’objectif que le bas, il se projette donc plus petit, et l’image capturée montre le rectangle sous forme de trapèze dont le bord supérieur est plus court que le bord inférieur.

La solution consiste à appliquer une rotation 3D à la trame capturée qui réoriente virtuellement le plan du capteur pour le rendre parallèle au plan de la scène. Le calcul est le même mappage de perspective que celui qu’utilise la détection AprilTag pour récupérer la pose d’un tag à partir de ses quatre coins, exécuté en sens inverse : étant donné une rotation, l’opération remappe chaque pixel de sortie vers la position d’entrée d’où la rotation l’aurait fait provenir.

rotation_corr() applique cette correction :

img.rotation_corr(x_rotation=10.0, y_rotation=0.0, z_rotation=0.0)

Les trois paramètres de rotation sont exprimés en degrés et décrivent des rotations autour des axes x, y et z d’une caméra virtuelle centrée sur l’image. x_rotation incline la caméra vers le haut ou vers le bas (la correction naturelle pour une prise de vue d’un mur au niveau du sol) ; y_rotation fait pivoter la caméra vers la gauche ou la droite ; z_rotation fait tourner la caméra autour de son axe optique (la correction naturelle pour un montage qui n’est pas de niveau).

x_translation et y_translation déplacent latéralement la caméra virtuelle sans la faire pivoter. zoom (par défaut 1.0) met l’image de sortie à l’échelle. fov (par défaut 60.0) décrit le champ de vision vertical de la caméra, utilisé pour calculer la projection – la valeur doit correspondre à l’objectif réel afin de garder la géométrie cohérente.

Pour une combinaison arbitraire d’inclinaison et de panoramique, plusieurs rotations non nulles se composent en un seul appel. L’ordre des opérations est fixé à l’intérieur de l’implémentation ; l’application se contente de fournir les angles et le résultat en ressort.

5.22.3. Redresser un rectangle connu

La forme la plus couramment utile de rotation_corr() est le mot-clé corners=, qui prend une liste de quatre tuples (x, y) décrivant les coins d’un rectangle connu dans l’image d’entrée. La méthode calcule la rotation 3D qui aurait mappé un véritable rectangle sur ces quatre points précis, applique l”inverse de cette rotation à l’ensemble de l’image, et renvoie un résultat dans lequel le rectangle connu est de nouveau rectangulaire :

plate_corners = [(45, 80), (300, 60), (310, 180), (40, 200)]
img.rotation_corr(corners=plate_corners)

L’usage classique est exactement ce que le nom suggère : une plaque d’immatriculation (ou toute autre caractéristique rectangulaire) photographiée sous un angle oblique. Une étape amont détecte la plaque et signale les positions de ses quatre coins dans l’image capturée ; en transmettant ces coins à rotation_corr(), on produit une image dans laquelle la plaque apparaît comme un véritable rectangle, prête pour l’étape suivante de reconnaissance de caractères ou de mise en correspondance par modèle.

Lorsque la forme à quatre coins résout le problème qu’une application cherche à résoudre, elle est nettement plus utile que la forme à six paramètres. L’application n’a pas à estimer le moindre angle de rotation ; elle se contente de fournir quatre points à la méthode et laisse celle-ci déterminer le reste. La forme à six paramètres est utile lorsqu’aucun rectangle identifiable n’est visible dans la scène et que la rotation doit être ajustée manuellement à partir de connaissances externes (un angle de montage calibré, par exemple).