@@ -28,8 +28,50 @@ docker run -v .:/working ghcr.io/educelab/pgs-recon:latest \
2828Upon successful completion of the pipeline, your reconstructed model can be
2929found in ` recon/mvs/my-object.obj ` .
3030
31+ ### What lands in the output directory
32+ Every intermediate is named ` <stage>_<role> ` , after the stage that produced it,
33+ so a half-finished directory can be read for what has happened so far. Optional
34+ stages are marked; the rest are always present:
35+
36+ ```
37+ recon/
38+ pgs-recon.json # the manifest: what ran, and with what arguments
39+ my-object_recon_config.txt # the effective arguments, loadable with -c
40+ mvg/
41+ sfm_data.json # the imported scene
42+ matches_dir/ # per-image features, matches[_filtered].bin
43+ recon_dir/
44+ sfm_data.bin # the solve
45+ robust_sfm.bin # --mvg-robust
46+ autoscale_sfm.bin # --mvg-autoscale
47+ landmarks[_scaled].ply # --mvg-autoscale: the markers it scaled from
48+ colorize_sfm.ply # sparse cloud coloured from the images
49+ mvs/
50+ convert_scene.mvs # the interface scene every MVS stage reads
51+ undistorted_images/
52+ densify.mvs densify.ply # --mvs-densify: scene + the dense cloud
53+ reconstruct_mesh.ply
54+ refine_mesh.ply # --mvs-refine (on by default)
55+ my-object.obj # the deliverable, + .mtl and texture image
56+ ```
57+
58+ ** Locate an artifact through the manifest, not by rebuilding its name.** Every
59+ stage records the paths it consumed and produced, relative to the output
60+ directory, and those records are what a resumed job reads — which is what lets
61+ these names change without invalidating a directory that already exists:
62+
63+ ``` shell
64+ jq -r ' .stages.texture.outputs.mesh' recon/pgs-recon.json # the textured mesh
65+ jq -r ' .stages.convert.inputs.sfm' recon/pgs-recon.json # the solved SfM it came from
66+ ```
67+
68+ Upgrading from 1.7, where the manifest was ` metadata.json ` and intermediates were
69+ named by chaining (` scene_dense_refine.ply ` )? Those directories are still read,
70+ but a 1.7 manifest carries no per-stage record, so a run against one rebuilds it
71+ from the start. See [ docs/migrating-to-1.8.md] ( docs/migrating-to-1.8.md ) .
72+
3173### Staged and resumable runs
32- The pipeline records what it has finished in ` <output>/metadata .json ` , so
74+ The pipeline records what it has finished in ` <output>/pgs-recon .json ` , so
3375** re-running the same command in the same output directory resumes it** rather
3476than starting over. After a crash or an out-of-memory kill during mesh
3577refinement, this picks up at ` refine ` :
@@ -75,19 +117,21 @@ mesh/refine/texture to a high-memory node, chained with `afterok`. Notes:
75117 re-refines and re-textures but touches nothing before it.
76118* Changing the shape is allowed at any point. Adding ` --mvs-densify ` to a
77119 finished reconstruction re-runs densify and the mesh stages, and dropping it
78- again re-runs them against the non-dense filenames.
120+ again re-runs them against the sparse cloud. Filenames stay put either way:
121+ an artifact is named for the stage that wrote it, not for the stages upstream
122+ of it.
79123* Stages before ` --from ` are never run implicitly: if one is incomplete or its
80124 inputs have moved, the run fails immediately, naming each, instead of quietly
81125 doing work the job was not sized for.
82126* If the range stops before stages the run invalidates, those stages are named
83127 in a warning and rebuilt by the next run that covers them. The final textured
84128 mesh keeps its usual ` mvs/<name>.obj ` filename in the meantime, so check the
85129 warning rather than the filename.
86- * What is on disk is never consulted — ` <output>/metadata .json ` is the record. If
87- you delete an intermediate by hand, use ` --rerun ` to rebuild it.
130+ * What is on disk is never consulted — ` <output>/pgs-recon .json ` is the record.
131+ If you delete an intermediate by hand, use ` --rerun ` to rebuild it.
88132* An argument aimed at a stage outside the range is ignored with a warning,
89- because it would change filenames the rest of the pipeline has already
90- committed to. Per-invocation settings are exempt and can differ freely between
133+ because it would change what the stages in range consume, and this run is not
134+ sized to rebuild them . Per-invocation settings are exempt and can differ freely between
91135 jobs: ` --path ` and ` --cam-db ` apply silently, and ` --threads ` , ` --log-level ` ,
92136 ` --config ` and ` --output ` are not recorded at all, so they never leak into a
93137 later job.
@@ -96,6 +140,30 @@ mesh/refine/texture to a high-memory node, chained with `afterok`. Notes:
96140* ` --no-mvs ` is deprecated: use ` --to colorize ` for an SfM-only run. The old flag
97141 still works (it sets ` --to colorize ` and warns) but will be removed.
98142
143+ ### When mesh refinement takes too long
144+ ` refine ` is the pipeline's slowest and hungriest stage, and it can run out of two
145+ different resources. Out of ** memory** is the familiar one, and resuming the same
146+ command picks up where the kill happened.
147+
148+ Out of ** wall clock** looks different: no progress in the log, one core pinned at
149+ 100%, and memory flat. That is mesh * preparation* rather than the optimization —
150+ before refining anything, ` RefineMesh ` subdivides the input mesh and remeshes the
151+ result with single-threaded CGAL, which is silent at the default verbosity and on
152+ a mesh of a few hundred thousand vertices can run for tens of minutes or more.
153+ Adding cores or memory does not help. Turning it off does:
154+
155+ ``` shell
156+ # Skip the remesh; refine everything else as before
157+ pgs-recon -o recon/ --from refine --refine-ensure-edge-size 0
158+
159+ # Or subdivide less aggressively, so preparation has less to remesh
160+ pgs-recon -o recon/ --from refine --refine-max-face-area 64
161+ ```
162+
163+ Both change the refined mesh, so they are options rather than defaults. If refine
164+ is not worth its cost on a given dataset, ` --no-mvs-refine ` drops it from the
165+ pipeline shape and textures the reconstructed mesh directly.
166+
99167### Docker images
100168We provide multi-architecture (x86, arm64) Docker images in the
101169[ GitHub Container Registry] ( https://github.com/educelab/pgs-recon/pkgs/container/pgs-recon ) .
@@ -154,7 +222,7 @@ transform. The input mesh must already be in the SfM coordinate frame.
154222``` shell
155223docker run -v .:/working ghcr.io/educelab/pgs-recon \
156224 pgs-sfm-orient \
157- -i /working/recon/sfm /sfm_data.bin \
225+ -i /working/recon/mvg/recon_dir /sfm_data.bin \
158226 --input-mesh /working/recon/mvs/my-object.obj \
159227 -o /working/recon/mvs/my-object-centered.obj \
160228 --save-transform /working/recon/orient.npy \
@@ -283,8 +351,8 @@ so a typo in any of them is unambiguous. The OpenMVG camera sensor database is
283351expected at ` <prefix>/lib/openMVG/sensor_width_camera_database.txt ` .
284352
285353Unlike most arguments, ` --path ` is deliberately * not* inherited from a previous
286- run's ` metadata.json ` when a staged run resumes (see ` --from ` /` --to ` above), so
287- each job of a split reconstruction picks up the prefix of the node it lands on.
354+ run's manifest when a staged run resumes (see ` --from ` /` --to ` above), so each job
355+ of a split reconstruction picks up the prefix of the node it lands on.
288356
289357### Advanced Installation
290358#### Installation Location
0 commit comments