Restaurer un graphique à partir d’un scan, avec le logiciel Tracker

Où l’on voit comment refaire un graphique présentable et modifiable à partir d’une image scannée de mauvaise qualité.

Les PDF de sujets d’examens regorgent de graphiques intéressants mais malheureusement avec une qualité déplorable qui gâche le document dans lequel il est inséré.

Parfois, c’est la qualité de l’image qui pose problème. Parfois, il faut le dire, c’est le graphique d’origine qui est en cause : insuffisamment gradué, notations obsolètes, fautes de frappe…

Pour reprendre ce graphique dans un document d’exercice ou d’évaluation, on ne dispose pas toujours des données avec lesquelles ce graphe a été fait. Voyons comment on peut générer les données avec une précision suffisante pour “restaurer” le graphique, j’entends par là : le rendre “présentable”, et personnalisable (légendes des axes, échelle, grille…

Le logiciel Tracker est déjà connu des profs de physique-chimie pour le pointage vidéo, pour lequel il est très performant. Autre avantage : il est gratuit et multiplateforme. Je peux donc l’installer chez moi comme au lycée.

L’idée est d’ouvrir l’image scannée du graphique d’origine, avec Tracker, et de cliquer sur plusieurs points de la courbe pour générer des données. Nous verrons plus loin comment gérer l’échelle.

  • D’abord, lancer Tracker et ouvrir l’image. Tracker n’ouvre pas que des vidéos.
  • Ensuite, cliquer sur l’icône permettant d’insérer un système d’axes.
  • deux lignes roses apparaissent, qui vont définir un repère pour les positions des clics de la souris. En cliquant-glissant sur l’intersection, on déplace l’origine du repère, pour la faire coïncider avec celle du graphe sur l’image. Si l’image scannée est penchée, on peut ajuster l’inclinaison du repère avec le ‘+’ situé près de l’origine.
  • Pour les pointages vidéos, il faut généralement créer un segment pour fixer l’échelle de distance (sur Tracker, c’est un “bâton de calibration”. Ici, ce n’est pas vraiment utile, puisque les deux axes ont des échelles différentes ; on peut définir un segment de calibration pour l’un des axes, mais l’autre aura nécessairement la même échelle, donc fausse. Voir la suite.
  • Nous allons ensuite cliquer sur différents points de la courbe, pour que Tracker enregistre les positions x et y des pixels cliqués. Or, ce processus étant initialement prévu pour des vidéos, à chaque clic on passe automatiquement à l’image suivante. Par défaut, Tracker prévoit 10 images, ce qui ne laisserait placer que 10 points. C’est souvent insuffisant, on peut donc modifier ça en cliquant sur l’icône “inspecteur de vidéo”, et en augmentant la valeur du champ “image finale” (par exemple 100 pour cliquer sur 100 points). Si on ne sait pas d’avance combien il faut, ce champ pourra être modifié après avoir commencé à cliquer.
  • Ensuite, aller dans le menu “Trajectoire” pour créer une “masse ponctuelle”, c’est-à-dire une série de positions pour suivre le déplacement d’un objet dans une vidéo.
  • Cliquer sur plusieurs points de la trajectoire (il faut appuyer sur la touche Maj pour changer l’aspect du curseur. On voit apparaître des points numérotés.
  • Simultanément, deux graphes se tracent automatiquement dans le panneau de droite, avec les données issus des pixels cliqués. Par défaut, le temps est mis en abscisses, mais on peut changer les grandeurs portées en abscisses et en ordonnées pour mettre y en fonction de x, et voir se reproduire la courbe de l’image scannée.
  • Une fois arrivé au bout de la courbe, on a le résultat suivant :
  • Le plus fastidieux est fait. Il s’agit maintenant de récupérer les valeurs en x et y, visibles dans le tableur en bas à droite. Il faut noter que ces valeurs ne peuvent pas correspondre aux limites des axes du graphe d’origine. Cela sera ajusté plus tard.
  • Avant d’exporter les données du tableur, il peut être nécessaire d’ajuster le séparateur décimal des nombres. Personnellement, je n’utilise plus les virgules pour des raisons de compatibilité entre logiciels. Même sur un tableur j’utilise le point comme séparateur décimal. Pour vérifier si les valeurs ont le séparateur souhaité, faire un clic-droit sur une cellule du tableur de Tracker, puis “Numbers/Format” pour changer si besoin.
  • Ensuite, dans le menu Fichier, aller dans Exporter/Fichier de données”. On peut exporter en fichier .txt, ou bien copier-coller dans un logiciel de texte brut (Gedit sous Linux, Bloc-Notes sous Windows, etc). Pour la suite, il faudra un fichier csv, mais de toute façon un fichier txt peut être sauvegardé en csv.
  • À noter que dans la boîte de dialogue il faut choisir le délimiteur : c’est le caractère séparant les colonnes du fichier texte. Peu importe lequel, mais il faut retenir le choix qui a été fait. D’autre part, on peut désélectionner la colonne x ou y, mais pas t, alors qu’ici on veut absolument x et y , mais ce n’est pas grave.
  • Une fois les valeurs insérées dans un fichier csv, on obtient quelque chose comme ça (ici : le point comme séparateur décimal, le point-virgule comme séparateur de colonnes).

Nos valeurs sont très fausses ! x est censé varier de 400 à 900 (nm) et y de 0 à 1 (absorbance). Il faudrait faire correspondre chaque x à une valeur entre 400 et 900. Même travail pour y avec les bornes 0 et 1. Je crois qu’on peut appeler ça un mapping. Il nous faut juste trouver la fonction affine qui associe une série de valeurs en entrée à une autre en sortie, telle que les min et max coïncident avec ce qu’on veut.

J’ai rédigé pour ça un petit script Python qui fait le boulot :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jul 24 18:38:59 2023

@author: david

Ce script réalise un mapping de séries de données x et y
pour faire correspondre les valeurs extrêmes à des bornes fixées.
Utile pour des points de données graphiques récupérées
avec Tracker, pour les faire correspondre aux valeurs souhaitées.
"""

import pandas as pd
import matplotlib.pyplot as plt
# à personnaliser :--------------
# indice 0 : données brutes
# indice 1 : données d'arrivée

x1min = 400
x1max = 900
y1min = 0.
y1max = 1.
nomX = 'x'# nom de la colonne x
nomY = 'y'# nom de la colonne y
NomFichier = 'spectreComplexeCuivre.csv' # fichier de sortie
table = pd.read_csv("donnees_brutes.csv", # nom du fichier d'entrée
                    sep=';',# caractère délimiteur de colonnes
                    skiprows=1,# éventuellement sauter la 1e ligne
                    )
# ------------------------------

def mapping(serie, mini, maxi):
    min0= min(serie)
    max0= max(serie)
    pente = (maxi-mini) / (max0 - min0)
    ordo = mini - min0 * pente
    return serie * pente + ordo

def trace(serie0,serie1,axe):
    axe.scatter(serie0,serie1,s=10, clip_on=False)
    axe.set_xlim(min(serie0),max(serie0))
    axe.set_ylim(min(serie1),max(serie1))

x0 = table['x']
x1 = mapping(x0, x1min, x1max)
y0 = table['y']
y1 = mapping(y0, y1min, y1max)

fig, axs = plt.subplots(nrows=2,ncols=1)

trace(x0,x1,axs[0])
trace(y0,y1,axs[1])

df = pd.DataFrame({nomX:x1,nomY:y1})

print(df)
df.to_csv(NomFichier,index=False,sep=';')

J’utilise le module pandas pour importer/exporter des données dans des fichiers. Le graphe fait avec matplotlib ne sert qu’à contrôler rapidement le résultat. En début de script, on rentre les extrêmes souhaités pour x et y (ici 400 et 900 pour x, et 0 et 1 pour y, en cohérence avec le graphe d’origine).

Le script importe les valeurs depuis le fichier csv issu de Tracker, fait le travail de recherche de pente et d’ordonnée à l’origine pour les fonctions affines recherchées, et exporte les valeurs “mappées” dans un nouveau fichier csv. Les valeurs de sortie sont visibles dans la console et sur les graphiques tracés.

Le script Python :

Voilà. On a des valeurs fidèles au graphe d’origine, prêtes à être utilisées dans un outil graphique de son choix. Exemple avec LibreOffice (qui ouvre les fichiers csv, il faut le rappeler !) :

Exemple avec LaTeX (le module pgfplots permet lui aussi de lire des données depuis un fichier csv) :

Soyez le premier à commenter

Laisser un commentaire