Skip to main content
Retour aux billets
Oct. 20268 min de lecture

Last Seen : j'ai appris à un drone de onze ans à retrouver une personne à partir d'une seule photo, et à demander avant de suivre qui que ce soit

Last Seen donne à un DJI Phantom 3 de 2015 une seule photo et une zone de recherche. OpenCV 5 trouve et compare chaque personne, Claude décide où regarder ensuite, et un humain répond à « Est-ce que c'est elle? » avant que le drone suive qui que ce soit. Piloté en direct dans un parc : trouvé dès le premier balayage à 0,85, suivi pendant 90 secondes, 49 épingles sur la carte.

OpenCV AI CompetitionOpenCV 5ClaudeDronesDJI Mobile SDKComputer VisionAWS LambdaSearch and RescueHackathon
J'ai écrit ce billet pour l'OpenCV AI Competition 2026 (octobre 2026), et j'ai bâti Last Seen pour la même soumission. Le code, les journaux de vol et la trace de chaque mission sont sur GitHub à github.com/JonathanSolvesProblems/last-seen; le simulateur fonctionne sans appareil et sans clé. La page de la coordonnatrice est déployée sur AWS à partir du dépôt pour une mission, alors il n'y a pas de bouton permanent vers une version en ligne ici.
La revendication en une phrase : piloté en direct le 25 octobre 2026, le drone m'a trouvé dès son premier balayage avec une correspondance de 0,85, un humain l'a confirmé, et il m'a suivi pendant 90 secondes avec 49 épingles sur la carte de la coordonnatrice, chaque chiffre étant lu dans les fichiers de mission du dépôt par un script qui fait échouer la construction si le texte et les données ne concordent pas. Ce sont mes propres vols, avec moi comme sujet, et personne d'autre ne les a corrigés; l'erreur des épingles par rapport au GPS d'un téléphone était prévue et n'a pas été mesurée, et une photo prise à hauteur des yeux n'a obtenu que 0,24 pour la même personne vue des airs.
Carte titre : une photo de profil ronde au-dessus du logo Last Seen, avec la ligne « A photo in, a person found, and nothing happens until a human says that's them. » et jonathansolvesproblems.com.
Last Seen : un drone de 11 ans fouille un parc à la recherche d'une personne à partir d'une seule photo, et un humain confirme avant qu'il suive qui que ce soit.

Une seule photo et un vieux drone

Imaginez une coordonnatrice de recherche dans un parc à la brunante. Un homme atteint de démence a quitté sa résidence il y a une heure. Elle a une seule photo prise ce matin et un bénévole avec un vieux drone grand public. C'est un personnage composite; le travail, lui, est réel. L'appareil aussi : un DJI Phantom 3 Standard de 2015, sans détection d'obstacles et avec un lien vidéo en 720p, piloté par une application Kotlin sur le téléphone qui fait sortir la vidéo et entrer les commandes. La personne que le drone trouve dans la vidéo, c'est moi, avec mon consentement.

OpenCV voit, à chaque image

Trois boucles sont gardées séparées exprès. La première, c'est OpenCV 5 à chaque image. cv2.dnn, le nouveau moteur de graphes, exécute YOLO11n pour les personnes en environ 41 à 50 ms par image sur le processeur d'un portable. Chaque personne est ensuite comparée à la photo de deux façons : le réseau de réidentification de personnes du Model Zoo d'OpenCV et des histogrammes HSV des vêtements par bande du corps, fusionnés en un seul score. Un modèle de caméra transforme les pieds de chaque boîte en un point au sol, et c'est ce point qui arrive sur la carte de la coordonnatrice.

Vue aérienne d'un champ intérieur de baseball : un homme en veste de cuir noire qui marche sur la terre battue rouge dans une boîte orange étiquetée person 0.79, avec un encart OpenCV 5 DNN, YOLO person detector, 41 ms per frame, 24 fps, 1 person.
Le moteur DNN d'OpenCV 5 exécute un détecteur de personnes YOLO sur la vidéo du drone : 41 ms par image, 24 i/s, sur le processeur d'un portable.
Vue aérienne d'un homme qui s'éloigne sur la terre battue, encadré avec un score de 0,39, et un panneau qui compare l'image du drone à la photo de référence : réseau de réidentification 0,48, couleur des vêtements 0,19, correspondance 0,39.
Chaque personne est comparée à la photo de deux façons : le réseau de réidentification du Model Zoo d'OpenCV et les couleurs de ses vêtements.

Claude décide où regarder, jamais qui est quelqu'un

La deuxième boucle, c'est Claude, toutes les quelques secondes. Il a six outils stricts : scan_here, fly_to, look_closer, ask_coordinator, follow_confirmed et end_mission. Il voit le tableau des candidats et les images recadrées et choisit la suite. Pendant qu'il réfléchit, l'environnement d'exécution garde l'appareil en vol stationnaire et en perception, et chaque décision est écrite dans trace.jsonl. La troisième boucle, c'est une personne, une seule fois. ask_coordinator affiche « Est-ce que c'est elle? » sur le téléphone de la coordonnatrice avec la photo à côté de ce que voit le drone. La page est une URL de fonction Lambda, et la réponse est une écriture conditionnelle DynamoDB, alors une deuxième réponse à la même question est refusée.

La page de la coordonnatrice : « Is this them? » avec l'image du drone à côté de la photo de référence, Strong match 0.85, les boutons That's them et Not them, la description de la personne par le drone, et une carte avec des anneaux espacés de 10 m autour du dernier point connu.
La mission 3 m'a trouvé dès son premier balayage à 0,85 et a demandé. La page est servie par AWS Lambda; DynamoDB garde la réponse.

