Interpréter une matrice de transformations géométriques

Réponses à toutes vos questions après le Bac (Fac, Prépa, etc.)
Snake9
Messages: 3
Enregistré le: 25 Oct 2019, 13:20

Interpréter une matrice de transformations géométriques

par Snake9 » 25 Oct 2019, 13:34

Bonjour,

Je travaille dans l'informatique, et pour mon travail, je suis confronté à un problème de mathématiques que je n'arrive pas à résoudre.

Pour bien comprendre le problème, voici le contexte : je développe un logiciel qui lit un fichier XML qui définit comment découper et placer des images dans un plan en 2D. Plus concrètement, je possède une image qui est composée de plusieurs éléments. Les nœuds du fichier XML définissent les "morceaux" d'images à découper (en disant par exemple : "je découpe dans mon image un rectangle de dimensions 30 sur 40 pixels à partir de la position (25,40) en pixels sur mon image"), puis d'autres valeurs vont dire quelles transformations géométriques appliquer pour bien placer, orienter et redimensionner mon image sur le plan 2D.

Voici un exemple de nœud :

Code: Tout sélectionner
<Image srcX="201" srcY="383" dstX="32.150795" dstY="57.19337" width="31" height="24" a="0.248288766" b="-2.31910777" c="1.91672742" d="-0.27060008" />


Les valeurs dstX, dstY, a,b,c et d sont utilisées pour former une matrice de transformation géométrique qui combine translation, rotation, changement d'échelle (scale) et skew (je n'ai pas le mot français mais c'est la transfo qui fait ça : )

Image
skew

srcX et srcY sont les positions x et y du pixel où on commence le découpage, mais on peut ignorer ces valeurs car elles sont indépendantes de mon problème.
width et height sont la largeur et la hauteur (ou plutôt longueur) du rectangle à découper dans l'image, c'est-à-dire les dimensions du morceau d'image que j'ai découpé.

Malheureusement, mes cours de mathématiques remontent à loin et je ne savais pas comment récupérer les valeurs à partir de la matrice de transformation pour appliquer translation, rotation, scale et skew.

J'ai réussi à trouver un algorithme qui fait ça, en cherchant sur internet, en voici la traduction en français (je mets uniquement la partie qui nous intéresse)

