Nodes/ComfyUI-SplatKit/SphereSfM Add Camera Path
ComfyUI Node

SphereSfM Add Camera Path

Grow a splat dataset instead of rebuilding it — add a camera path to what you've got

By mickmumpitz·Created about a month ago·Updated a day ago· 17
SphereSfM Add Camera Path
  • pano_frames_1
  • pano_frames_2
  • pano_frames_3
  • pano_frames_4
  • model_dir
  • num_images
  • num_points
  • num_added_frames
dataset_dir
frame_stride1
max_frames0
matcher_typeexhaustive
adjust_existing_camerasfalse
retriangulatetrue
face_size0
max_num_features8192
peak_threshold0.0066
edge_threshold10
max_num_matches32768
abs_pose_min_num_inliers30
image_ordercamera_major

You built a scene with SphereSfM Dataset, trained it, and now you want to fly through a room the original camera path never touched. The obvious move - re-run the whole pipeline from scratch - is also the wasteful one: feature extraction, matching, and spherical bundle adjustment are all expensive, and you'd redo every frame you already solved. SphereSfM Add Camera Path exists so you don't. It takes one more WAN pano trajectory (a single Camera Plot + WAN group) and registers it into the dataset you already built, growing images/ and the sparse reconstruction instead of starting over.

This is incremental SfM, and it's genuinely handy - you can keep flying the camera through new corners of a scene and each run folds the new views into the same reconstruction. It's also chainable: every successful add is promoted to the base model, so you can add a second, third, fourth path by running this node again against the same dataset.

How it works

The base build leaves behind _spheresfm_work/ - the equirect frames, the feature database.db, and the SPHERE model. This node reuses all of it, so the new frames are solved in the same world as the originals:

  1. New equirect frames are appended to _spheresfm_work/equirect (numbering continues).
  2. feature_extractor runs on the new frames only (their own SPHERE camera, same database).
  3. A matcher runs - exhaustive by default, because the new clip is a separate trajectory and has to be matched against the existing frames, not just its own neighbors.
  4. image_registrator pins the new images against the existing 3D points, point_triangulator adds new points, and sphere_cubic_reprojecer writes the new cube faces into images/, replacing sparse/0 with the extended model.

Inputs that matter

  • dataset_dir (required) - the existing dataset. Wire the Dataset Project node's dataset_dir here, or type the folder. It must contain _spheresfm_work/ from a mode=colmap_now build; panorama_only datasets can't be extended.
  • pano_frames_1 - the new WAN equirect video. "Optional" in the schema, required in practice. pano_frames_2/3/4 concatenate more trajectories.
  • adjust_existing_cameras - off (default) keeps existing poses bit-stable; purely additive, only new faces are written. On lets a global solve nudge the old poses to fit the new data - and re-renders every cube face, so only flip it if the new path reveals the base was slightly off.
  • matcher_type - keep exhaustive unless the new clip is a direct temporal continuation of the last one.
  • retriangulate (default on) - run the triangulator so new images contribute 3D points; off is faster and sparser.
  • abs_pose_min_num_inliers - min verified inliers to register a new image (default 30). Lower it if new frames won't register; raise it to be stricter.
  • face_size - set the same value the base dataset used so the new faces match the existing ones (0 = auto).

Outputs: model_dir, num_images, num_points, and num_added_frames so you can confirm the add actually registered something.

Install

Same pack-wide install as the base node:

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 ComfyUI. The colmap_sphere.exe binary auto-downloads on first SfM run (SHA-256 verified, NVIDIA Turing+ for GPU matching, CPU fallback otherwise). Ready-made graph: workflows/1b_camera_plot_add_to_dataset.json.

Common issues

  • "dataset folder does not exist" - you built it with mode=panorama_only, or pointed at the wrong folder. It needs a colmap_now build with _spheresfm_work/.
  • New frames won't register - the new path must share view with the existing scene (start it near where earlier paths looked) so SfM can match features across them, and it still needs real movement/parallax. Lower abs_pose_min_num_inliers, double-check matcher_type is exhaustive, and make sure the new clip actually overlaps the old views.
  • Run it before upscaling the dataset, and keep adjust_existing_cameras off unless you have a reason - the purely additive default is what keeps your already-working reconstruction untouched.

One more thing: running this node deletes the base run's solve fingerprint, so a later reuse_solve on the base node re-solves rather than inheriting the extended model. That's intentional - the solve on disk is no longer the base run's.

CategorySplatKit

Inputs (17)

NameTypeDefaultDescription
dataset_dirSTRINGThe EXISTING SphereSfM dataset to add to -- wire the Dataset Project node's dataset_dir here (the same value the base SphereSfM node used as output_name), or type the dataset folder name/path. Must contain _spheresfm_work/ from a mode=colmap_now build.
pano_frames_1optIMAGEThe new WAN equirect pano video (one Camera Plot + WAN group) to add to the dataset. Required in practice.
pano_frames_2optIMAGEOptional extra new trajectory; concatenated after pano_frames_1.
pano_frames_3optIMAGEOptional third new trajectory.
pano_frames_4optIMAGEOptional fourth new trajectory.
frame_strideoptINT11–100Use every Nth new frame. Thin long clips but keep matching overlap.
max_framesoptINT00–1000Cap NEW frames after stride (0 = no cap).
matcher_typeoptCOMBOexhaustiveHow to match the new frames. exhaustive (default) matches them against the EXISTING frames too, which is what lets a separate path link into the reconstruction -- keep this unless the new clip is a direct temporal continuation of the last one.
adjust_existing_camerasoptBOOLEANfalseOFF (default): keep the existing cameras/poses FIXED -- purely additive, original views stay bit-stable, only new faces written. ON: let a global solve refine existing poses to fit the new data (re-renders EVERY cube face; use only if the new path reveals the base was slightly off).
retriangulateoptBOOLEANtrueRun point_triangulator after registration so the newly added images contribute 3D points (denser cloud in the added region). Off = register poses only (faster, sparser).
face_sizeoptINT00–2048Cube-face resolution (px). 0 = auto (~equirect_w/4). Set the SAME value the base dataset used so new faces match the existing ones.
max_num_featuresoptINT81921024–32768
peak_thresholdoptFLOAT0.00660–0.1
edge_thresholdoptFLOAT101–50
max_num_matchesoptINT327684096–131072
abs_pose_min_num_inliersoptINT3010–200Min verified inliers to register a new image against the existing 3D points. Lower if new frames won't register; raise for stricter.
image_orderoptCOMBOcamera_majorOrder recorded in the dataset marker for upscaling (COLMAP files untouched). camera_major groups each cube face into a coherent per-view sub-video across ALL trajectories; frame_major keeps plain lexical order.

Outputs (4)

NameTypeDescription
model_dirSTRING
num_imagesINT
num_pointsINT
num_added_framesINT