Coordonnées d'un point à partir d'une photo — Les-mathematiques.net The most powerful custom community solution in the world

Coordonnées d'un point à partir d'une photo

Bonjour,

Je suis nouveau sur ce forum :)

Je vous pose un problème développé sur Twitter avec @StadeOLHD, qui développe une base de donnée complète sur le stade de l'Olympique Lyonnais (par exemple les affluences, ou autres stats diverses). Pour compléter la BDD, il serait intéressant de pouvoir rentrer les coordonnées de la frappe d'un joueur lorsqu'il y a but.

Ainsi, nous cherchons à obtenir les coordonnées exactes cartésiennes (x,y) du plan du terrain (sachant que les longueurs sont en mètres et que le terrain est un rectangle de 105x68) de l'emplacement du tir du buteur. La difficulté réside à obtenir des coordonnées cartésiennes à partir de photos issues des caméras des diffuseurs. Voici un exemple sur la photo jointe :


L'objectif est de déterminer les coordonnées de la croix sur la frappe du dominicain Mariano Diaz, sachant que comme les dimensions d'un terrain sont régies par des règles définies par la FIFA, nous connaissons exactement les distances et positions des lignes blanches sur le terrain.

La perspective de la photographie rend cette opération délicate. Mes recherches sur internet m'ont menées vers les systèmes de coordonnées homogènes mais j'ai difficile à appréhender cette notion, ayant juste un niveau prépa école ingénieur en maths.
Existe-t-il des formules de passage toutes faites si on connait les angles et coordonnées des points de fuite et comment les obtenir sur chaque image ?

Le but de ce post est vraiment d'aborder la partie purement mathématique du problème; l'implémentation on s'en occupera.

Merci d'avance pour vos lumières ;)66708

