Mes faux positifs sont devenus mon meilleur dataset
1 260 erreurs. C’est la meilleure chose qui soit arrivée à mon détecteur de météores.
Chacune de ces erreurs est une image où mon système a cru voir un météore, et où j’ai cliqué sur « Faux positif ». Mises bout à bout, elles forment aujourd’hui l’essentiel du dataset avec lequel j’entraîne un modèle de détection. Je n’ai jamais ouvert d’outil d’annotation. Le système a produit lui-même les données qui lui manquaient, parce que j’avais prévu un moyen simple de corriger ses erreurs.
Un bolide dans les captures
Tout est parti d’un bolide. En parcourant les captures d’une nuit prises par ma caméra AllSky, une caméra fisheye qui photographie le ciel entier du crépuscule à l’aube, j’en ai vu un énorme traverser le champ. Le genre d’événement qu’on rate presque toujours, parce que personne ne passe ses matinées à faire défiler les images de la nuit.
J’ai voulu qu’une machine le fasse à ma place.
Le montage est volontairement simple. Chaque capture part par SCP (une copie de fichiers via SSH) vers un Raspberry Pi 4b. Un watcher, un petit processus qui surveille le dossier d’arrivée, la récupère et la passe dans un pipeline Python qui reprend l’algorithme du module AllSky Meteor Detection.
L’algorithme passe l’image en niveaux de gris, puis repère les contours avec le filtre de Canny, qui détecte les brusques changements de luminosité. Il épaissit ensuite ces contours pour relier les fragments proches, écarte les zones nuageuses, et cherche des segments avec une transformée de Hough, la méthode classique pour trouver des lignes droites dans une image. Un masque exclut les zones du champ à ignorer.
Quand un segment passe les filtres, le pipeline publie le résultat sur MQTT, un protocole de messagerie léger très répandu en domotique, m’envoie l’image annotée sur Telegram et l’ajoute à un tableau de bord Next.js. Chaque matin à 6 heures, un bilan de la nuit tombe. Premier commit le 21 mars 2026.
Tout ce qui ressemble à un météore
Le problème de cet algorithme tient en une phrase : il cherche des traits lumineux rectilignes, et le ciel nocturne en est rempli.
Les avions en laissent. Les satellites aussi. Et parfois, le reflet de la lune sur les nuages suffit à dessiner un segment tout à fait convaincant. Pour une transformée de Hough, tout ça ressemble à un météore.
J’ai donc fait ce que tout le monde fait dans ce cas : régler les seuils.
{
"min_length": 45,
"max_length": 2500,
"hough_threshold": 120,
"max_line_gap": 8,
"dilation_iterations": 1,
"cloud_area_threshold": 1550
}
Six paramètres de détection, et chacun est un compromis. Monter min_length élimine des faux positifs, et des météores courts avec eux. Réduire max_line_gap évite de relier des étoiles entre elles, au risque de casser une traînée fragmentée. Chaque réglage échange une erreur contre une autre.
Au bout d’un moment, tourner les boutons ne fait plus progresser. Pour un algorithme qui ne voit que des contours et des segments, la traînée d’un satellite et celle d’un météore se ressemblent trop.
Deux boutons
Ce qui a débloqué la suite tient dans un détail d’interface. Le 5 avril, j’ai ajouté deux boutons sur chaque détection du tableau de bord : « Valider » et « Faux positif ».
Un clic sur « Faux positif » retire la détection du site. L’image, elle, part dans une archive avec trois fichiers : l’image source, l’image annotée et un JSON de métadonnées (horodatage, segments détectés). Un clic sur « Valider » fait la même chose du côté des positifs.
Le détail qui compte, c’est l’image source. Le pipeline dessine chaque segment détecté en vert, avec un trait de 10 pixels d’épaisseur. Si j’avais archivé seulement l’image annotée, mon futur modèle aurait surtout appris à reconnaître mon trait vert. Il aurait d’ailleurs eu d’excellents scores.
Le reste s’est fait sans effort particulier. Chaque passage en revue des détections devenait une séance d’annotation, sans que j’aie à changer quoi que ce soit à ma façon d’utiliser l’outil.
Résultat aujourd’hui : 1 260 faux positifs archivés, et 134 positifs.
Ce déséquilibre résume le problème. Pour chaque météore validé, j’ai archivé plus de neuf fausses alertes. Chacune m’a coûté un clic. Chacune est devenue un exemple de ce qu’un météore n’est pas.
Zéro
Avec ces archives, j’ai entraîné un modèle YOLO, une famille de modèles de détection d’objets rapide et très répandue, dans sa plus petite version (yolo11n). Le dataset est équilibré : les 134 positifs, 600 faux positifs, et 20 % des images mises de côté pour la validation, c’est-à-dire pour mesurer le modèle sur des images qu’il n’a jamais vues.
Premier entraînement : 50 époques (50 passages complets sur les images d’entraînement), en 640 pixels, la taille par défaut. Résultat : un mAP de 0.
Le mAP (mean Average Precision) est la métrique standard de la détection d’objets. Il mesure, entre 0 et 1, à quel point le modèle trouve les bons objets au bon endroit. À zéro, le modèle n’avait strictement rien appris.
La cause était dans les images elles-mêmes. Une capture AllSky couvre le ciel entier, et certaines traînées de météores sont extrêmement diffuses. Réduites à 640 pixels, elles cessent tout simplement d’être détectables. Je demandais au modèle de trouver quelque chose que le redimensionnement avait déjà effacé.
En 1536 pixels, le mAP50 est monté à 0,38. Le mAP50 est la version la plus courante de cette mesure : une détection y compte comme juste dès que sa boîte recouvre au moins la moitié du vrai météore. Puis le 5 septembre, j’ai reconstruit le dataset et enchaîné huit entraînements dans la même journée. Le dernier, en 1280 pixels, a tourné près de quatre heures. Il a fini à une précision de 0,81 (quand il signale un météore, il a raison 81 fois sur 100), un rappel de 0,89 (il trouve 89 % des météores présents) et un mAP50 de 0,81. Le dataset ayant changé entre-temps, je ne compare pas ces deux résultats au centième près.
La leçon dépasse largement les météores. Le prétraitement par défaut d’un framework est pensé pour le cas moyen. Si ce que tu cherches est petit, fin ou diffus, il peut l’effacer avant même que ton modèle ne le voie.
Ce que les chiffres ne disent pas
Je préfère être précis sur ce que valent ces 0,81.
Le jeu de validation compte 147 images, dont seulement 27 contiennent un météore. Un rappel de 0,89 sur 27 météores, ça représente environ trois météores manqués. C’est assez pour dire que le modèle a appris quelque chose, et beaucoup trop peu pour affirmer qu’il est fiable.
Le modèle est d’ailleurs toujours en cours d’entraînement. En production, sur le Pi, c’est encore l’algorithme classique qui tourne, avec ses seuils et ses avions. Et ça me convient très bien : chaque nuit, il continue d’alimenter l’archive.
Le bouton qui manque partout
Ce que ce projet m’a montré dépasse largement l’astronomie.
Tout système où un humain corrige une machine produit des données. Un ticket de support clos parce que l’alerte était fausse. Une suggestion refusée dans un outil. Une alerte de monitoring qu’on acquitte sans rien faire. À chaque fois, quelqu’un vient de dire au système « tu t’es trompé », avec tout le contexte sous les yeux. Dans la plupart des produits, cette information disparaît avec le clic.
La garder ne coûte presque rien. Dans mon cas : un bouton, un dossier, un fichier JSON.
J’ai parlé dans Ce que SpaceX fait de ses échecs de l’intérêt de brancher le réel le plus tôt possible. Le bouton « Faux positif » en est la version la plus modeste. Il capture chaque erreur au moment exact où quelqu’un la remarque, et c’est le moment où elle a le plus de valeur.
Si ton système peut se tromper, prévois ce bouton dès le premier jour.
Mes 1 260 erreurs sont aujourd’hui la partie la plus précieuse de ce projet. Chacune m’a coûté un clic.