Persp to ERP Warp
Turn one phone photo into an equirect canvas a pano model can finish
- image
- control_video
- control_mask
- inpaint_mask
- erp_guide
SplatKit starts from a 360° panorama, but most of us don't have one lying around - we have a phone photo. Persp to ERP Warp is the front end that bridges the gap (it's the "Image→pano" stage in workflow 0_generate_360_panorama-upscale.json): it takes a normal perspective photo and warps it onto an equirectangular (ERP) canvas, marking everything outside the photo's footprint as an inpainting mask. You then hand control_video + inpaint_mask to an image-to-pano generator (Krea 2 Turbo, or Qwen-Image-Edit with a 360 LoRA), it invents the rest of the sphere, and you have a panorama to feed the rest of SplatKit. So: this node makes your single 360° input instead of a 360° camera.
The warp itself is area-prefiltered - the source is heavily minified into its ERP footprint, so supersample (default 2) kills aliasing/moire before a bicubic warp, and you'd go 3–4 for very high-res sources. Placement is yaw_deg/pitch_deg (0 = forward/horizon). h_fov_deg matters most: match your camera (phone main ~70, wide ~90, ultrawide ~110–120), since vertical FOV follows from the image aspect. Keep width = 2 × height - the pano LoRA expects a 2:1 canvas.
Inputs and outputs that matter
Required: image, width/height (1440×720 default), length (frames in the still batch - 1 is a single ERP still, 5 gives the video model a little temporal extent), h_fov_deg.
The optional list has two worth knowing:
mask_feather(default 8 px) - softens the known/hole boundary so an inpainting sampler blends instead of leaving a hard seam.fill_color(default black) - tints the unknown region oncontrol_videoonly; the masks are unchanged so inpainting still regenerates it. If a model reacts badly to black init, try#808080mid-grey.
Outputs: control_video (the ERP canvas), control_mask (where the photo lands, for conditioning), inpaint_mask (a MASK for the unknown region - what an inpainting sampler actually uses), and erp_guide - a technical equirect reference chart (lat/lon grid, degree labels, floor/ceiling perspective curves, and a dotted FOV box showing exactly where your image sits) that you can feed a generator as a pure geometry hint for the 360 layout. Handy when the model keeps drawing walls at the wrong angle.
Install & gotchas
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, and this node needs no model downloads - the heavy MoGe/SphereSfM stuff only triggers when you reach the actual SplatKit stages. Two traps: a wrong h_fov_deg visibly warps the photo's perspective, and if your source was taken at a significant roll, straighten it before warping (workflow 0 includes a roll-180° seam fix on the output pano side for a reason). If you have no idea what your lens FOV is, run Estimate FOV first and wire its h_fov_deg in - that's exactly the pairing it was built for.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| width | INT | 144064–8192 | ERP canvas width. Keep 2:1 (width = 2*height) for the pano LoRA. |
| height | INT | 72032–4096 | — |
| length | INT | 51–257 | Frames in the still batch (N = 1+4k). 1 = single ERP still (fastest); 5 gives the video model a little temporal extent. |
| h_fov_deg | FLOAT | 9020–170 | HORIZONTAL field of view of the source photo, in degrees. Vertical FOV follows from the image aspect (square pixels). Match your camera: phone main ~70, wide ~90, ultrawide ~110-120. |
| yaw_degopt | FLOAT | 0-180–180 | Horizontal placement of the view center (0 = forward/center col). |
| pitch_degopt | FLOAT | 0-90–90 | Vertical placement of the view center (0 = horizon/mid row). |
| mask_featheropt | INT | 80–128 | Feather (px) on the inpaint_mask edge. Softens the known/hole boundary so an inpainting sampler blends instead of leaving a hard seam. 0 = hard edge. |
| supersampleopt | FLOAT | 2.01–4 | Anti-alias quality. The source is heavily minified into the ERP footprint; this area-prefilters it to footprint x this factor before a bicubic warp, killing aliasing/moire. 2 is a good default, 3-4 for very high-res sources, 1 = off (old bilinear-ish). |
| grid_spacing_degopt | INT | 105–90 | Lat/lon grid spacing (deg) on the 'erp_guide' chart. The guide is a TECHNICAL equirect reference (no photo): lat/lon grid + degree labels, floor/ceiling perspective curves, and a dotted FOV box marking exactly where the image sits. Feed it to a generator as a pure geometry hint for the 360 layout. |
| guide_opacityopt | FLOAT | 0.550–1 | 0 = draw only the lat/lon grid + FOV box; >0 = also draw the floor + ceiling perspective curves (how a ground/ceiling plane distorts into equirect). |
| fill_coloropt | STRING | #000000 | Colour of the UNKNOWN region on the ERP canvas (everything outside the photo's footprint). Hex '#RRGGBB' / '#RGB', or 'r,g,b' with 0-255 components. Default black. This only tints control_video -- the masks are unchanged, so an inpainting sampler still regenerates the region regardless. Handy when a model reacts badly to black init (try '#808080' mid-grey). |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| control_video | IMAGE | — |
| control_mask | IMAGE | — |
| inpaint_mask | MASK | — |
| erp_guide | IMAGE | — |