Version 2.1.0 — macOS Apple Silicon Gaussian Splatting Pipeline
- Purpose: All-in-one GUI + CLI tool for Gaussian Splatting 3D reconstruction on macOS
- Author: Frederick (freddewitt) — github.com/freddewitt/CorbeauSplat
- License: MIT
- Python: 3.13+ (main), 3.11 (ML Sharp venv)
- Stack: PySide6, COLMAP/Glomap, Brush (Rust/WGPU), Apple ML Sharp, upscayl-ncnn, opencv-python-headless
- File count: ~78 Python files
# GUI mode (default, no args)
python3 main.py
# CLI modes
python3 main.py pipeline -i video.mp4 -o ~/projects --preset dense
python3 main.py colmap -i images/ -o ~/projects
python3 main.py brush -i dataset/ -o dataset/ --preset dense
python3 main.py view -i splat.ply
python3 main.py upscale -i image.png -o ~/out --scale 4
python3 main.py clean -i splat.ply --strength strong
python3 main.py clean -i noisy.ply -o cleaned.ply --then-export spzVue d'ensemble : main.py (entry) → app/cli/ (dispatch CLI) et app/gui/ (PySide6, studio_window.py/StudioWindow shell Qt ; l'enchaînement des étapes vit dans pipeline_orchestrator.py (sans Qt, registre @pipeline_step) — interface à 3 zones : rail gauche, centre, barre d'activité (activity_bar.py — étape en cours, détail, progression, Annuler ; le journal a sa propre fenêtre, logs_window.py) — + panels/ par module) s'appuient tous deux sur app/core/ (moteurs, tous héritant de base_engine.py/BaseEngine : engine.py/ColmapEngine, brush_engine.py, sharp_engine.py, upscale_engine.py, superplat_engine.py, four_dgs_engine.py, extractor_360_engine.py, export_engine.py, ply_cleaner.py, splat_transform_engine.py). colmap_commands.py isole la construction des argv COLMAP (SRP, extrait de ColmapEngine — v1.2.3). media.py centralise les formats acceptés — conteneurs vidéo (FFmpeg) et images, avec la conversion automatique des formats non lisibles par toute la chaîne (HEIC/TIFF/BMP/WebP… → PNG ou JPEG) ; les trois sites de détection (panneau Source, ColmapEngine, FourDGSEngine) y puisent la même liste. app/scripts/installers/ installe les binaires externes dans engines/.
Le rail gauche (hiérarchie statique à trois niveaux : Projet, ENTRAÎNEMENT, OPTIONS, OUTILS) et le bandeau/barre d'activité sont décrits en détail dans docs/manifest-detail.md.
Détail (fichiers, classes, patterns, moteurs, dépendances, sécurité) → graphify query "<question>" ou graphify explain "<concept>". Ne pas dupliquer ici ce que le graphe retrouve déjà.
- E2E réel = pipeline principal seulement —
pytest -m e2ecouvre COLMAP → Brush → clean → export SPZ (7 tests, ~21 s). Upscale/Sharp/360/4DGS couverts en e2e réel (21 tests, ~6 min, marqueurs dédiés). Suite par défaut : 1023 pass, 5 skip (2026-09-23), dont 5 fichiers lançant un PySide6 réel en sous-processus viatests/_real_qt.py— le mock PySide6 deconftest.pyest global à la session et irréversible, donc un vrai panneau ne peut être instancié qu'ainsi, etcoveragene suit pas l'enfant sansparallel = true+ amorçage explicite (sans quoi les panneaux paraissent non couverts tout en s'exécutant). Couverture 68 %. Marqueurs e2e :e2e_sharp,e2e_upscale,e2e_4dgs,e2e_360en plus dee2eumbrella (e2e désélectionné). GLB export tests skip sitrimesh/open3dabsents - Workers tested headless via mock PySide6 —
conftest.pypatches PySide6 at session scope, but import chain still requires numpy mock for CI
| Version | Key Changes |
|---|---|
| 2.0.0 (2026-09-23) | Version stable. Audit « version stable » (docs/AUDIT_STABLE.md, rapports par lot dans docs/audit-stable/) : 9 lots — GUI panneau par panneau, CLI argument par argument, automatisation scénario par scénario, e2e réels. 78 défauts relevés, 54 corrigés avec tests de régression. Bloquants : reprise COLMAP jamais câblée ; sortie Sharp non isolée par projet ; PLY introuvable sans étape Brush ; format Upscale jpeg refusé ; extract360 --layout par défaut refusé ; 4DGS mono-caméra impossible ; sous-modèle COLMAP : le mapper mettait l'ébauche en sparse/0 et le vrai modèle en sparse/1 (nouveau app/core/sparse_models.py, promotion du plus grand modèle, pipeline principal et 4DGS) ; FFmpeg 9 refusait -vsync. Nouveautés issues de l'audit : sharp --upscale réel, brush --refine_mode réel (app/core/brush_refine.py partagé GUI/CLI), trim vidéo en 4DGS, skip_frames Sharp et « Récursif » Nettoyage dans la GUI, device Brush auto, flags de chaînage restaurés à la reprise. Dernières décisions : réglage Notifications persisté dans config.json (L6-01) ; cases « Nettoyage/Exporter/SuperSplat après » et « Lancer Brush » honorées par les boutons Lancer locaux des pages OUTILS via le mécanisme de chaîne (L3-05/L5-08, un seul slot finished_signal). 1023 tests, e2e réels 28/28. |
| 2.0.0-rc1 (2026-09-20) | Première release candidate, publiée sur main (la 1.5.1 vit désormais sur la branche v1). Code identique à beta.5 ; README réécrit pour la v2 (chaîne en un clic, plage vidéo, conversion d'images, galerie Upscale, configurations nommées), .serena et opencode.multimodel.json sortis du suivi git. Reste : validation manuelle sur Mac (points 6 et 7). |
Historique 2026-09-20 (beta.5 : plan d'audit 8 lots, audit de code complet ; journal réparé, chargement de configuration sans téléchargement) et versions ≤ beta.4 : docs/manifest-detail.md. Versions ≤ 1.0.6 : CHANGELOG.md (historique complet).
Source (vidéo/images) → [Extraction 360] → [Upscale] → FFmpeg (si vidéo) → filtre flou → COLMAP (features/matcher/mapper) → [Undistortion] → Brush (config + entraînement) → .ply → [Nettoyage] → [Export SPZ/GLB/OBJ/XYZ]. Séquence réelle : PIPELINE_STEPS / plan_pipeline(). Diagramme détaillé → docs/manifest-detail.md.
9 languages via assets/locales/{lang}.json, 283 keys each. LanguageManager singleton with Observer pattern. Fallback chain: selected → en.json → fr.json → empty dict.
Verrouillé par tests/test_locales.py : les 9 fichiers doivent avoir exactement les mêmes clés, aucune clé ne doit être orpheline (jamais référencée dans app/), et toute clé passée en littéral à tr() doit exister dans les 9 langues.
.venv/: Main app (Python 3.13 recommended, PySide6, etc.).venv_sharp/: ML Sharp (Python 3.11 — required by Apple's fork).venv_360/: 360Extractor (isolated environment)
pipeline, colmap, brush, sharp, view, upscale, 4dgs, extract360, clean, splattransform
Each has --help. No subcommand = GUI mode. Full reference: CLI.md
pipeline runs COLMAP → Brush, then Cleaning and Export when asked:
--clean [light|medium|strong] (bare flag = medium) and --export FORMAT
(--export_output to redirect). Checkpoints land in
<output>/<project>/checkpoints, the same place the interface uses.
- Backlog mineur traité (D5, D8, D9, D13, L3-08, L3-11, L5-10) ; décisions prises : L5-07 laissé tel quel (gel d'annulation ≤ ~7 s, limite connue), D3 FPS vidéo = 5 partout, L6-02 lanceur : moteurs désactivés ignorés + confirmation avant installation, L6-04 documenté (README). Commits
75f3ed9,7feb53a, tagv2.0.1poussés. - ✅ D14, M11, M8 clos le 2026-10-08 (commit
16f731b) : D14 — aucune version de Brush (release v0.3.0 viabrush --help, git main via les structs clap) ne connaît--save-iterations,--refine-pose,--log-levelni--test-split: retirés de l'allowlist et deBrushParams(anciens presets toujours chargés, clés ignorées) ;eval_every(le seul réel) gagne un spinbox « Éval. toutes les N étapes (0 = jamais) » dans le groupe Checkpoints. Allowlist par mode de build : release et source (main, 200 commits plus loin) n'acceptent pas les mêmes options —BrushEngine.COMMON_FLAGS(27) +RELEASE_ONLY_FLAGS(8 :--lr-scale-end,--opac-loss-weight,--rerun-*…) +SOURCE_ONLY_FLAGS(16 :--growth-start-iter,--lod-*,--alpha-mode…),allowed_flags(build_mode)choisit ; un flag de l'autre mode est signalé comme tel dans le journal ; l'infobulle du champ « Arguments suppl. » liste les options du mode choisi (clébrush_args_tooltip).SOURCE_ONLY_FLAGSest un instantané du 2026-10-08 (main bouge) à rafraîchir viabrush --helpdu binaire compilé. Clés i18nbrush_eval_every,brush_args_tooltipdans les 9 langues ; 13 tests. Groupes d'options par mode de build (GUI) : deuxQGroupBoxcochables sous Checkpoints, affichés selon le mode choisi dans Avancé — « Options release (0.3.0) » (lr_scale_end,opac_loss_weight,scale_loss_weight,aux_loss_time) et « Options build git » (growth_start_iter,split_at_screen_size,alpha_mode,invert_masks,units_per_meter,opac_decay,min_scale_factor,background_noise_strength,lod_*×4) ; valeurs préremplies = défauts Brush, groupe décoché = rien envoyé, et seules les valeurs du mode actif sortent deget_params(). ChampsBrushParamscorrespondants (None = défaut), repliés danscustom_argsparto_engine_params()uniquement pour lebuild_modequi les accepte (--invert-masksémis nu, en dernier) ; un preset chargé qui contient ces valeurs coche le groupe. 19 clés i18n ×9 ; 8 tests de plus. Non couverts :background_color,render_mode,random_init_scene_scale,max_scene_batch_cache_size,rerun-*(restent accessibles via « Arguments suppl. »). M11 —_build_center()dereconstruction_panel(4 sections) etentrainement_panel(6 sections) découpés à la main, chaque section recevantlayout; empreinte structurelle (arbre de widgets, états, libellés dans les 9 langues) identique avant/après. M8 —linux_brushétait déjà renseigné et correspond ausha256.sumofficiel v0.3.0 : rien à changer. Suite : 1077 pass, 5 skip.test_journal_integrityrepasse (4/4) depuis la clôture du 2026-10-08. - Réglages Apple Silicon (2026-10-07, intégrés à 2.0.1,
9aa073c/feb23b2) : pas denice, threads = P-cores (compute_env, aussi pour NumPy viaapp/__init__.py), ALIKED/LightGlue forcés CPU (use_gpu 0, ~6× plus rapide que CoreML), sonde VideoToolbox/MPS. À faire par l'utilisateur : déplacer le tagv2.0.1(encore sur7feb53a) →git tag -f v2.0.1 HEAD && git push -f origin v2.0.1.
- Audit v2026.1 (statuts dans
audit_journal.json, gitignoré) : clos en 2.1.0 (2026-10-12, commits3bb13c7+ session 7, poussés, tagv2.1.0). Majeurs 45/45 (StudioWindow →pipeline_orchestrator.py), mineurs 137/137 tranchés : 11 (injection moteurs Export/Nettoyage), 55 (détection source dans_SourceScanWorker), 115 (modèles Upscale non vérifiés signalés), 87 (requirements.lockdéjà en place) corrigés ; 103, 9, 10, 22, 32, 60, 133 acceptés tels quels (décision utilisateur). Messages deply_cleaner/upscayl_managerencore en français. À valider en GUI réelle : chaîne complète après extraction de l'orchestrateur, combo formats SplatTransform, X/Y/Z Visualiser, info CPU Reconstruction, redémarrage après réinstallation, question de MAJ au démarrage, rail en arabe (RTL). - splat-transform 3.10.0 + format SOG (2026-10-07, non commité) : pin npm 2.7.1 → 3.10.0,
sogajouté (CLI, panneau SplatTransform). À faire : tester une vraie conversion.sog, commiter ; option de sortiesplatdu panneau non supportée par 3.10.0 ; décider si l'export GLB passe par splat-transform (GLB actuel ≠KHR_gaussian_splatting) ; COLMAP 4.2.1 pas encore dans Homebrew (installé : 4.2.0) ;graphify updaterefusé (1726 vs 1727 nœuds),--forceen attente. - ✅ Câblage conversion d'images + Upscale depuis l'interface validé le 2026-09-22 (Qt réel offscreen, vrai upscayl-bin) : chaîne Source → Upscale → Reconstruction avec
upscaler_avantsur dossier mixte jpg/tif/bmp/webp/heic, et bouton Lancer local (dossier et HEIC seul). Filtre « Parcourir › Image » aligné surmedia.IMAGE_EXTENSIONSle 2026-09-23 (audit L2-02). - Source =
<projet>/images/lui-même (2026-09-22, non commité au moment de l'écriture) : les originaux sont déplacés dansimages_src/(protocole de l'upscale) etimages/est reconstruit converti ; l'upscale enchaîné agrandit alors les copies d'images/viaimages_upscaling/. VoirColmapEngine._move_project_images_aside/_run_upscale. Chaîne complète validée le 2026-09-22 (Qt réel offscreen, vrais COLMAP/Brush/upscayl/SuperSplat, tous drapeaux : flou, undistort, upscale, Brush, clean, export spz, viewer) sur source images et vidéo ; 3 défauts corrigés, non commités : format 360 envoyéjpeg(→jpg, data du combo), upscale non récursif après Extraction 360 (→rglob+_staged_names(root=)), sorties Nettoyage/Export collées au 1er projet lors d'un 2e lancement (→is_chain_owned+_chain_prefilled). Reste : reconstruction 360 sur vraies données (le panorama synthétique n'a pas assez de texture pour COLMAP).
- E2E 4DGS Phase A ✅ — session 12, 4 tests (mode COLMAP dégradé), marqueur
e2e_4dgs. Phase B (nerfstudio,.venv_4dgs) restante. (ffmpeg + COLMAP + nerfstudio, coûteux) - Validation manuelle sur Mac de la refonte session 14 — aucun test automatisé ne couvre le rendu Qt réel. À vérifier : FPS visible seulement en source vidéo, bannière de mélange images+vidéo, colonne droite et filet masqués sur les bons écrans, chaînage réel bout-en-bout sur vraies données, molette sur les combos Réglages (ne doit plus rien changer), bannière 4DGS et tooltip
4dgsdu combo Mode. Ajouts du 2026-09-17 à vérifier aussi : galerie de modèles Upscale (volet droit — poids affiché, Télécharger puis Supprimer, modèles « Inclus » sans action, combo et cartes qui restent d'accord) ; réglages COLMAP du panneau 4DGS (chevauchement grisé hors matcher séquentiel) ; « Lancer » en mode Sharp puis en mode 4DGS depuis le panneau Source. - Validation manuelle sur Mac des chantiers du 2026-08-07 (Upscale, champs Projet, suppressions, 360) — la GUI PySide6 n'a pas été exécutée pendant le chantier. À vérifier : Upscale en tête du groupe PARAMÈTRES (filet vertical continu l'incluant) et absent d'OUTILS ; colonne droite et filet masqués sur la page Upscale ; toggle « Upscaler avant reconstruction » en tête du bloc Automatisation, décoché au démarrage ; chaîne source images — fichiers présents dans
<sortie>/<projet>/images_upscaledavant le démarrage de COLMAP et dossier source d'origine intact ; chaîne source vidéo — message différé affiché puisimages_src/créé pendant la Reconstruction ; bouton Lancer local depuis PARAMÈTRES › Upscale, indépendant du Lancer global ; sauvegarde/rechargement d'une configuration nommée avec réglages Upscale non-défaut. Extraction 360 — en tête de PARAMÈTRES (avant Upscale) tout en restant dans OUTILS, les deux pages devant être indépendantes (saisir un chemin dans l'une ne change rien dans l'autre) ; chaînesource_360seul puissource_360+upscaler_avant, avecimages_360/peuplé avantimages_upscaled/, lui-même avant le démarrage de COLMAP. Champs Projet —checkpoint_destrenseigné : l'export chaîné doit retrouver le PLY dans<destination>/<projet>/(c'est le cas de régression réel du chantier) ;export_dir/export_formatrenseignés : le run chaîné doit les respecter plutôt que la saisie du panneau Export. Suppressions — 🗑 grisé sur « Défaut » et sur un preset intégré, actif sur un preset personnel ; bouton « Supprimer… » des Réglages (liste, confirmation, disparition effective). - L'épinglage Brush devra être bumpé à la main à chaque release amont (
brush_release+ empreinte, ensemble). C'est désormais signalé au démarrage au lieu de casser l'installation, mais ça reste une action manuelle récurrente. Automatiser suppose une racine de confiance indépendante de l'artefact (attestations GitHub/sigstore) — pas le sidecar.sha256, qui vient de la même origine. - 360Extractor
--export-colmap(2026-09-11) — flag découvert lors de l'audit dépendances tierces, non intégré. Écrit une calibration virtuelle + config de rig + scriptreconstruct.pyen plus des images extraites, exploitables par COLMAP (rig_configurator) pour éviter à la Reconstruction de redeviner des poses caméra déjà connues (utile en 360°, layoutcube). Non implémenté : upstream indique lui-même « full reconstruction qualification is pending » — feature encore expérimentale côté 360Extractor. Design d'intégration esquissé si repris : flagRunState.extraction360_export_colmap(opt-in, actif seulement si layoutcube),Extractor360Engineajoute--export-colmap,_build_colmap_worker()bascule vers un chemin de reconstruction assisté (logique répliquée danscolmap_commands.py, pas d'appel au script externe généré, pour rester cohérent avec les garanties sécurité du reste du code) avec repli automatique sur la Reconstruction standard en cas d'échec/COLMAP trop ancien. Pas de changement d'ordre du pipeline nécessaire (Extraction 360 tourne déjà avant Reconstruction). À reprendre seulement après validation de la qualité de sortie côté 360Extractor. - LightGlue/ALIKED déjà actif, LoMa (COLMAP 4.2.0) à évaluer (2026-09-13) — Audit ONNX :
SIFT_LIGHTGLUE/ALIKED_LIGHTGLUEsont déjà entièrement câblés (app/core/params.py,app/core/colmap_commands.py, CLIapp/cli/parser.py, GUIreconstruction_panel.py) et accélérés par défaut sur Mac via CoreML (COLMAP_COREML_ENABLEDactif inconditionnellement sur macOS dans le build COLMAP,use_gpu=1non surchargé par l'app) — à vérifier en pratique avant de considérer le gain acquis : logsGLOG_v=2doivent afficher « Enabling CoreML execution provider », sinon repli silencieux vers le CPU. Piste ouverte : matcher LoMa (LOMA_B/B128/L/G/R, PR colmap/colmap#4524, mergé en 4.2.0 — version déjà installée) annoncé plus robuste que LightGlue sur scènes difficiles (faible texture, gros mouvements caméra), mais poids encore hébergés sur le repo perso de l'auteur (pas encore asset officiel COLMAP). Non implémenté — à ajouter seulement si un test réel (comparaison sur nos propres jeux d'images) montre LightGlue insuffisant ; extension mineure des mêmes structures, aucune nouvelle dépendance.
Un graphe de connaissance est maintenu dans graphify-out/. Pour toute question d'architecture : graphify query "<question>". Hook post-commit installé → graphe rafraîchi automatiquement après chaque commit (extraction code AST ; l'extraction sémantique des docs nécessite une clé API, sinon ignorée).