Pipeline cosma-qc ================= Vue d'ensemble -------------- Le pipeline cosma-qc traite les vidéos GoPro brutes acquises par les drones sous-marins AUV COSMA pour produire des nuages de points 3D denses (PLY) et des exports web (GLB). Flux de données global ---------------------- .. code-block:: text z620 (/mnt/portablessd) ├── GX*.MP4 (brut) │ ▼ [1. Ingest] SQLite DB (jobs) │ ▼ [2. Extraction ffmpeg] GPU worker /cosma-qc-frames/job_{id}/frame_%06d.jpg │ ▼ [3. Reconstruction lingbot-map] GPU worker /cosma-qc-frames/job_{id}/reconstruction.ply │ ▼ [4. Stitch per_auv] GPU worker /cosma-qc-frames/stitch_{N}.ply (par AUV) │ ▼ [5. Stitch cross_auv] GPU worker /cosma-qc-frames/stitch_global.ply │ ▼ [6. Export GLB (à la demande)] GPU worker /cosma-qc-frames/job_{id}/reconstruction.glb Étape 1 — Ingest ----------------- **Script :** scripts/ingest.py **Rôle :** Scanner le SSD de z620, regrouper les MP4 GoPro par AUV/GoPro/segment temporel et écrire les jobs dans la base SQLite. Logique de regroupement : - Les fichiers sont groupés par numéro de caméra GoPro (GXXX). - Un nouveau segment est créé si l'écart entre deux fichiers dépasse **5 minutes**. - Chaque segment → un job en base avec statut pending. Structure d'un job en base : .. code-block:: sql CREATE TABLE jobs ( id INTEGER PRIMARY KEY, auv TEXT, gopro TEXT, segment INTEGER, files TEXT, -- JSON list of z620:/path/GX*.MP4 status TEXT, -- pending / running / done / failed worker TEXT, created_at TIMESTAMP, updated_at TIMESTAMP ); Les chemins vidéo sont stockés sous la forme z620:/chemin/absolu/GX*.MP4 pour indiquer que la source est sur z620, pas sur le worker GPU. Étape 2 — Extraction des frames --------------------------------- **Fonction :** do_extract dans le dispatcher (core .82) **Outil :** ffmpeg Paramètres d'extraction : .. code-block:: bash ffmpeg -i input.mp4 -vf fps=2,scale=1920:1080 -q:v 2 {frames_dir}/job_{id}/frame_%06d.jpg **Particularité z620 :** lorsque la source est z620:/..., ffmpeg s'exécute **directement sur z620** via SSH — seuls les JPEG voyagent sur le réseau. Les MP4 bruts ne quittent jamais z620. Filtre hors-eau (heuristique de luminosité) : - Les frames dont la luminosité moyenne est au-dessus d'un seuil sont supprimées (ciel, surface, hors-eau). - Ce filtre réduit le bruit dans la reconstruction. Reprise sur crash : - Un fichier marqueur .video_N.done est créé après chaque MP4 traité. - En cas de redémarrage, les vidéos déjà traitées sont ignorées. Étape 3 — Reconstruction 3D ----------------------------- **Fonction :** do_reconstruct **Outil :** lingbot-map (demo.py) sur le worker GPU **Entrée :** répertoire de frames {worker_frames_dir}/job_{id}/ **Sortie :** {worker_frames_dir}/job_{id}/reconstruction.ply (nuage de points dense, jusqu'à **150 millions de points**) Un viewer Viser est automatiquement démarré sur le port 8100 + job_id pendant la reconstruction pour visualisation en temps réel. .. code-block:: bash # Visualiser pendant reconstruction # naviguer vers http://{worker_ip}:{8100+job_id} Étape 4 — Stitch par AUV -------------------------- **Fonction :** do_stitch_per_auv **Déclenchement :** automatique quand **tous les jobs d'un AUV** sont en statut done. **Outil :** cosma-stitch.py **Opération :** alignement et fusion des PLY de tous les segments d'un même AUV. **Sortie :** {worker_frames_dir}/stitch_{N}.ply Ce stitch s'exécute sur le worker qui détient les PLY (pas de copie inter-workers). Étape 5 — Stitch cross-AUV ---------------------------- **Fonction :** do_stitch_cross_auv **Déclenchement :** automatique quand **tous les stitches per_auv** sont validés. **Opération :** fusion de tous les PLY par AUV en un nuage de points global final. **Sortie :** {worker_frames_dir}/stitch_global.ply Étape 6 — Export GLB (à la demande) ------------------------------------- **Outil :** trimesh (conversion PLY → GLB) **Sous-échantillonnage :** 5 millions de points (adapté web/navigateur) **Sortie :** {worker_frames_dir}/job_{id}/reconstruction.glb Un serveur HTTP minimal est lancé sur le worker (port **8300**) pour le téléchargement : .. code-block:: bash # Sur le worker python3 -m http.server 8300 --directory {worker_frames_dir} # Télécharger depuis un PC wget http://{worker_ip}:8300/job_{id}/reconstruction.glb Statuts de jobs --------------- .. list-table:: :header-rows: 1 :widths: 20 80 * - Statut - Description * - pending - Job créé, en attente de dispatch * - running - En cours de traitement (extraction ou reconstruction) * - done - Reconstruction terminée, PLY disponible * - failed - Erreur — voir logs du dispatcher