Ressource technique · RUMBA.RD
Dyslexia-Focused Reading Experiment
Analyse du dépôt GitHub Dyslexia-Focused-Study-Toolkit-Reading-Experiment, un pipeline expérimental pour étudier la lecture dyslexique avec OpenFace, calibration, QCM, télémétrie et métriques de regard.
Contexte scientifique
La dyslexie développementale est un trouble neurodéveloppemental qui entraîne des difficultés persistantes dans la reconnaissance des mots et le décodage, malgré une intelligence normale et une scolarisation adéquate. Les personnes dyslexiques présentent souvent une instabilité des mouvements oculaires : fixations courtes ou prolongées selon les tâches, régressions fréquentes et vitesse de lecture réduite.
Les mesures oculométriques constituent un indice sensible et non intrusif de la charge cognitive. Elles permettent d'observer le temps de lecture, la durée des fixations, les régressions et la longueur des saccades. Dans le cas de RUMBA.RD, ces indices servent à comparer des textes standards et des textes adaptés.
Origine et objectifs du dépôt
Le dépôt GitHub TimTrinche/Dyslexia-Focused-Study-Toolkit-Reading-Experiment s'inscrit dans un projet plus large consacré au développement d'outils gratuits pour étudier et améliorer la lecture chez les personnes dyslexiques.
RUMBA.RD vise à élaborer un dispositif expérimental permettant de comparer différents aménagements typographiques : espacement des lettres, mise en forme syllabique, repères de lecture ou algorithmes de formatage. L'objectif est de mesurer leurs effets sur la fluidité oculométrique et la compréhension.
L'outil combine une application Python en plein écran, la présentation de textes, des questions de compréhension, l'enregistrement des mouvements oculaires avec OpenFace 2.0 et des scripts d'analyse. Le choix d'OpenFace rend l'expérimentation possible avec une simple webcam, donc sans oculomètre spécialisé.
- Dérouler plusieurs essais dans une session unique d'OpenFace.
- Présenter des tâches de lecture en plein écran.
- Évaluer la compréhension avec QCM et réponses ouvertes.
- Enregistrer la télémétrie et les marqueurs d'événements.
- Exporter
markers.csv,gaze.tsv,telemetry.tsvetmetrics.csv.
Organisation du dépôt et description du code
Le cœur du dépôt se trouve dans le script experiment_runner.py. Il orchestre la session expérimentale, vérifie la présence d'OpenFace, charge le plan expérimental, affiche les textes et écrit les sorties d'analyse.
# Détection de l'exécutable OpenFace dans le système
DEFAULT_OPENFACE_DIR = "./OpenFace/build/bin"
OPENFACE_ENV_VAR = "OPENFACE_DIR"
OPENFACE_ROOT_ENV_VAR = "OPENFACE_ROOT"
# Si l'utilisateur définit OPENFACE_DIR, on l'utilise.
# Sinon, on cherche l'exécutable connu.
openface_root = os.environ.get(OPENFACE_ROOT_ENV_VAR) or find_openface_root(DEFAULT_OPENFACE_DIR)
os.environ[OPENFACE_ENV_VAR] = openface_root
Le fichier plan.csv définit les essais, les conditions et les réponses attendues. Il permet par exemple un ordre contrebalancé AB/BA pour comparer un texte standard et un texte formaté.
id,title,style,color,q1,q2
A,TextA,plain,#6495ED,2,3
B,TextB,formatted,#FFA07A,1,4
Un journal d'événements enregistre les clics, les débuts de fixation, les changements de phrase et les réponses. Cette granularité permet de reconstruire la chronologie complète de l'expérience.
class MarkerLogger:
def log(self, code: str, meta: dict | None = None) -> None:
now = time.monotonic_ns()
self.marks.append((now, code, meta or {}))
Contrôle d'OpenFace et télémétrie
La classe OpenFaceController encapsule le lancement d'OpenFace. Elle démarre le processus de suivi du visage et du regard, puis stocke les données dans un répertoire de sortie. Pendant la lecture, un échantillonneur collecte des informations sur la luminance, la pose de tête et les conditions de mesure.
openface_proc = subprocess.Popen([
os.path.join(openface_root, "FaceLandmarkVidMulti"),
"-out_dir", tmpdir,
"-2Dfp", "-3Dfp", "-pdmparams", "-pose", "-gaze",
video_file,
])
def sample(self):
pixel = self.screen.get_pixel_colour(x, y)
self.samples.append({
"time_ns": time.monotonic_ns(),
"screen_lum": luminance(pixel),
"head_pose": self.current_pose,
"ambient_lum": self.ambient_sensor.get_value(),
})
Ces mesures permettent d'identifier les variations d'éclairage ou de posture susceptibles d'affecter la détection du regard. Elles renforcent la qualité des comparaisons entre conditions.
Calibrage et mappage du regard
Avant chaque phase de lecture, l'application effectue une calibration en cinq points. L'objectif est de transformer les coordonnées oculaires produites par OpenFace en coordonnées écran exploitables pour l'analyse.
def lstsq_2d(inpts: np.ndarray, outpts: np.ndarray) -> np.ndarray:
# Ajoute une colonne de 1 pour modéliser la translation.
A = np.hstack([inpts, np.ones((inpts.shape[0], 1))])
# Résout la régression linéaire A * M = outpts.
M, _, _, _ = np.linalg.lstsq(A, outpts, rcond=None)
return M # matrice 3x2 transformant l'oeil vers l'écran
La qualité du mapping est ensuite estimée par une erreur moyenne de localisation. Si l'erreur est trop élevée, l'expérimentateur peut refaire la calibration. Après la lecture, les marqueurs et les données de regard sont combinés pour produire gaze.tsv.
Déroulement d'un essai
La classe ExperimentApp combine l'interface, les marqueurs, la calibration, la présentation du texte et les questions de compréhension. Une session typique suit une progression très simple.
- Saisie d'un identifiant pseudonyme.
- Calibration en cinq points.
- Présentation d'un texte standard ou formaté.
- Questions de compréhension sous forme de QCM.
- Question ouverte pour recueillir une trace qualitative.
- Pause, recalibration éventuelle, puis essai suivant.
def ask_qcm(self, question: str, answers: list[str], correct_id: int) -> None:
self.marker.log("QCM_START", {"question": question})
selected = self.ui.display_qcm(question, answers)
self.marker.log("QCM_END", {
"response": selected,
"correct": selected == correct_id,
})
À la fin de la session, les fichiers markers.csv, telemetry.tsv, gaze.tsv et metrics.csv sont enregistrés pour l'analyse.
Analyse automatique
Le module d'analyse lit les fichiers de télémétrie et de regard, puis applique un lissage exponentiel pour réduire le bruit. Les fixations sont détectées en repérant des périodes où la dérivée du regard reste sous un seuil pendant une durée minimale.
def smooth_eye(signal: np.ndarray, alpha: float = 0.2) -> np.ndarray:
smoothed = np.zeros_like(signal)
smoothed[0] = signal[0]
for i in range(1, len(signal)):
smoothed[i] = alpha * signal[i] + (1 - alpha) * smoothed[i - 1]
return smoothed
Pour chaque phrase, le pipeline calcule des métriques comme le temps de lecture, la durée moyenne des fixations, le nombre de régressions et la longueur moyenne des saccades. Ces mesures permettent de tester si une condition typographique réduit la charge cognitive ou améliore la compréhension.
Utilisation pour tester les hypothèses RUMBA.RD
Le protocole permet de comparer des textes plain et formatted au sein d'un même participant. La mise en forme peut inclure un repérage syllabique, une modification de l'espacement ou une couleur de suivi.
Hypothèse 1 : span perceptif
En élargissant l'espacement entre les mots et en utilisant une mise en forme syllabique, on peut s'attendre à des saccades plus longues et à un déplacement du regard plus stable, grâce à une réduction de la foule visuelle.
Hypothèse 2 : charge cognitive
Si la mise en forme réduit l'effort de décodage, on devrait observer des fixations plus courtes, un temps de lecture total réduit et un nombre de régressions plus faible.
Hypothèse 3 : compréhension
Une meilleure segmentation visuelle devrait libérer des ressources cognitives pour le traitement sémantique et se traduire par des scores plus élevés aux QCM ou dans les réponses ouvertes.
Forces et limites
| Forces | Limites à contrôler |
|---|---|
| OpenFace 2.0 et une simple webcam réduisent fortement le coût d'expérimentation. | La précision reste limitée pour les micro-saccades ou les mouvements inférieurs à un degré. |
| Le dépôt open-source facilite la reproductibilité et l'adaptation des stimuli. | La calibration peut se dégrader si le participant modifie fortement sa posture. |
Le fichier plan.csv permet de définir plusieurs conditions et ordres d'essais. | La télémétrie à 1 Hz suffit pour les variations lentes mais peut manquer des événements rapides. |
| L'intégration du QCM, des réponses ouvertes et du regard donne une vision plus complète de la lecture. | Les stimuli doivent être adaptés aux langues, aux directions de lecture et aux profils de lecteurs. |
Conclusion
Le dépôt Dyslexia-Focused-Study-Toolkit-Reading-Experiment représente une avancée importante dans la démocratisation de l'oculométrie appliquée à la lecture. Il propose un outil accessible, libre et adaptable pour conduire des expériences complètes avec ou sans aménagements typographiques.
En combinant OpenFace 2.0, calibration, suivi du regard, télémétrie, QCM et analyse automatique, le pipeline répond à un besoin méthodologique clair : rendre les hypothèses de RUMBA.RD testables, reproductibles et discutables par la communauté scientifique.