Réponses

  • Il y a eu des discussions à ce sujet sur le forum :
    Redresser une image
    Redressement d'images
    Il y avait même des implémentations informatiques (en Sage).
  • Une petite remarque : de mémoire, les dimensions du terrain (largeur et longueur) varient, selon le stade, de plusieurs mètres.
    Mais ce n'est pas grave, on doit certainement trouver les dimensions de chaque stade sur Internet.
  • Le terrain fait 105x68, c'est pareil pour tous en L1 (règles de la LFP)
  • J'ai récupéré le code Sage, faisons-le marcher ici. La première étape est de fabriquer une matrice d'homographie qui redresse le terrain, en utilisant le quadrilatère formé par la surface de but. J'ai pris les coordonnées
    E(0,916) F(550,916) G(550,-916) H(0,-916)
    (le point G ;-) est à 5,50m de la ligne de but, 9,16m à gauche de l'axe des buts).

    Le code suivant fabrique la matrice voulue, à partir des coordonnées de la photo :
    a=[440,601,227,39]; b=[179,200, 346,318]
    
    M=[matrix(3,1,[a[ i],b[ i],1]) for i in range(4)];
    l=[M[3].augment(M[1]).augment(M[2]).determinant(),\
    M[0].augment(M[3]).augment(M[2]).determinant(),\
    M[0].augment(M[1]).augment(M[3]).determinant()]
    A=(l[0]*M[0]).augment(l[1]*M[1]).augment(l[2]*M[2])
    
    C=matrix(3,3,[0,-550,550, 916,-916,-916,1,-1,1])
    R=C*(A.adjoint())
    n=R[2,2]
    R=(1/n)*R
    
    Commençons par vérifier que ça amène bien les points E,F,G,H où l'on veut :
    L=['E','F','G','H']
    for i in range(4) :
        Im=R*vector([a[ i],b[ i],1]) 
        print "Image de",L[ i]," : ",[ Im[0]/Im[2],Im[1]/Im[2]]
    
    Image de E  :  [0, 916]
    Image de F  :  [550, 916]
    Image de G  :  [550, -916]
    Image de H  :  [0, -916]
    
    Maintenant qu'on est rassuré, on rentre les coordonnées de I sur la photo :
    Im=R*vector([825,332,1]) 
    print "Image de I :",[(Im[0]/Im[2]).round(),(Im[1]/Im[2]).round()]
    
    Image de I : [1782, -103]
    
    et on trouve que I est à 17,82m de la ligne de but, 1,03 à gauche de l'axe des buts. Ça semble raisonnable.
  • @Minolt
    Au temps pour moi, je pensais qu'il existait encore des mesures distinctes, même en Pro.
  • Bonjour
    Peut-on aussi se baser sur la hauteur des poteaux pour pouvoir restituer la position exacte du ballon quand il est en l'air c'est à dire assez souvent
    Amicalement
    [small]p[/small]
  • justement c'est quand le ballon est au sol que l'on peut trouver ses coordonnées avec par exemple la hauteur d'un poteau et la distance entre deux poteaux
    il faut qu'il existe une droite passant par le ballon (edit: et la base) d'un poteau et perpendiculaire à la droite portant ce poteau
    sinon...
  • @pappus : tu poses cette question sérieusement ? Il est bien clair que les deux coordonnées de l'image du ballon sur la photo ne peuvent pas suffire à trouver les trois coordonnées du ballon dans l'espace.
  • Après, on peut se poser la question si on a aussi sur la photo l'ombre du ballon sous la lumière d'un projecteur dont on connaît la position et la hauteur.
  • Bonsoir GaBuZoMeu
    Je ne sais trop pourquoi mais je te donne toujours l'occasion de me tirer les oreilles!
    Plus sérieusement je pensais à plusieurs caméras. N'est-ce pas le principe du cinéma en relief?
    Amicalement
    [small]p[/small]appus
  • Le problème de reconstitution d'une scène 3-d à partir de plusieurs vues 2-d est effectivement classique. Mais un ballon en l'air a une petite tendance à ne pas rester en place, et il faudrait donc plusieurs images exactement simultanées !
  • Bonsoir,
    Quand on regarde un match de foot avec un écran classique, il est souvent difficile si on n'est pas très attentif de savoir si un coup de pied de recentrage s'éloigne ou se rapproche de soi !
    Amicalement.
    [small]p[/small]appus
  • Bonjour et merci à tous pour vos messages. J'ai essayé de faire un redressement d'image avec GIMP (en utilisant leur outil de redressement de perspective), et ensuite en relevant les coordonnées (x,y) en pixels des 4 points de la surface j'ai pu appliquer deux règles de 3 pour obtenir les coordonnées du point de tir.

    Voici les photos obtenues :

    Pour le but face au virage nord (celui de Mariano) j'obtient comme déviation :
    17.57 m de la ligne de but
    0.90 m à gauche de l'axe central

    A comparer avec les résultats du logiciel SAGE :
    17.82 m de la ligne de but (soit 1.4% d'écart)
    1.03 m à gauche de l'axe central (soit 0.4% d'écart si on considère toute la largeur du terrain)

    C'est pas mal !!
    Je suis curieux d'avoir vos résultats pour la deuxième situation : le but de darder contre le PSG en 2016. A noter que ce but est intéressant et permet de rebondir sur un autre débat : la position en altitude du ballon (la référence prise ici est l'ombre manifeste du ballon sur le terrain); sachant que Darder a marqué le but en reprise de volée : le ballon était donc en l'air au moment de sa frappe.

    J'ai trouvé :
    6.43 m de la ligne de but
    1.66 m à gauche de l'axe central

    Cependant, dans l'optique d'implémenter ça dans une base de données, la méthode SAGE me parait bien élégante. Serait-il possible de comprendre comment ça marche et comment reproduire les résultats ?

    Merci beaucoup !!66776
    66778
    66780
  • As-tu lu les discussions que j'ai mises en lien ? Il y a là-dedans pas mal d'explications sur la méthode (et aussi pas mal de scories dues à dlzlogic).
    Si tu utilise GIMP et l'outil transformation - perspective, tu dois voir une fenêtre avec une matrice 3x3. C'est cette matrice que je calcule. La voici pour la photo que tu avais fournie :
    [      3.1400       9.0587      -3003.1]
    [      1.7969      -12.961       2671.1]
    [-0.000093451    0.0016061       1.0000]
    

    Pour l'autre photo, avec le même code je trouve comme matrice
    [   -2.3105     1.7129     914.63]
    [   0.10244     8.1443    -2398.6]
    [-3.5175e-6  0.0010014     1.0000]
    
    ce qui me donne comme position [646, -99] : 6,46m de la ligne de but, 99cm à gauche de l'axe.

    PS. J'ai réutilisé le code pour calculer les coordonnées du point de penalty sur la première photo. J'ai repris moi-même les cotes des sommets du rectangle de la surface de but, que je trouve légèrement différents de ceux indiqués. La position calculée du point de penalty est à 11,25m de la ligne de but, 19cm à droite de l'axe. Pas trop mal.
  • Bonjour,

    Je tenais à vous remercier très sincèrement car le programme fonctionne quasi parfaitement en suivant le code SAGE fourni par GaBuZoMeu. Au passage, j'ai découvert ce logiciel et ne savais pas l'installer: j'ai profité du service cloud COCALC gratuit pour peu que l'on ne fasse pas trop attention aux performances.

    Pourquoi "quasi" ? J'ai l'impression que les caméras de télévision déforment très légèrement les portions de l'image situées sur les côtés ce qui fait que la position calculée de la ligne de la surface de réparation varie de 50cm environ.

    J'ai corrigé quelques fautes de frappe dans le code liées au fait que le forum prend [ i ] pour une mise en italique...
    a=[440,601,227,39]; b=[179,200, 346,318]
    
    M=[matrix(3,1, [ a[ i ], b[ i ], 1] ) for i in range(4)];
    l=[M[3].augment(M[1]).augment(M[2]).determinant(),\
    M[0].augment(M[3]).augment(M[2]).determinant(),\
    M[0].augment(M[1]).augment(M[3]).determinant()]
    A=(l[0]*M[0]).augment(l[1]*M[1]).augment(l[2]*M[2])
    
    
    C=matrix(3,3,[0,-550,550, 916,-916,-916,1,-1,1])
    R=C*(A.adjoint())
    n=R[2,2]
    R=(1/n)*R
    
    Im=R*vector([825,332,1]) 
    print "Image de I :",[(Im[0]/Im[2]).round(),(Im[1]/Im[2]).round()]
    

    Je vais remettre en forme le code Javascript et le partager sur mon site pour que cela aide d'autres internautes.
    1000 mercis.
  • Le traitement mathématique suppose que la caméra se comporte exactement comme une chambre noire. Ce n'est sans doute pas le cas.
  • Voici pour info le résultat ci-dessous une fois faite la mise en page dans mon outil.
    Remarque préalable: pour moi le (0,0) est le poteau de corner en bas à gauche comme indiqué sur le dessin.

    J'ai donc défini au pixel près les contours des 6 mètres et ai appliqué la matrice magique. J'ai cliqué sur trois points de contrôle (le point de pénalty qui devrait avoir comme coordonnées (34m,16m) et deux points arbitrairement choisis sur la ligne des 16m50.

    Ce dont je m’aperçois:
    * le point de penalty est à peu près bon à 20cm près (on peut l'accepter compte tenu de la qualité de la photo)
    * en revanche la ligne des 16m50 a une déviation de 0,50m entre la croix verte du bas et la croix verte du haut. On peut même avoir près d'1 mètre entre deux essais de positionnement à la souris d'E,F,G,H.
    * la moindre modification d'un pixel de l'un des point E,F,G,H fait énormément varier les coordonnées "réelles calculées" des croix vertes et de la fameuse croix bleue du tireur.67052
  • J'obtiens des résultats assez sensiblement différents. Je pense que ce n'est pas une bonne idée de surligner les traits de la surface de but de lignes jaunes et rouges assez épaisses : cela nuit à la précision des relevés des cotes des sommets de la surface de but
  • bonsoir

    bravo et merci à Gabu pour la richesse mathématique et la précision de ses réponses

    les supporters de l'Olympique lyonnais seront flattés et impressionnés
    par autant de détails sur le tir de leur avant-centre Mariano Diaz

    surtout sur un tir qui a fait mouche !

    cordialement
  • GaBuZoMeu écrivait : http://www.les-mathematiques.net/phorum/read.php?8,1517560,1523974#msg-1523974
    [Inutile de recopier l'avant dernier message. Un lien suffit. AD]

    Bonjour, les résultats sont différents de quel point de vue ? Les relevés des 4 points initiaux ? Est-ce que vos résultats donnent une ligne à effectivement 16m50 ?
  • Bon, avec des traits plus fins et un "calibrage" à l'aide des points J, K, L, j'arrive à quelque chose de bien !67062
  • A tout hasard, est-il possible - une fois la matrice R calculée - de faire le calcul inverse: trouver un point sur l'image à partir du point réel ?
    J'imagine que c'est bijectif.
  • Oui, a priori, il suffit de multiplier le vecteur $(x,y,1)$ par l'inverse de la matrice (ce qui est pénible à calculer mais est programmé en Sage, Matlab, Scilab, R, etc.).
  • Bien sûr. Même procédé, dans le sens contraire.
  • Merci beaucoup, je vais tester de ce pas.
    PS: j'avais promis de partager publiquement le programme résultant de cet échange. Je le ferrai d'ici quelques jours sur mon site.
  • Bonjour,

    Cela ne semble pas fonctionner.

    Si je repars de la conclusion de GaBuZoMeu:
    GaBuZoMeu a écrit:
    Maintenant qu'on est rassuré, on rentre les coordonnées de I sur la photo :
    Im=R*vector([825,332,1]) 
    print "Image de I :",[(Im[0]/Im[2]).round(),(Im[1]/Im[2]).round()]
    
    Image de I : [1782, -103]
    

    et on trouve que I est à 17,82m de la ligne de but, 1,03 à gauche de l'axe des buts. Ça semble raisonnable.

    Je tente le chemin inverse dans SAGE:
    v=vector([1782, -103, 1])
    Rinverse = R.inverse()
    

    Si je multiplie v par l'inverse de la Matrice R:
    sage: v*Rinverse
    (392722479704497/999947872000, 2346138276818249/7285983812800, 317508878583593/994266350)
    

    Soit (392, 322, 319340).

    Je ne retombe donc pas sur mes pattes. J'ai dû oublier qq chose...
  • Ne pas confondre v*Rinverse (que Sage interprète comme $v^{\mathsf T} R^{-1}$) et Rinverse*v qui est $R^{-1}v$.67520
  • Le problème qui se pose est celui de la précision des calculs. Une homographie donne une approximation, qui correspond à un système sans lentilles où la caméra n'est qu'un sténographe sans compter les approximations faites sur la réflexion.

    Si on se place dans cette approximation linéaire, celle-ci n'a presque aucune chance de préserver le réseau des entiers donc l'image par l'homographie n'est pas définie stricto-sensu mais seulement modulo des approximations. Mes élèves de 1S/TS qui travaillent sur le sujet utilisent des moyennes sur les homographies, mais c'est très délicat et ça demande de mettre les mains dans le cambouis. Je crois qu'ils utilisent aussi des librairies préprogrammées sur python qui permettent
    de gérer directement des centaines d'homographies.

    Bref, il faut regarder la marge d'erreur et faire attention à ce que l'on voit, car il y a des interpolations dans tous les sens pour "faire joli" donc prudence c'est un terrain miné! Bonne chance.

    M.
  • @GaBuZoMeu, c'est parfait, merci. Cela fonctionne.

    @Mauricio, effectivement, je m'en rends compte. Mon logiciel permet d'abord de construire la matrice à partir des points EFGH des 6 mètres. Pour affiner cette matrice, je mets en surimpression, en noir, la surface de réparation ABCD calculée grâce à ce que GaBuZoMeu a partagé ce soir, jusqu'à ce que le résultat soit "satisfaisant visuellement".

    Je dois avoir une marge d'erreur de 50cm environ sur le tir du buteur en fonction des réglages. 1/2m pour le football, c'est très satisfaisant :-)67552
  • C'est très précis en effet, mais je suis quand même étonné (je dois peut-être aller acheter un nouvel appareil photo pour nos expériences!) . Enfin, il faut faire attention car un appareil photo comporte toutes sortes d'algorithmes d'interpolation et python (sage est pareil j'imagine) à tendance à tricher.

    Si je peux donner un conseil c'est d'utiliser les fichiers raw (si tu n'y a pas accès tu peux le fabriquer) et de supprimer les interpolations faite par python (ou sage). Normalement tu devrais voir apparaître des zones noires sur l'image par homographie (les endroits ou l'homographie est très "dillatante"). Ce n'est pas le cas sur tes images, ce qui me fait penser qu'il y a un loup quelque part. Trop beau pour être vrai à mon avis, mais il est possible que Sage fasse le travail à ta place et qu'il le fasse bien.

    Pour calculer la marge d'erreur, tu peux aussi prendre les quatre points du but pour avoir une vue de face, le carré rouge, ou des points sur l'arc de cercle et comparer une des coordonnées ainsi obtenues, c'est plus prudent. Ce que je fais faire à mes élèves c'est prendre un bout de matrice et analyser pour être sûr. Tu cherches deux zones précises, le joueur et le rectangle.

    Si le terrain de foot marche aussi bien avec ses dessins géométriques, je vais l'adopter pour expliquer la géométrie projective à mes élèves surtout que nous avons un terrain de foot juste à côté du lycée.

    Mauricio
  • Je ne comprends absolument pas ce que tu racontes, Mauricio. Qu'est-ce que tu veux dire par "python a tendance à tricher" ? Tricher sur quoi ? Il n'y a aucune interpolation de faite en Sage. Juste des calculs sur les coordonnées de points relevées sur la photo, calculs qui consistent à calculer une matrice d'homographie qui envoie quatre points du plan sur quatre autres points du plan.

    Pourrais-tu être plus clair ? Là, j'ai l'impression que tu imagines je ne sais quelle magie dans le traitement fait en Sage.
  • Salut GBZM! Si on parle bien de la même chose une image c'est discret: des points à coordonnées entières correspondant à des pixels (je passe sur comment ces pixels sont définis qui est aussi important). Prends par exemple
    (x,y) -> (2x,y/2)
    Tu vas être un peu embêté pour avoir l'image du pixel (1,1). Donc je pense que Sage fait des calculs. J'avais déjà poser la question sur le forum par exemple sur python pour enlever l'interpolation dont je m'étais aperçu à mes dépends. Normalement tu devrais presque voir la dérivée de ton homographie sur l'image et constater des trous. C'est très instructifs pour des élèves qui apprennent le calcul d'ailleurs.

    Prends par exemple
    (x,y)->(10x,y/10)
    Tu as plein de pixels dans l'image sans antécédents donc des trous noirs. Donc quand tu prends une image par homographie tu vois des zones qui marche bien (dérivée proche de l'identité) et d'autres non (dérivée loin de l'identité).

    Donc dans le passage du modèle continu sur R, il y a une approximation qu'il faut gérer. Toute la difficulté dans l'application des mathématiques vient souvent de ces petits détails, qui font toute la saveur du sujet...

    Oui je pense que Sage fait des calculs, je suis sûr que ton appareil photo fait des calculs (il est en fait déjà sur la pixelisation). Donc je ne dis pas que l'image est forcément truquée, je dis juste méfiance, vérifions, calculons, approchons. Si ça marche bien alors j'achète pour mes élèves et je vous remercie au passage de ce bel exemple.;-)

    Mauricio
  • J'ai du mal à comprendre pourquoi il y aurait une approximation faite par tel ou tel logiciel sur des calculs de matrices. Je peux dire par là que ce n'est pas le logiciel qui cause l'approximation mais d'autres facteurs externes: la déformation liée à l'objectif, la qualité de la photo etc. Au passage, je n'ai pas d'autre qualité que l'image extraite d'une vidéo HD de la Ligue 1 ou de l'UEFA.

    En tout état de cause, je n'utilise pas SAGE pour faire mon applicatif mais du javascript dans une page HTML5. J'aurai bientôt le plaisir de rendre accès au code source et à une page de démo pour que vous puissiez vous faire votre propre idée.
  • @Mauiricio : je ne crois pas qu'on parle de la même chose. As-tu lu le fil ? Il n'y a aucune manipulation de faite sur l'image. Juste un relevé de coordonnées de points sur l'image, avec forcément une approximation. Ensuite, comme je l'ai déjà écrit, je suppose que l'appareil de prise de vue se comporte à peu près comme une chambre noire. Mais sage ne fait absolument aucun calcul caché, il fait juste le calcul de matrice d'homographie que je lui demande à partir de quatre points dont les coordonnées sont relevées sur le fichier image et dont on connaît la position sur le terrain. Point, c'est tout.
  • Bonjour à tous, j'ai le plaisir de partager mon code HTML/javascript ici:

    http://www.stadeolhd.com/assistant.php

    UN ENORME MERCI
  • Une nouvelle fois, je tenais à vous remercier tant l'outil est formidable et m'aide chaque jour.
    Vive les maths !

    Démonstration sur Twitter
  • Merci des nouvelles. ;-)
    Les matchs de foot se font rares ces temps-ci.
Connectez-vous ou Inscrivez-vous pour répondre.
Success message!