SphereSfM Add Camera Path (Dual-Res)
Fuse another trajectory into an 8K splat dataset
- pano_frames_1
- pano_frames_2
- pano_frames_3
- pano_frames_4
- model_dir
- num_images
- num_points
- num_added_frames
If you're on the dual-res track - SfM on low-res equirects, training images reprojected from 8K - then SphereSfM Add Camera Path (Dual-Res) is the incremental-add sibling of the plain Add Camera Path node. Same idea: grow an existing dataset with one more Camera Plot + WAN trajectory instead of rebuilding it. Same world-registration mechanism against the base run's _spheresfm_work/. The difference is that the new trajectory arrives with its own hi-res face source, and the node keeps the low-res pose solve and the 8K reprojection in lockstep the whole way.
Where the plain version takes a raw WAN equirect video, this one takes the proxy frames from a HiRes Composite - the low-res equirects SfM will pose - plus that same HiRes Composite's hires_manifest, which carries the exact list of 8K files for the trajectory. You don't point it at a folder; you wire the manifest. That's a cleaner contract than the base dual-res node's hires_dir folder (no count-mismatch guessing), at the cost of being tied to the HiRes Composite graph.
Inputs that matter
dataset_dir(required) - the existing dual-res dataset to grow. Same value the dual-res build node used asoutput_name.pano_frames_1(required) - the new trajectory'sproxy_framesfrom its HiRes Composite. Must be the same resolution as the proxies the base dataset was posed on, or the shared-camera assumption breaks.hires_1(required) - thehires_manifestfrom the same HiRes Composite feedingpano_frames_1.pano_frames_2/3/4andhires_2/3/4let you add up to four trajectories at once, concatenated in order.
Everything else mirrors the plain add node, with dual-res flavour:
frame_stride- stride here, not in a loader. It thins the proxies and the matching 8K files together, which is the only way the two stay aligned.matcher_type-exhaustive(default) matches the new frames against the existing ones, which is what lets a separate path link into the reconstruction.sequentialonly if the clip is a direct temporal continuation.adjust_existing_cameras- off (default) keeps existing poses fixed, purely additive. On lets a global solve refine them - and re-renders every cube face from 8K, so it's slow. You'll feel that one.retriangulate(default on) - the new images contribute 3D points; off registers poses only.face_size-0= COLMAP default off the rescaled 8K SPHERE camera. Set the same value the base build used so faces match.abs_pose_min_num_inliers(default 30) - lower it if the new frames won't register.cleanup_hires_source- off by default, and leave it off until you're done iterating on this dataset. On, it deletes the new trajectory's consumed 8K frames from the HiRes Composite'sframes/folder, but only once a same-size copy is confirmed staged in_spheresfm_work/equirect_hires. Note the hardlink caveat: ifframes/and the staging area are on the same volume, deleting reclaims the directory listing but ~no disk.
Outputs: model_dir, num_images, num_points, and num_added_frames - the last one is your "did it actually register" sanity check.
Install & gotchas
Pack-wide install as usual:
cd ComfyUI/custom_nodes
git clone https://github.com/mickmumpitz/ComfyUI-SplatKit
python_embeded\python.exe -m pip install -r ComfyUI-SplatKit/requirements.txt
Restart, let colmap_sphere.exe auto-download on first SfM run, and make sure the base dataset was built with mode=colmap_now (that's what leaves _spheresfm_work/ behind - a panorama_only build can't be extended).
The failure modes are the same as the plain add, just with one extra way to trip:
- The base dataset must exist and have
_spheresfm_work/- "dataset folder does not exist" means you built itpanorama_onlyor pointed at the wrong folder. - New frames won't register - the new path has to share view with the existing scene (start it near where earlier paths looked), keep
matcher_typeonexhaustive, and lowerabs_pose_min_num_inliersif needed. It still needs real parallax; a static pan registers nothing. - Resolution mismatch - if
pano_frames_1's proxies aren't the same resolution as the base dataset's, the shared-camera solve breaks. Match them before wiring.
And the same chainability and ordering rules apply: each successful add becomes the base model, so you can keep adding paths; run adds before upscaling the dataset; and keep adjust_existing_cameras off unless the new path genuinely reveals the base poses were off.
Inputs (22)
| Name | Type | Default | Description |
|---|---|---|---|
| dataset_dir | STRING | The EXISTING dual-res dataset to grow -- wire the Dataset Project node's dataset_dir (the same value the dual-res build node used as output_name). | |
| pano_frames_1 | IMAGE | The NEW trajectory's proxy_frames from its HiRes Composite. Must be the same resolution as the proxies the base dataset was posed on. | |
| hires_1 | STRING | hires_manifest from the SAME HiRes Composite feeding pano_frames_1 -- that trajectory's exact 8K file list. | |
| pano_frames_2opt | IMAGE | Optional second new trajectory; concatenated after pano_frames_1. | |
| pano_frames_3opt | IMAGE | Optional third new trajectory. | |
| pano_frames_4opt | IMAGE | Optional fourth new trajectory. | |
| hires_2opt | STRING | hires_manifest for pano_frames_2. | |
| hires_3opt | STRING | hires_manifest for pano_frames_3. | |
| hires_4opt | STRING | hires_manifest for pano_frames_4. | |
| frame_strideopt | INT | 11–100 | Use every Nth new frame. Stride HERE, not in a loader: this thins the proxies and the matching 8K files together. |
| max_framesopt | INT | 00–1000 | Cap NEW frames after stride (0 = no cap). |
| matcher_typeopt | COMBO | exhaustive | exhaustive (default) matches the new frames against the EXISTING ones too, which is what lets a separate path link into the reconstruction. Keep it unless the new clip is a direct temporal continuation of the last one. |
| adjust_existing_camerasopt | BOOLEAN | false | OFF (default): existing poses stay FIXED, only the new faces are written. ON: let a global solve refine them (re-renders EVERY cube face from 8K -- slow). |
| retriangulateopt | BOOLEAN | true | Run point_triangulator so the new images contribute 3D points. |
| face_sizeopt | INT | 00–8192 | Cube-face resolution (px). 0 = COLMAP default off the 8K SPHERE camera. Set the SAME value the base build used. |
| max_num_featuresopt | INT | 81921024–32768 | — |
| peak_thresholdopt | FLOAT | 0.00660–0.1 | — |
| edge_thresholdopt | FLOAT | 101–50 | — |
| max_num_matchesopt | INT | 327684096–131072 | — |
| abs_pose_min_num_inliersopt | INT | 3010–200 | Min verified inliers to register a new image. Lower if the new frames won't register; raise for stricter. |
| image_orderopt | COMBO | camera_major | 2 options: camera_major, frame_major |
| cleanup_hires_sourceopt | BOOLEAN | false | After the add, delete the NEW trajectory's consumed 8K frames from the HiRes Composite's frames/ folder -- but only once a same-size copy is confirmed staged in this dataset's _spheresfm_work/equirect_hires. OFF by default. Note: if frames/ and equirect_hires are on the same volume they are hardlinked, so this reclaims a directory listing but ~no disk; it frees real space only when they are separate copies. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| model_dir | STRING | — |
| num_images | INT | — |
| num_points | INT | — |
| num_added_frames | INT | — |