MiniBox · Compteur cycliste autonome
novembre 2022 → novembre 2023
MiniBox, un compteur de vélos open source
MiniBox est mon projet de mémoire de licence pro APSIO, mené en binôme avec Noémie Tandol. C'est le projet dont je suis le plus fier, surtout pour ce qu'il essayait de résoudre.
Le problème
Le trafic cycliste augmente depuis plusieurs années : la pandémie, le vélo à assistance électrique, l'amélioration des infrastructures. Pour adapter les aménagements, encore faut-il pouvoir mesurer ce trafic, et de façon assez fine et étendue pour en tirer des conclusions. Les compteurs cyclistes professionnels existent, mais ils coûtent cher, ce qui cantonne leur déploiement à quelques points stratégiques.
L'idée était donc de construire un compteur miniature et autonome, tournant sur un Raspberry Pi, à un coût assez bas pour en poser beaucoup plutôt que quelques-uns. Les destinataires visés : les collectivités qui veulent évaluer l'effet de leurs aménagements, et les associations de promotion du vélo comme 2 pieds 2 roues ou l'AF3V.
Le projet est sous licence GPL-3.0. L'open source était une condition, pas une coquetterie : un outil de mesure censé éclairer une décision publique doit pouvoir être audité par n'importe qui.
Pourquoi YOLO plutôt qu'un autre modèle
Avant d'écrire la moindre ligne, on a comparé les grandes familles de détection d'objets. Faster R-CNN et Mask R-CNN sont très précis, ce dernier va même jusqu'à segmenter finement chaque objet, mais ils sont lents. RetinaNet excelle sur les petits objets denses, ce qui explique son usage en imagerie aérienne et satellite, mais ce n'était pas notre cas. SSD est rapide et gère plusieurs tailles de boîtes ; YOLO aussi, avec l'avantage de tout faire en une seule passe sur l'image, ce qui le rend adapté au temps réel.
Comme notre contrainte principale était de tourner en direct sur du matériel modeste, YOLO s'est imposé. Sa faiblesse connue, la difficulté sur les très petits objets et les scènes très chargées, n'était pas bloquante pour compter des vélos filmés d'assez près.
Comment ça marche
Le système tient sur trois couches.
La détection. YOLOv5, exécuté avec PyTorch, repère les objets dans le flux vidéo. Il identifie les vélos image par image, sans aucune mémoire d'une image à l'autre.
Le suivi. C'est là qu'est la vraie difficulté, et c'est ce qui m'a le plus appris. Détecter un vélo sur une image ne suffit pas à le compter : sans suivi, le même vélo présent sur trente images consécutives serait compté trente fois. On a commencé avec la bibliothèque SORT, puis on est passés à Norfair, qui maintient l'identité d'un objet entre les images. On compte alors des passages, et non des détections. Au passage, en comparant les positions successives d'un même vélo, le programme en déduit son sens de circulation.
La visualisation. Une interface Django reçoit les comptages et les affiche avec Chart.js, sous forme de graphiques filtrables par date et par type d'objet.
Sous le capot
Le programme est découpé proprement : un point d'entrée main.py, un config_handler.py qui lit la configuration depuis un fichier config.ini, et un dossier Functions qui regroupe le gros de la logique (l'interface avec YOLOv5, la détection, le suivi des objets, les utilitaires).
Le calcul de direction est un petit morceau dont je suis assez content, parce qu'il est simple et efficace. Pour chaque objet suivi, on garde ses dernières positions, on regarde les quatre dernières et on en tire un déplacement moyen. Si l'objet bouge assez vite, au-dessus d'un seuil qui sert à ignorer le bruit et les objets immobiles, on en déduit un des quatre sens : haut-gauche, haut-droite, bas-gauche, bas-droite. C'est ce qui permet de dire non seulement combien de vélos passent, mais dans quel sens.
Entre YOLO et Norfair, il a fallu un adaptateur : YOLOv5 renvoie ses détections sous forme de tenseur PyTorch, que je convertis en objets attendus par Norfair (coordonnées de la boîte, score de confiance, classe). Rien de spectaculaire, mais c'est le genre de plomberie sans laquelle deux briques ne se parlent pas.
Enfin, le projet a des tests unitaires lancés à chaque commit et chaque pull request sur les branches develop et master, pour éviter de casser une fonctionnalité en en réparant une autre. Et la configuration se duplique facilement pour séparer un profil de développement d'un profil de production.
Le cadre juridique
Un compteur qui filme la rue pose forcément la question du droit, alors on a creusé le sujet, et il est moins évident qu'il n'y paraît. En France, seules les autorités publiques comme les mairies peuvent filmer la voie publique. Une entreprise ou un particulier n'en a pas le droit, même pour surveiller sa propre voiture garée devant chez lui.
La CNIL considère toutefois comme légitime l'usage de caméras sur la voie publique pour compter les piétons, les voitures et les vélos dans un but d'aménagement, à condition que le dispositif soit autorisé par les services publics quand les personnes filmées ne peuvent pas exercer leur droit d'opposition. Côté RGPD, la règle clé est simple : si la vidéo ne permet pas d'identifier une personne, directement ou indirectement, l'essentiel du cadre ne s'applique pas. Un floutage irréversible est d'ailleurs considéré comme un effacement conforme.
C'est exactement ce qui a orienté la conception. En traitant le flux en direct, sans jamais enregistrer d'image, on ne conserve que des comptages anonymes. On se place ainsi du bon côté de la ligne dès le départ, plutôt que de bricoler une conformité après coup.
Le cheminement
Rien n'est sorti droit du premier coup. La première version prenait des photos à intervalle régulier avant de les analyser : trop lent, et surtout problématique côté réglementation puisqu'on stockait des images de la rue. On est ensuite passés au traitement du flux en direct, ce qui a réglé la question du RGPD en même temps que le problème de vitesse. La dernière version exploite une carte graphique Nvidia pour tenir la cadence.
Concrètement, sur une vidéo test de 3 min 54 (7096 images) avec un fort passage de vélos, coureurs et voitures : 20 vélos réels, le programme en a compté 21, le tout traité en 3 min 34 à environ 33 images par seconde. Correct, avec quelques erreurs sur les directions.
Les limites
Je préfère aussi dire ce qui n'a pas marché. Le suivi confond parfois les identités et attribue l'identifiant d'une voiture à un vélo. L'installation sur Raspberry Pi s'est révélée plus pénible que prévu. Et on n'a jamais réussi à détecter ce qu'on visait au départ, comme savoir si un vélo est chargé ou si le cycliste porte un équipement de protection.
Et après
Le projet s'arrête au niveau d'un prototype convaincant, mais les pistes ne manquent pas. La plus directe serait de passer à YOLOv8, qui intègre son propre suivi et rendrait Norfair inutile ; on a commencé à l'explorer mais on a buté sur une bibliothèque (lap) incompatible avec notre version de Python sous Windows.
Au-delà, entraîner notre propre modèle permettrait de détecter des choses que les modèles génériques ignorent : un vélo chargé de sacoches, un vélo électrique, une personne en équipement de protection. Dans la même veine, Grounding DINO ouvre la détection à partir de simples phrases, du genre repérer toutes les personnes portant un gilet de sécurité jaune, sans réentraîner quoi que ce soit. Restent deux améliorations plus terre à terre : une image Docker pour installer le tout sur un Raspberry Pi sans se battre avec les dépendances, et des zones de détection définies à l'échelle d'une rue pour affiner encore les statistiques.
Ma première contribution open source
Sur ce projet, j'ai pour la première fois remonté un bug et proposé une solution sur un dépôt open source. Ça m'a permis de faire un premier pas dans ce monde et d'offrir mon aide, à mon niveau. Pour la petite histoire, je n'avais pas tout fait dans l'ordre et ma proposition ne réglait pas vraiment le problème, mais elle a au moins permis de le signaler.