Bonjour
Je souhaiterais calculer une mesure de la similarité / distance entre deux tracés. Je vous décris la procédure pour que vous compreniez ce que j’entends par « tracé ».
- Je dispose d’un tracé de référence (choix de la représentation libre) : imaginez un tracé fait avec un crayon sans lever le crayon. Ça peut être un simple cercle, un triangle, ce genre de choses.
- Je capture le tracé d’un utilisateur (j’ai un bout de code qui fait ça en écoutant les événements
mousemove
sur le document, cf. l’annexe en fin de post). J’obtiens une liste de points : les points que les événementsmousemove
m’ont donné pendant que le bouton de la souris était enfoncé. - Je veux savoir à quel point la forme du tracé de l’utilisateur ressemble au tracé de référence, sans tenir compte de l’échelle (il peut être plus petit ou plus grand, ce qui compte c’est que la forme soit la même). Par exemple si le tracé de référence était un cercle et que l’utilisateur a dessiné à peu près un cercle (pas forcément de même diamètre), la mesure de distance devrait être proche de zéro. Mais si ce qu’il a tracé ne ressemble pas du tout à un cercle la distance devrait être grande.
Je ne sais pas bien dans quelle direction partir. J’ai fait quelques recherches Google mais je ne parviens ni à trouver quelque chose qui réponde à ce besoin précisément, ni une solution à un problème similaire que je parviendrais à adapter.
Au départ, j’ai imaginé l’algorithme suivant :
- On a besoin d’un tracé de référence (le tracé dont l’utilisateur cherche à imiter la forme).
- Normaliser les tracés (le but est de « coller » les tracés vers l’origine du repère) :
- Rechercher l’abscisse la plus petite dans la liste des points du tracé.
- Retirer la valeur trouvée aux abscisses de tous les points du tracé.
- Faire de même avec les ordonnées.
- On calcule la distance entre chaque point du tracé et le point le plus proche du tracé de référence.
- Le résultat est la somme des distances : plus cette somme est proche de zéro, plus les tracés sont similaires.
Les problèmes que j’ai identifié avec cette approche sont les suivants :
- Cela ne répond pas au besoin d’être insensible à l’échelle : un tracé reproduisant parfaitement la forme mais d’une taille différente à celle du tracé de référence ne permettra pas d’avoir une distance nulle.
- Si un tracé contient peu de points (si on bouge la souris très vite par exemple), le point le plus proche peut être loin d’un point du tracé tout en étant sur le tracé. Par exemple si on a un point de coordonnées (0,5) et que le tracé de référence est constitué des points (0,0) et (0,10), le point est à une distance de 5 de chaque point du tracé, alors qu’il est sur le tracé.
Je suppose que puisque je voudrais être insensible à l’échelle du dessin, j’aurais besoin de travailler avec des vecteurs mais je n’ai aucune idée de comment faire. Vos suggestions sont les bienvenues ! Soyez toutefois conscient⋅es que mon niveau en mathématique est très faible, attendez-vous donc à des questions !
Annexe – l’exemple de code avec lequel je compte capturer le tracé de l’utilisateur :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | let captureEnabled = false; let shapePoints; function startCapture() { console.log('START CAPTURE'); captureEnabled = true; shapePoints = []; } function capture(mouseEvent) { if (!captureEnabled) { return; } shapePoints.push(Point.fromMouseEvent(mouseEvent)); } function endCapture() { console.table(shapePoints); captureEnabled = false; } class Point { constructor(x, y) { this.x = x; this.y = y; } static fromMouseEvent(event) { return new Point(event.offsetX, event.offsetY); } } window.addEventListener('mousedown', startCapture, false); window.addEventListener('mousemove', capture, false); window.addEventListener('mouseup', endCapture, false); |