Trois missions dans un parc

Le 25 octobre 2026, j'ai piloté trois missions dans un parc public en jouant la personne disparue. La mission 1 utilisait une photo prise à hauteur des yeux. Vu des airs, je n'ai jamais dépassé 0,24, alors il a regardé de plus près deux fois, fouillé deux coins, n'a jamais rien demandé à personne, et je l'ai rappelé. C'est le bon comportement pour une correspondance faible, et c'est le cas difficile. La mission 2 utilisait une photo aérienne : il a regardé de plus près à 0,76, a demandé, a été confirmé, et m'a suivi pendant 90 secondes avec 49 épingles. Dans son propre résumé, l'agent a écrit que le verrouillage n'a tenu que 47 % du temps et qu'il m'a perdu sept fois. La mission 3 m'a trouvé dès le premier balayage à 0,85, a demandé, a été confirmée, et m'a suivi jusqu'à ce que la batterie atteigne son seuil de 18 % après 64 secondes; l'enveloppe a alors interrompu la mission et l'appareil s'est posé tout seul.

Vue aérienne de la bordure d'un champ intérieur en terre battue et du gazon, avec un trépied et un homme en veste noire encadré avec un faible score de 0,15.
Mission 1, avec une photo prise du sol : je n'ai jamais dépassé 0,24, alors il n'a jamais rien demandé à personne. C'est le cas difficile.
Vue aérienne d'un parc en automne avec un homme en veste noire au bord du champ intérieur, et un encart intitulé « the map on her phone, live » qui montre la trace blanche du drone autour d'épingles P1, P2, P4 et P5 dans des anneaux espacés de 10 m.
Après qu'un humain dit que c'est la bonne personne, il la suit et dépose une épingle chaque seconde. Mission 2 : 90 s, 49 épingles, verrouillage tenu 47 %.

La vérification de la caméra elle-même

J'ai imprimé des marqueurs ArUco de 190 mm et je les ai vérifiés avec une règle. La calibration complète n'a pas été faite en vol, mais les marqueurs apparaissent dans la vidéo de bord, alors la vérification de la caméra a été faite après coup sur les images. solvePnP d'OpenCV, sur un seul marqueur, place la caméra à 5,9 m au-dessus alors que le baromètre indiquait 8,0 m. L'écart est stable, environ 2 m, ce qui pointe vers le modèle d'objectif de la fiche technique plutôt que vers du bruit, et le rapport le dit.

Diapositive intitulée The camera's own check, qui explique que solvePnP sur les images de vol place la caméra à 5,9 m au-dessus des marqueurs ArUco de 190 mm alors que le baromètre indiquait 8,0 m, à côté d'une photo aérienne de deux marqueurs imprimés fixés sur la terre battue.
solvePnP sur les marqueurs imprimés visibles dans les images de vol place la caméra à 5,9 m alors que le baromètre indiquait 8,0 m.

Une sécurité qu'une consigne ne peut pas promettre

follow_confirmed lève NotConfirmed pour toute personne que la coordonnatrice n'a pas confirmée. C'est du code, pas une consigne, et c'est testé. L'enveloppe (géorepérage, plafond, vitesse, seuil de batterie et arrêt si le lien devient périmé) est vérifiée à chaque cycle de contrôle dans pilot.py, et l'agent ne peut pas l'élargir. La coordonnatrice peut rappeler l'appareil à partir de la page, et l'interrupteur de mode du pilote a priorité sur tout : je le rebascule et les manettes sont à moi. La sécurité ne dépend jamais de l'aller-retour vers le nuage.

Diapositive intitulée Safety that a prompt cannot promise, qui montre la vérification de follow() dans runtime.py qui lève NotConfirmed pour toute personne non confirmée, et les vérifications de batterie et d'altitude à chaque cycle dans pilot.py qui lèvent Abort.
La sécurité vit dans le code, pas dans la consigne : aucun suivi sans personne confirmée, et l'enveloppe vérifie chaque cycle de contrôle.

Ce qui n'est pas revendiqué

Chaque chiffre de ce billet vient de mes trois propres vols, avec moi comme seul sujet, alors rien n'est corrigé par quelqu'un d'autre; ce que le dépôt garantit, c'est que le texte concorde avec les fichiers de mission, parce qu'un script fait échouer la construction quand ils ne concordent pas. L'erreur des épingles par rapport au GPS du téléphone du sujet et la vérification de l'angle de la nacelle avec les marqueurs imprimés étaient prévues et n'ont pas été mesurées. L'identification repose sur les vêtements et la silhouette, pas sur le visage : une photo avec d'autres vêtements ne correspondra pas, deux personnes habillées pareil sont toutes deux soumises à la coordonnatrice, et une photo prise à hauteur des yeux ne correspond pas à la même personne vue d'en haut, ce qui est le prochain problème. Une personne a parfois été séparée en deux pistes, et l'agent l'a signalé au lieu de le cacher. Le décollage autonome a échoué à chaque tentative le 30 septembre et a fonctionné le 25 octobre. Il n'y a pas de détection d'obstacles : l'appareil est gardé au-dessus d'un terrain dégagé par le géorepérage et le plafond. Le Phantom est immatriculé auprès de Transports Canada et a été piloté avec un certificat de pilote de base, en visibilité directe, loin des passants.

Projet associé

Last Seen: an eleven-year-old drone finds a person from one photo with OpenCV 5, asks a human "Is this them?", and only then follows

Voir le projet