nvs2colmap 0.7.0__tar.gz → 0.7.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/PKG-INFO +10 -12
  2. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/README.md +9 -11
  3. nvs2colmap-0.7.3/nvs2colmap/SiggraphAsia2026VVC/README.md +379 -0
  4. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/SiggraphAsia2026VVC/__main__.py +15 -19
  5. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/SiggraphAsia2026VVC/cameras.py +22 -138
  6. nvs2colmap-0.7.3/nvs2colmap/SiggraphAsia2026VVC/link_frames.py +70 -0
  7. nvs2colmap-0.7.3/nvs2colmap/SiggraphAsia2026VVC/points.py +21 -0
  8. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/SiggraphAsia2026VVC/undistort.py +5 -9
  9. nvs2colmap-0.7.3/nvs2colmap/dynamic3dgs/README.md +196 -0
  10. nvs2colmap-0.7.3/nvs2colmap/n3dv/README.md +359 -0
  11. nvs2colmap-0.7.3/nvs2colmap/stnerf/README.md +228 -0
  12. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap.egg-info/PKG-INFO +10 -12
  13. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap.egg-info/SOURCES.txt +8 -0
  14. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/pyproject.toml +7 -1
  15. nvs2colmap-0.7.0/nvs2colmap/SiggraphAsia2026VVC/link_frames.py +0 -113
  16. nvs2colmap-0.7.0/nvs2colmap/SiggraphAsia2026VVC/points.py +0 -43
  17. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/LICENSE +0 -0
  18. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/__init__.py +0 -0
  19. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/blender/__main__.py +0 -0
  20. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/blender/preview_cameras.py +0 -0
  21. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/blender/render.py +0 -0
  22. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/blender/sample_cameras.py +0 -0
  23. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/colmap.py +0 -0
  24. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/dynamic3dgs/__main__.py +0 -0
  25. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/dynamic3dgs/camera_meta.py +0 -0
  26. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/dynamic3dgs/link_frames.py +0 -0
  27. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/dynamic3dgs/points.py +0 -0
  28. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/extract_videos.py +0 -0
  29. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/n3dv/__main__.py +0 -0
  30. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/n3dv/extract_videos.py +0 -0
  31. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/n3dv/poses_bounds.py +0 -0
  32. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/stnerf/__init__.py +0 -0
  33. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/stnerf/__main__.py +0 -0
  34. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/stnerf/extract.py +0 -0
  35. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/stnerf/pose.py +0 -0
  36. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/utils/__init__.py +0 -0
  37. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/utils/colmap.py +0 -0
  38. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/utils/ffmpeg.py +0 -0
  39. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/utils/rotation.py +0 -0
  40. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/write_model.py +0 -0
  41. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap/write_pcd.py +0 -0
  42. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap.egg-info/dependency_links.txt +0 -0
  43. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap.egg-info/entry_points.txt +0 -0
  44. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap.egg-info/requires.txt +0 -0
  45. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/nvs2colmap.egg-info/top_level.txt +0 -0
  46. {nvs2colmap-0.7.0 → nvs2colmap-0.7.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nvs2colmap
3
- Version: 0.7.0
3
+ Version: 0.7.3
4
4
  Summary: Utilities for converting novel view synthesis datasets to COLMAP format.
5
5
  Author-email: Howard Yin <yindaheng98@gmail.com>
6
6
  Maintainer-email: Howard Yin <yindaheng98@gmail.com>
@@ -94,16 +94,14 @@ Install COLMAP from conda-forge:
94
94
  conda install -c conda-forge colmap
95
95
  ```
96
96
 
97
- The `colmap` executable is installed into the conda environment. Activate
98
- that environment before a `--use-colmap` run. Activation puts `colmap` on
99
- `PATH` and loads the shared libraries the executable links against. A Python
100
- virtualenv such as `.venv` can be activated afterwards so its `python` stays
101
- first on `PATH`.
97
+ The `colmap` executable is `${CONDA_EXE%/bin/conda}/bin/colmap`. It loads
98
+ shared libraries from the conda `lib` directory next to that binary, so pass
99
+ this path to `--colmap-executable`.
102
100
 
103
101
  For Neural 3D Video scenes, pass `data/ffmpeg` and `data/ffprobe`, or put
104
102
  `ffmpeg` and `ffprobe` on `PATH`. To run the COLMAP reconstruction that
105
103
  [InstantSplat](https://github.com/yindaheng98/InstantSplat) continues from,
106
- pass `--colmap-executable colmap` after the conda environment is active.
104
+ pass `--colmap-executable "${CONDA_EXE%/bin/conda}/bin/colmap"`.
107
105
 
108
106
  Extract a Neural 3D Video scene and write per-frame COLMAP text models for
109
107
  [InstantSplat](https://github.com/yindaheng98/InstantSplat):
@@ -131,7 +129,6 @@ Run COLMAP reconstruction and undistortion for each frame, for
131
129
  [InstantSplat](https://github.com/yindaheng98/InstantSplat):
132
130
 
133
131
  ```bash
134
- conda activate
135
132
  python -m nvs2colmap.n3dv \
136
133
  --path data/Robo360/xarm6_gold_rope_in_basket_2 \
137
134
  --ffmpeg ffmpeg \
@@ -139,7 +136,7 @@ python -m nvs2colmap.n3dv \
139
136
  --video-extension MP4 \
140
137
  --n-frames 1 \
141
138
  --use-colmap \
142
- --colmap-executable colmap \
139
+ --colmap-executable "${CONDA_EXE%/bin/conda}/bin/colmap" \
143
140
  --colmap-use-gpu 1
144
141
  ```
145
142
 
@@ -164,7 +161,8 @@ python -m nvs2colmap.stnerf \
164
161
 
165
162
  Link a Siggraph Asia 2026 VVC scene and write per-frame COLMAP text models
166
163
  for [InstantSplat](https://github.com/yindaheng98/InstantSplat). The default
167
- starts at the first frame file, so `selfcap` `000900.jpg` is `frame901`:
164
+ starts at the first frame file and writes `frame1`, including a `selfcap`
165
+ scene whose first file is `000900.jpg`:
168
166
 
169
167
  ```bash
170
168
  python -m nvs2colmap.SiggraphAsia2026VVC \
@@ -215,8 +213,8 @@ in every extracted frame. `--use-colmap` writes images to `frame*/input` and
215
213
  masks to `frame*/input_mask`, then runs COLMAP undistortion into `images/` and
216
214
  `image_masks/` for
217
215
  [InstantSplat](https://github.com/yindaheng98/InstantSplat). The default
218
- starts at the first frame file. Source file `000000.jpg` is frame `1`, and
219
- `000900.jpg` is frame `901`.
216
+ starts at the first frame file and writes `frame1`. A scene whose first file
217
+ is `000900.jpg` still begins at `frame1`.
220
218
 
221
219
  For Blender scenes, rendering writes one video per camera beside
222
220
  `poses_bounds.npy`, plus `blender_frames.json` in that same directory. The
@@ -65,16 +65,14 @@ Install COLMAP from conda-forge:
65
65
  conda install -c conda-forge colmap
66
66
  ```
67
67
 
68
- The `colmap` executable is installed into the conda environment. Activate
69
- that environment before a `--use-colmap` run. Activation puts `colmap` on
70
- `PATH` and loads the shared libraries the executable links against. A Python
71
- virtualenv such as `.venv` can be activated afterwards so its `python` stays
72
- first on `PATH`.
68
+ The `colmap` executable is `${CONDA_EXE%/bin/conda}/bin/colmap`. It loads
69
+ shared libraries from the conda `lib` directory next to that binary, so pass
70
+ this path to `--colmap-executable`.
73
71
 
74
72
  For Neural 3D Video scenes, pass `data/ffmpeg` and `data/ffprobe`, or put
75
73
  `ffmpeg` and `ffprobe` on `PATH`. To run the COLMAP reconstruction that
76
74
  [InstantSplat](https://github.com/yindaheng98/InstantSplat) continues from,
77
- pass `--colmap-executable colmap` after the conda environment is active.
75
+ pass `--colmap-executable "${CONDA_EXE%/bin/conda}/bin/colmap"`.
78
76
 
79
77
  Extract a Neural 3D Video scene and write per-frame COLMAP text models for
80
78
  [InstantSplat](https://github.com/yindaheng98/InstantSplat):
@@ -102,7 +100,6 @@ Run COLMAP reconstruction and undistortion for each frame, for
102
100
  [InstantSplat](https://github.com/yindaheng98/InstantSplat):
103
101
 
104
102
  ```bash
105
- conda activate
106
103
  python -m nvs2colmap.n3dv \
107
104
  --path data/Robo360/xarm6_gold_rope_in_basket_2 \
108
105
  --ffmpeg ffmpeg \
@@ -110,7 +107,7 @@ python -m nvs2colmap.n3dv \
110
107
  --video-extension MP4 \
111
108
  --n-frames 1 \
112
109
  --use-colmap \
113
- --colmap-executable colmap \
110
+ --colmap-executable "${CONDA_EXE%/bin/conda}/bin/colmap" \
114
111
  --colmap-use-gpu 1
115
112
  ```
116
113
 
@@ -135,7 +132,8 @@ python -m nvs2colmap.stnerf \
135
132
 
136
133
  Link a Siggraph Asia 2026 VVC scene and write per-frame COLMAP text models
137
134
  for [InstantSplat](https://github.com/yindaheng98/InstantSplat). The default
138
- starts at the first frame file, so `selfcap` `000900.jpg` is `frame901`:
135
+ starts at the first frame file and writes `frame1`, including a `selfcap`
136
+ scene whose first file is `000900.jpg`:
139
137
 
140
138
  ```bash
141
139
  python -m nvs2colmap.SiggraphAsia2026VVC \
@@ -186,8 +184,8 @@ in every extracted frame. `--use-colmap` writes images to `frame*/input` and
186
184
  masks to `frame*/input_mask`, then runs COLMAP undistortion into `images/` and
187
185
  `image_masks/` for
188
186
  [InstantSplat](https://github.com/yindaheng98/InstantSplat). The default
189
- starts at the first frame file. Source file `000000.jpg` is frame `1`, and
190
- `000900.jpg` is frame `901`.
187
+ starts at the first frame file and writes `frame1`. A scene whose first file
188
+ is `000900.jpg` still begins at `frame1`.
191
189
 
192
190
  For Blender scenes, rendering writes one video per camera beside
193
191
  `poses_bounds.npy`, plus `blender_frames.json` in that same directory. The
@@ -0,0 +1,379 @@
1
+ # Siggraph Asia 2026 Volumetric Video Challenge
2
+
3
+ This package converts scenes from the **Siggraph Asia 2026 Volumetric Video
4
+ Challenge** into per-frame COLMAP outputs. By default it writes COLMAP text
5
+ models. Views whose distortion is zero are hardlinked. Views with a nonzero
6
+ `D_<view>` keep a hardlink of the original in `input/`. COLMAP's
7
+ `image_undistorter` writes `images/` and a `PINHOLE` model fitted to that
8
+ image. Included masks follow the images. With `--use-colmap`, it runs the full
9
+ COLMAP pipeline on every extracted frame.
10
+
11
+ ## Supported Datasets
12
+
13
+ - **Siggraph Asia 2026 VVC**: dataset
14
+ [zju3dv/SiggraphAsia2026VVC](https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC).
15
+ The public release contains the `siga` and `selfcap` tracks. The camera YAML
16
+ is the EasyVolCap layout used by the previous challenge release and by
17
+ [TrackerSplat's SIGA2025 loader](https://github.com/yindaheng98/TrackerSplat/blob/SIGA2025VVC/tools/parse_camera_SIGA2025VVC.py).
18
+
19
+ The dataset is gated and about 309 GB. Request access on the dataset page,
20
+ then log in with `hf auth login`.
21
+
22
+ Runtime dependencies:
23
+
24
+ ```bash
25
+ pip install numpy torch
26
+ pip install -U huggingface_hub
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ Each scene is one tar. `curl` pipes it into `tar`, so the archive is not stored.
32
+ The archive keeps its scene directory, so the files land at
33
+ `data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1.tar/004_1_seq1`.
34
+ `cp -al` then hardlinks every file into
35
+ `data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1`. Remove only that
36
+ directory, then hardlink again. That deletes generated frames and leaves the
37
+ extracted files in the `.tar` directory. `release_manifest.json` lists the
38
+ public views.
39
+
40
+ ```bash
41
+ mkdir -p \
42
+ data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1.tar \
43
+ data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1.tar \
44
+ data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1.tar \
45
+ data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1.tar \
46
+ data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1.tar \
47
+ data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0.tar \
48
+ data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0.tar \
49
+ data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0.tar \
50
+ data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0.tar \
51
+ data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0.tar \
52
+ data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0.tar \
53
+ data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0.tar \
54
+ data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0.tar \
55
+ data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0.tar \
56
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike.tar \
57
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi.tar \
58
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga.tar \
59
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike.tar \
60
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi.tar \
61
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga.tar
62
+ hf auth login
63
+ hf download zju3dv/SiggraphAsia2026VVC --type dataset --local-dir data/SiggraphAsia2026VVC --include "license.txt" --include "checksums.sha256" --include "release_manifest.json" --include "archive_manifest.json" --include "heldout_test_cameras/*"
64
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/test/004_1_seq1.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1.tar
65
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/test/006_1_seq1.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1.tar
66
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/test/007_0_seq1.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1.tar
67
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/test/008_2_seq1.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1.tar
68
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/test/011_0_seq1.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1.tar
69
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/val/001_1_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0.tar
70
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/compression/val/012_0_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0.tar
71
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/test/004_1_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0.tar
72
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/test/006_1_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0.tar
73
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/test/007_0_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0.tar
74
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/test/009_0_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0.tar
75
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/test/011_0_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0.tar
76
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/val/001_1_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0.tar
77
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/siga/sparse/val/012_0_seq0.tar | tar -xf - -C data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0.tar
78
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/selfcap/compression/test/0512_bike.tar | tar -xf - -C data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike.tar
79
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/selfcap/compression/test/0525_corgi.tar | tar -xf - -C data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi.tar
80
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/selfcap/compression/test/0811_yoga.tar | tar -xf - -C data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga.tar
81
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/selfcap/sparse/test/0512_bike.tar | tar -xf - -C data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike.tar
82
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/selfcap/sparse/test/0525_corgi.tar | tar -xf - -C data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi.tar
83
+ curl -fL -H "Authorization: Bearer $(hf auth token)" https://huggingface.co/datasets/zju3dv/SiggraphAsia2026VVC/resolve/main/selfcap/sparse/test/0811_yoga.tar | tar -xf - -C data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga.tar
84
+ ```
85
+
86
+ Each archive starts with the scene directory, for example `004_1_seq1/images/`.
87
+ `checksums.sha256` lists the uploaded archives; those tar files are not kept.
88
+
89
+ The held-out package is small and has camera YAML and no images.
90
+ `heldout_test_cameras/checksums.sha256` checks that archive. Extract it so
91
+ `test_intri.yml` and `test_extri.yml` land in each `.tar` scene directory.
92
+ List the archive first. The transforms drop a leading `SiggraphAisa2026VVC/`
93
+ prefix when it is present, and insert `.tar` before the scene directory, so
94
+ `004_1_seq1/test_intri.yml` lands at `004_1_seq1.tar/004_1_seq1/test_intri.yml`.
95
+
96
+ ```bash
97
+ tar -tf data/SiggraphAsia2026VVC/heldout_test_cameras/SiggraphAisa2026VVC_heldout_test_cameras.tar | head
98
+ tar -xf data/SiggraphAsia2026VVC/heldout_test_cameras/SiggraphAisa2026VVC_heldout_test_cameras.tar \
99
+ -C data/SiggraphAsia2026VVC \
100
+ --transform 's,^SiggraphAisa2026VVC/,,' \
101
+ --transform 's,\([^/]*\)/\([^/]*\)$,\1.tar/\1/\2,'
102
+ ```
103
+
104
+ Hardlink every extracted file into the scene directory passed to `--path`.
105
+ Remove only those scene directories first. The `.tar` directories stay.
106
+
107
+ ```bash
108
+ rm -rf \
109
+ data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1 \
110
+ data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1 \
111
+ data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1 \
112
+ data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1 \
113
+ data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1 \
114
+ data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0 \
115
+ data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0 \
116
+ data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0 \
117
+ data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0 \
118
+ data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0 \
119
+ data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0 \
120
+ data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0 \
121
+ data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0 \
122
+ data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0 \
123
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike \
124
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi \
125
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga \
126
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike \
127
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi \
128
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga
129
+ mkdir -p \
130
+ data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1 \
131
+ data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1 \
132
+ data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1 \
133
+ data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1 \
134
+ data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1 \
135
+ data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0 \
136
+ data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0 \
137
+ data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0 \
138
+ data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0 \
139
+ data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0 \
140
+ data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0 \
141
+ data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0 \
142
+ data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0 \
143
+ data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0 \
144
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike \
145
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi \
146
+ data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga \
147
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike \
148
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi \
149
+ data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga
150
+ cp -al data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1.tar/004_1_seq1/. data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1/
151
+ cp -al data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1.tar/006_1_seq1/. data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1/
152
+ cp -al data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1.tar/007_0_seq1/. data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1/
153
+ cp -al data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1.tar/008_2_seq1/. data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1/
154
+ cp -al data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1.tar/011_0_seq1/. data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1/
155
+ cp -al data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0.tar/001_1_seq0/. data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0/
156
+ cp -al data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0.tar/012_0_seq0/. data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0/
157
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0.tar/004_1_seq0/. data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0/
158
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0.tar/006_1_seq0/. data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0/
159
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0.tar/007_0_seq0/. data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0/
160
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0.tar/009_0_seq0/. data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0/
161
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0.tar/011_0_seq0/. data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0/
162
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0.tar/001_1_seq0/. data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0/
163
+ cp -al data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0.tar/012_0_seq0/. data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0/
164
+ cp -al data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike.tar/0512_bike/. data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike/
165
+ cp -al data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi.tar/0525_corgi/. data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi/
166
+ cp -al data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga.tar/0811_yoga/. data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga/
167
+ cp -al data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike.tar/0512_bike/. data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike/
168
+ cp -al data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi.tar/0525_corgi/. data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi/
169
+ cp -al data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga.tar/0811_yoga/. data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga/
170
+ ```
171
+
172
+ Link images and masks, then write COLMAP text models. The default run starts
173
+ at the first frame file and writes `frame1`. `siga` frames begin at
174
+ `000000.jpg`. `selfcap` releases `000900.jpg` through `001799.jpg`, and
175
+ `000900.jpg` is still `frame1`.
176
+
177
+ ```bash
178
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1
179
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/test/006_1_seq1
180
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/test/007_0_seq1
181
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/test/008_2_seq1
182
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/test/011_0_seq1
183
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0
184
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/compression/val/012_0_seq0
185
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/test/004_1_seq0
186
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/test/006_1_seq0
187
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/test/007_0_seq0
188
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/test/009_0_seq0
189
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/test/011_0_seq0
190
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/val/001_1_seq0
191
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/siga/sparse/val/012_0_seq0
192
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/selfcap/compression/test/0512_bike
193
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/selfcap/compression/test/0525_corgi
194
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/selfcap/compression/test/0811_yoga
195
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike
196
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/selfcap/sparse/test/0525_corgi
197
+ python -m nvs2colmap.SiggraphAsia2026VVC --path data/SiggraphAsia2026VVC/selfcap/sparse/test/0811_yoga
198
+ ```
199
+
200
+ ## Dataset Format
201
+
202
+ A scene folder contains one directory of frames per view, EasyVolCap camera
203
+ YAML, and optional masks and point clouds:
204
+
205
+ ```text
206
+ 004_1_seq1/
207
+ images/
208
+ 00/000000.jpg
209
+ 00/000001.jpg
210
+ 01/000000.jpg
211
+ ...
212
+ masks/
213
+ 00/000000.png
214
+ 00/000001.png
215
+ ...
216
+ train_intri.yml
217
+ train_extri.yml
218
+ test_intri.yml
219
+ test_extri.yml
220
+ intri.yml
221
+ extri.yml
222
+ t_offsets.json
223
+ pcds/
224
+ 000000.ply
225
+ ```
226
+
227
+ Frames are `.jpg`. Output folders count those files from `frame1`, so the
228
+ first file is `frame1` whether its name is `000000.jpg` or `000900.jpg`.
229
+
230
+ `train_intri.yml` and `train_extri.yml` are the training views.
231
+ `test_intri.yml` and `test_extri.yml` are the test views, and are read when
232
+ those files are present. A view without `images/<view>/` is left out. A view
233
+ listed in both YAML files keeps the training record. Views are sorted by name,
234
+ so `images/00/000000.jpg` becomes `00.jpg`.
235
+
236
+ Each YAML pair stores:
237
+
238
+ - `names`: view ids, such as `00` and `01`.
239
+ - `K_<view>`: 3 x 3 intrinsic matrix. `fx`, `fy`, `cx`, and `cy` are read from
240
+ it.
241
+ - `H_<view>`, `W_<view>`: image height and width.
242
+ - `R_<view>`: Rodrigues rotation of the world-to-camera pose.
243
+ - `T_<view>`: world-to-camera translation. The pose is already in the COLMAP
244
+ camera convention.
245
+ - `D_<view>`: OpenCV distortion coefficients `k1 k2 p1 p2 k3`. An all-zero
246
+ vector is left out. Any other value is written as COLMAP `OPENCV` using
247
+ `k1 k2 p1 p2`, and COLMAP undistorts `input/` into `images/`. The saved
248
+ camera is the resulting `PINHOLE` model.
249
+
250
+ `t_offsets.json` stores a per-view time offset. The converter leaves it out of
251
+ the COLMAP files. `pcds/000000.ply`, when present, is hardlinked to
252
+ `sparse/0/points3D.ply` in every extracted frame.
253
+
254
+ ## Output Format
255
+
256
+ In the default mode, each frame directory contains images, any masks, and a
257
+ COLMAP text model. Zero-distortion images and masks are hardlinks. A scene with
258
+ nonzero distortion also keeps the original files:
259
+
260
+ ```text
261
+ 0512_bike/
262
+ frame1/
263
+ input/
264
+ 0002.jpg
265
+ ...
266
+ images/
267
+ 0002.jpg
268
+ ...
269
+ input_mask/
270
+ 0002.jpg.png
271
+ ...
272
+ image_masks/
273
+ 0002.jpg.png
274
+ ...
275
+ sparse/0/
276
+ cameras.txt
277
+ images.txt
278
+ points3D.txt
279
+ points3D.ply
280
+ ```
281
+
282
+ `input/` is a hardlink of the source image. `images/` is the file written by
283
+ COLMAP's `image_undistorter`. A zero-distortion scene has no `input/` in the
284
+ default mode; its hardlinks are only in `images/` and `image_masks/`.
285
+ Mask filenames keep the image filename and add `.png`, so `images/0002.jpg`
286
+ pairs with `image_masks/0002.jpg.png`, and `input/0002.jpg` pairs with
287
+ `input_mask/0002.jpg.png`. A view with no `masks/<view>/` file gets an image
288
+ and no mask. When `pcds/` is missing, `points3D.ply` is omitted.
289
+ `--use-colmap` leaves the reconstructed points in `distorted/sparse/0` and
290
+ does not link `pcds/`.
291
+
292
+ With `--use-colmap`, images are linked into `frame*/input` and masks into
293
+ `frame*/input_mask` (`input/0002.jpg` pairs with `input_mask/0002.jpg.png`).
294
+ Each frame then runs feature extraction, matching, triangulation, mapping,
295
+ `image_undistorter`, and `mask_undistorter`. Undistorted images are written to
296
+ `images/`, and undistorted masks to `image_masks/`.
297
+
298
+ All generated camera models use `PINHOLE`. Every camera gets its own COLMAP
299
+ camera ID because these scenes are multi-view captures with known poses and
300
+ per-view intrinsics. IDs start at 1 in view-name order.
301
+
302
+ ## Usage
303
+
304
+ Link images and masks, then write COLMAP text models:
305
+
306
+ ```bash
307
+ python -m nvs2colmap.SiggraphAsia2026VVC \
308
+ --path data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1
309
+ ```
310
+
311
+ Start at source frame `000009.jpg` and keep output frame numbering aligned
312
+ with it:
313
+
314
+ ```bash
315
+ python -m nvs2colmap.SiggraphAsia2026VVC \
316
+ --path data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1 \
317
+ --start-number 10 \
318
+ --n-frames 20
319
+ ```
320
+
321
+ `selfcap` sparse scenes such as `0512_bike` have no `masks/` and no
322
+ `test_*.yml`. The released frames are `000900.jpg` through `001799.jpg`, and
323
+ the default command writes them as `frame1` through `frame900`:
324
+
325
+ ```bash
326
+ python -m nvs2colmap.SiggraphAsia2026VVC \
327
+ --path data/SiggraphAsia2026VVC/selfcap/sparse/test/0512_bike
328
+ ```
329
+
330
+ Extract only the training cameras:
331
+
332
+ ```bash
333
+ python -m nvs2colmap.SiggraphAsia2026VVC \
334
+ --path data/SiggraphAsia2026VVC/siga/compression/val/001_1_seq0 \
335
+ --no-test-camera
336
+ ```
337
+
338
+ Run the full COLMAP pipeline for each frame:
339
+
340
+ ```bash
341
+ python -m nvs2colmap.SiggraphAsia2026VVC \
342
+ --path data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1 \
343
+ --n-frames 1 \
344
+ --use-colmap \
345
+ --colmap-executable "${CONDA_EXE%/bin/conda}/bin/colmap" \
346
+ --colmap-use-gpu 1
347
+ ```
348
+
349
+ Reuse existing linked frame images:
350
+
351
+ ```bash
352
+ python -m nvs2colmap.SiggraphAsia2026VVC \
353
+ --path data/SiggraphAsia2026VVC/siga/compression/test/004_1_seq1 \
354
+ --skip-frame-linking
355
+ ```
356
+
357
+ ## Important Options
358
+
359
+ - `--path`: scene directory containing `images/`, `train_intri.yml`, and
360
+ `train_extri.yml`.
361
+ - `--n-frames`: number of frames to extract and write. If omitted, every frame
362
+ from `--start-number` through the last frame on disk is used. If omitted
363
+ with `--skip-frame-linking`, frame directories are counted from `frame%d`.
364
+ - `--no-train-camera`: skip cameras listed in `train_intri.yml` and
365
+ `train_extri.yml`.
366
+ - `--no-test-camera`: skip cameras listed in `test_intri.yml` and
367
+ `test_extri.yml`.
368
+ - `--start-number`: 1-based position in the frames on disk, default `1`.
369
+ Output `frame%d` uses that same count. The first file is `frame1`.
370
+ - `--skip-frame-linking`: keep existing frame images and masks, and skip
371
+ hardlinking and the distortion undistortion. A zero-distortion scene reuses
372
+ `frame*/images`, or `frame*/input` with `--use-colmap`. A scene with nonzero
373
+ distortion reuses `frame*/input` and the `images/` already written by COLMAP.
374
+ - `--use-colmap`: run the full COLMAP pipeline instead of only writing
375
+ `sparse/0` text models.
376
+ - `--colmap-executable`: path to the COLMAP executable. Nonzero distortion uses
377
+ it for `image_undistorter`, and `--use-colmap` uses it for the full pipeline.
378
+ - `--colmap-use-gpu`: whether COLMAP SIFT extraction and matching should use
379
+ GPU, default `1`.
@@ -9,7 +9,7 @@ from nvs2colmap.colmap import run_video_colmap
9
9
  from nvs2colmap.write_model import write_video_colmap_text_model
10
10
 
11
11
  from .cameras import read_camera_meta
12
- from .link_frames import count_frame_dirs, first_frame_number, link_frames, select_frame_indices
12
+ from .link_frames import count_frame_dirs, link_frames, select_frame_indices
13
13
  from .points import link_point_clouds
14
14
  from .undistort import undistort_frames
15
15
 
@@ -38,10 +38,8 @@ def parse_args() -> argparse.Namespace:
38
38
  parser.add_argument(
39
39
  "--start-number",
40
40
  type=int,
41
- help=(
42
- "1-based source frame to start from. Defaults to the first frame file. "
43
- "Source file 000000.jpg is frame 1, and 000900.jpg is frame 901."
44
- ),
41
+ default=1,
42
+ help="1-based position in the frames on disk. The first file is frame1.",
45
43
  )
46
44
  parser.add_argument(
47
45
  "--no-train-camera",
@@ -85,7 +83,7 @@ def parse_args() -> argparse.Namespace:
85
83
  parser.error("Cannot set both --no-train-camera and --no-test-camera.")
86
84
  if args.n_frames is not None and args.n_frames < 1:
87
85
  parser.error("--n-frames must be at least 1.")
88
- if args.start_number is not None and args.start_number < 1:
86
+ if args.start_number < 1:
89
87
  parser.error("--start-number must be at least 1.")
90
88
  return args
91
89
 
@@ -99,39 +97,37 @@ def main() -> None:
99
97
  include_train=not args.no_train_camera,
100
98
  include_test=not args.no_test_camera,
101
99
  )
102
- if args.skip_frame_linking:
103
- start_number = args.start_number or first_frame_number(folder)
104
- n_frames = args.n_frames
105
- if n_frames is None:
106
- n_frames = count_frame_dirs(folder / "frame%d", start_number=start_number)
107
- frame_indices = list(range(start_number - 1, start_number - 1 + n_frames))
108
- else:
109
- frame_indices = select_frame_indices(available_frames, args.start_number, args.n_frames)
100
+ start_number = args.start_number
101
+ n_frames = args.n_frames
102
+ if args.skip_frame_linking and n_frames is None:
103
+ n_frames = count_frame_dirs(folder / "frame%d", start_number=start_number)
104
+ frame_indices = select_frame_indices(available_frames, start_number, n_frames)
105
+ output_numbers = list(range(start_number, start_number + len(frame_indices)))
110
106
 
111
107
  frame_output_pattern = folder / "frame%d"
112
108
  distorted = any(camera.dist is not None for camera in cameras)
113
- image_dir_name = "input" if args.use_colmap else "images"
114
- mask_dir_name = "input_mask" if args.use_colmap else "image_masks"
109
+ image_dir_name = "input" if args.use_colmap or distorted else "images"
110
+ mask_dir_name = "input_mask" if args.use_colmap or distorted else "image_masks"
115
111
  if not args.skip_frame_linking:
116
112
  link_frames(
117
113
  folder=folder,
118
114
  frame_pattern=frame_output_pattern,
119
115
  cameras=cameras,
120
116
  frame_indices=frame_indices,
117
+ output_numbers=output_numbers,
121
118
  image_dirname=image_dir_name,
122
119
  mask_dirname=mask_dir_name,
123
120
  )
124
121
 
125
122
  colmap_cameras = [camera.camera for camera in cameras]
126
123
  n_frames = len(frame_indices)
127
- start_number = frame_indices[0] + 1
128
124
  if not args.use_colmap:
129
125
  if distorted:
130
126
  if not args.skip_frame_linking:
131
127
  undistort_frames(
132
128
  frame_pattern=frame_output_pattern,
133
129
  cameras=cameras,
134
- frame_indices=frame_indices,
130
+ output_numbers=output_numbers,
135
131
  colmap_executable=args.colmap_executable,
136
132
  )
137
133
  else:
@@ -145,7 +141,7 @@ def main() -> None:
145
141
  link_point_clouds(
146
142
  folder=folder,
147
143
  output_pattern=frame_output_pattern / "sparse" / "0" / "points3D.ply",
148
- frame_indices=frame_indices,
144
+ output_numbers=output_numbers,
149
145
  )
150
146
  else:
151
147
  run_video_colmap(