Code: Tout sélectionner
vecteur translation = [dstX, dstY * -1]  (je multiplie par -1 à cause d'un changement de repère, le haut et le bas sont inversés)

On part du principe que a est non nul ou b est non nul :

Soit r = RacineCarre(a² + b²)

---------- Si b > 0 : angleRotation = ACos(a / r)
---------- Sinon : angleRotation = -1 * ACos(a / r)

vecteur scale = [ r ; (a * d - b * c) / r ]

vecteur skew = [ ATan( (a * c + b * d) / r², 0 ]




Cet algorithme marche quand la valeur x de mon vecteur skew est nulle. C'est-à-dire que je récupère les bonnes informations de translation, rotation et scale, mon image est correctement positionnée et orientée sur le plan.

Par contre, dés que j'ai un skew non nul, j'ai un problème de translation. La rotation et le scale restent corrects.

Mon problème est donc le suivant : je n'arrive pas à savoir quelle translation appliquer quand la coordonnée x de mon vecteur skew est non nulle.

Reprenons le nœud d'exemple :

Code: Tout sélectionner
<Image srcX="201" srcY="383" dstX="32.150795" dstY="57.19337" width="31" height="24" a="0.248288766" b="-2.31910777" c="1.91672742" d="-0.27060008" />


Avec ces valeurs, je trouve :

skew =[ -0.2001287 , 0 ]
translation = [ 32.150795 , - 57.19337 ]
rotation = 83.89 degrés
scale = [ 2.332361 , 1.87703 ]

Tout est correct sauf la translation. En cherchant manuellement les bonnes valeurs (en déplaçant l'image jusqu'à ce qu'elle arrive là où elle doit être normalement), j'obtiens les valeurs suivantes environ :

translation correcte = [32.8 , -50,7]

(avec une marge d'erreur de plus ou moins 1 je dirais)

Je sais aussi que dans tous mes cas, skew.y est nul.

Puisque quand skew.x est nul, la position est bonne, cela m'incite à penser que la position est la suivante :

position finale = [dstX, -1 * dstY] + skew.x * [kx, ky]

où kx et ky sont des valeurs qui doivent dépendre du reste des informations et que je dois calculer.

Mon problème est donc le suivant : comment exprimer les valeurs kx et ky en fonction des informations dont je dispose (c'est à dire les éléments de la matrice de transformation a, b, c, d, dstX et dstY, voire peut-être width et height).

J'ai essayé les calculs suivants pour essayer de trouver un lien me permettant de définir kx et ky en fonction des autres valeurs mais je n'ai rien trouvé actuellement :

Code: Tout sélectionner
translation =  skew.x * Vector2(kx,ky) = goodPos - currentPos = (0.649204999999995 ; 6,49337)

kx ; ky = translation / skew.x  = -3,24393752620186 ; -32,4459710176501

1/kx ; 1/ky = -0,308267342364895 ; -0,03082046764623


cos(angle) = 0,106437614426884
sin(angle) = 0,994319382409452
tan(angle) = 9,34180447169347


goodPos/currentPos = 1,02019250223828 ; 0,886466385876545
currentPos/goodPos = 0,980207164634146 ; 1,12807435897436


kx / cos(angle) = -30,4773603172987  => proche de - width (-31) et presque proche de dstX (32.150795)
kx / sin(angle) = -3,26247037279018

ky / cos(angle) = -304,835571450527
ky / sin(angle) = -32,6313371655559 => proche de -dstX (32.150795)

cos(angle)/kx = -0,003492350168084
sin(angle)/kx = -0,306516193477265

cos(angle)/ky = -0,003280457051786
sin(angle)/ky = -0,03064538835557


kx/tan(angle) = -0,347249563618174
ky/tan(angle) = -3,4732016834611

tan(angle) / kx = -2,87977323738144
tan(angle)/ky = -0,287918782477234


Si vous avez une piste que je pourrais explorer, je vous en serais très reconnaissant car je sèche un peu. :)

En vous remerciant d'avance.



pascal16
Membre Légendaire
Messages: 6663
Enregistré le: 01 Mar 2017, 12:58
Localisation: Angoulème : Ville de la BD et du FFA. gare TGV

Re: Interpréter une matrice de transformations géométriques

par pascal16 » 25 Oct 2019, 16:49

"skew" désigne plein de transformations avec des définition un peu différentes.

il me semble que le xml part d'un point milieu fixe et non pas d'un coté, c'est à vérifier dans ton cas.

[PS], je viens de tester, c'est bien ça.
un skew de 10 ° sur "angleX", transforme le rectangle en ne modifiant pas la ligne centrale qui passe par le centre

Snake9
Messages: 3
Enregistré le: 25 Oct 2019, 13:20

Re: Interpréter une matrice de transformations géométriques

par Snake9 » 28 Oct 2019, 18:12

Bonjour,

Merci pour votre réponse, mais je ne suis pas sûr de bien comprendre. Dans mon cas, la transformation skew semble bel et bien faite de sorte à ce que le centre de l'image reste inchangé. Faudrait-il faire en sorte que la transformation soit faite de sorte à ce que ce soit un autre point (l'un des sommets du rectangle défini par l'image, par exemple l'origine aux pixels (0;0)) qui soit inchangé par cette transformation ? Si oui, quel est le calcul à appliquer aux coordonnées (x;y) de n'importe quel point de l'image pour obtenir ses nouvelles coordonnées après l'application du skew ?

La déformation effectuée par le skew dans mon cas (avec le même exemple) transforme le carré orange suivant :

Image

en ce parallélogramme :

Image


Voici des images afin de mieux illustrer mon problème.

A partir d'une image composée de "morceaux" d'un personnage telle que l'image ci-dessous :

Image

Je découpe les différents morceaux conformément à ce qui est indiqué dans le fichier XML et j'applique les transformations géométriques sur ces images rectangulaires de sorte à recréer le personnage.

Le résultat que je devrais obtenir est le suivant :

Image

Mais au lieu de cela, j'obtiens le résultat suivant :

Image

Seules deux images sont mal positionnées :

Image
Image

qui correspondent à ces deux nœuds dans le fichier XML :


<Image srcX="201" srcY="383" dstX="32.150795" dstY="57.19337" width="31" height="24" a="0.248288766" b="-2.31910777" c="1.91672742" d="-0.27060008" />


<Image srcX="58" srcY="265" dstX="132" dstY="-51" width="75" height="92" a="0.08845472" b="0.9960799" c="-0.9508948" d="0.299235582" />

Ce sont les deux seuls nœuds pour lesquels la valeur du skew sur l'axe x est non nulle, toutes les autres images sont bien positionnées et orientées.

En sachant que quand je n'applique pas le skew mais que je laisse les mêmes valeurs de position/rotation/changement d'échelle, j'obtiens ce résultat :

Image


Ici on voit bien que les 2 images ne sont pas orientées comme il faudrait, mais en partant du principe que la position est bonne (car elle l'est dans tous les autres cas), j'ai l'impression qu'on pourrait s'imaginer que le point en haut à gauche de chaque image (c'est-à-dire le pixel (0;0)) est correctement placé dans les 2 cas (image bonne et dernière image fausse), ce qui incite à penser que le skew doit bel et bien déformer l'image non pas à partir de son centre mais à partir de son origine (donc au lieu d'avoir le point correspondant au pixel (width/2 ; height/2 comme point inchangé par la transformation, il faudrait que ce soit le point (0;0), il ne reste plus qu'à trouver les bonnes formules de calcul pour calculer x' et y' pour un skew qui ne modifierait pas l'origine).

pascal16
Membre Légendaire
Messages: 6663
Enregistré le: 01 Mar 2017, 12:58
Localisation: Angoulème : Ville de la BD et du FFA. gare TGV

Re: Interpréter une matrice de transformations géométriques

par pascal16 » 28 Oct 2019, 19:43

tu peux calculer de combien le centre est déplacé dans ta transformation, et le retrancher à la translation pour compenser.

GaBuZoMeu
Habitué(e)
Messages: 6132
Enregistré le: 05 Mai 2019, 09:07

Re: Interpréter une matrice de transformations géométriques

par GaBuZoMeu » 29 Oct 2019, 10:38

Un truc que je ne comprends pas bien.

Apparemment tu utilises les transformations 2D de CSS3. Puisque tu as une matrice fournie, pourquoi n'utilises-tu pas directement le
transform : matrix(...)
???
Pourquoi tiens-tu absolument à décomposer en translate, rotate, scale, skew ???

Peux-tu aussi indiquer clairement le code que tu écris à partir d'une matrice (notamment l'ordre des transformations) ?

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

Re: Interpréter une matrice de transformations géométriques

par fatal_error » 29 Oct 2019, 10:51

slt,

suivant la nomenclature: je tenterais au bonheur la chance:
https://developer.mozilla.org/en-US/doc ... /transform

Edit: j'ai comme a l'accoutumée répondu à côté. S'il s'agit de décomposer, il faudrait que tu fournisses un couple avant, après transfo pour tester.
La decomp se trouve sans skew.via TRS (trans, rot, scale par ex https://github.com/Automattic/node-canvas/issues/1004 ) mais aussi avec skew: où l'ordre SEMBLE etre trans skew scale rot (https://gist.github.com/Breton/9d217e03 ... 0b758d4ae6)
la vie est une fête :)

Snake9
Messages: 3
Enregistré le: 25 Oct 2019, 13:20

Re: Interpréter une matrice de transformations géométriques

par Snake9 » 29 Oct 2019, 14:46

Bonjour,

Merci pour vos réponses !

J'ai enfin réussi à résoudre le problème en utilisant la solution de Pascal16 : après avoir appliqué le skew, j'effectue une translation pour que le skew soit fait de sorte à ce que le point d'origine de l'image ne change pas, ce qui me permet d'avoir le bon rendu à la fin et qui marche pour toutes les images.

Merci beaucoup pour m'avoir aiguillé !

(Je n'utilise pas CSS3, pour tout vous dire j'ai pour mission de récupérer des fichiers d'un projet et les utiliser avec une autre technologie, la technologie que j'utilise n'a pas les mêmes fonctions que celle du projet original donc je dois refaire la décomposition pour pouvoir tout bien recalculer dans la technologie que j'utilise).

GaBuZoMeu
Habitué(e)
Messages: 6132
Enregistré le: 05 Mai 2019, 09:07

Re: Interpréter une matrice de transformations géométriques

par GaBuZoMeu » 29 Oct 2019, 15:07

À propos de l'ordre des transformations : ça ne semble pas être ce qu'affirme fatal_error :
In :
Code: Tout sélectionner
a,b,c,d,e,f=var('a,b,c,d,e,f')
M=matrix([[a,c,e],[b,d,f],[0,0,1]])
print 'M=\n',M
r=sqrt(a^2+b^2)
Rot=matrix([[a/r,-b/r,0],[b/r,a/r,0],[0,0,1]])
Scale=matrix([[r,0,0],[0,(a*d-b*c)/r,0],[0,0,1]])
Skew= matrix([[1,(a*c+b*d)/r^2,0],[0,1,0],[0,0,1]])
Trans= matrix([[1,0,e],[0,1,f],[0,0,1]])
Comp=(Trans*Rot*Scale*Skew).factor()
print 'Trans*Rot*Scale*Skew =\n',Comp

Out :
Code: Tout sélectionner
M=
[a c e]
[b d f]
[0 0 1]
Trans*Rot*Scale*Skew =
[a c e]
[b d f]
[0 0 1]

L'ordre de multiplication des matrices est Trans*Rot*Scale*Skew, ce qui veut dire que sur les coordonnées on fait d'abord Skew, puis Scale, puis Rot puis Trans.

 

Retourner vers ✯✎ Supérieur

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 32 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite