Nodes/camera-comfyUI/OutpaintAnyProjection
ComfyUI Node

OutpaintAnyProjection

Outpainting in any view, then folding the result back into the world

By Alexankharin·Created about a year ago·Updated about a month ago· 36
OutpaintAnyProjection
  • image
  • mask
  • final_image
  • needs_inpaint_mask
input_projection
input_horiz_fov90.00
output_projection
output_horiz_fov180.00
output_width4096
output_height4096
patch_projection
patch_horiz_fov90.00
patch_res1024
patch_phi45.00
patch_theta0.00
prompt
num_inference_steps50
cachedfalse
guidance_scale30.00
mask_blur30
debugfalse

Ordinary outpainting works on flat images. This node works on projections. OutpaintAnyProjection takes an image in any of the pack's three projections (pinhole, fisheye, equirectangular), extracts a patch from any view direction you pick, runs Flux inpainting on that patch, and reprojects the filled result back into the original canvas - expanding the image where the camera "didn't see." It's the node that turns a 90° pinhole photo into a full 180° fisheye, or grows a 180° fisheye into a 360° panorama, with the geometry kept consistent the whole way.

That last bit is the whole point. If you outpaint a flat crop and stitch it, the perspective never lines up - a straight line in the source comes out bent in the extension. By doing the outpaint in a patch projection (default pinhole, 90° fov, aimed at patch_phi/patch_theta) and then reprojecting the patch back into the target projection, the generated content lands with the correct lens distortion for where it sits in the frame. The pack's Outpaint_fisheye180.json workflow chains five passes of this node to go 90° pinhole → full 180° fisheye, and sbs180_workflow.json uses it to synthesize the second eye of a VR180 stereo pair.

How it works

Step one: reproject the whole input onto the output canvas. Step two: rotate the view to the patch direction and extract a square patch plus its coverage mask. Step three: Flux-inpaint the masked (hole) region. Step four: reproject the inpainted patch back onto the canvas, compositing it only where the original had holes. Anything still uncovered after back-projection comes out on needs_inpaint_mask, so you can chain passes and keep iterating until the mask is empty.

The inputs that matter

  • input_projection / input_horiz_fov and output_projection / output_horiz_fov - the projection you're coming from and the one you're building. The fov is where people go wrong; it must match your actual source image.
  • output_width / output_height - default 4096². That's a big canvas; you can drop it for tests.
  • patch_phi / patch_theta - where in the world the patch is aimed. This is your camera-move control: sweep phi and each patch extends a different direction.
  • patch_res - patch resolution (default 1024); the outpaint's generation budget.
  • prompt - what to draw in the hole. As with all inpainting, describe the scene so the fill blends.
  • num_inference_steps (50), guidance_scale (30), mask_blur (30) - Flux inpainting settings.
  • cached - keep the Flux pipeline loaded between passes (or from a previous node); set true when chaining passes, false if VRAM is tight.
  • debug - set true and it skips inpainting, returning the raw patch so you can verify the view before spending minutes generating.

What comes out

final_image (the grown canvas) and needs_inpaint_mask (what's still hole). Both are useful: the mask is your "keep going" signal.

Installing it

This node is the poster child for the pack's automatic dependency setup. It needs ComfyUI-Flux-Inpainting, which install.py clones into custom_nodes/inpainting_flux (skipping if you already have that pack under any usual folder name), plus the Flux model weights - a multi-GB download. ComfyUI Manager → Custom Nodes Manager → camera-comfyUI → Install → restart; or clone and run python install.py. If the node errors with "FluxNF4Inpainting is not available," re-run install.py.

Common issues

  • Patch is mostly gray or garbage - check the patch first with debug; you're probably aiming patch_phi/patch_theta at a region with no source data.
  • Seams visible at patch edges - raise mask_blur (default 30) so the fill feathers into the source.
  • VRAM blowups on the default 4096² output - drop output resolution for iteration, then scale up for the final pass.
CategoryCamera/Outpainting

Inputs (19)

NameTypeDefaultDescription
imageIMAGE
input_projectionCOMBOsource projection
input_horiz_fovFLOAT90.000–360
output_projectionCOMBOfinal projection
output_horiz_fovFLOAT180.000–360
output_widthINT40961–8192
output_heightINT40961–8192
patch_projectionCOMBOpatch projection
patch_horiz_fovFLOAT90.001–180
patch_resINT10241–8192
patch_phiFLOAT45.00-180–180
patch_thetaFLOAT0.00-90–90
promptSTRING
num_inference_stepsINT5010–60
cachedBOOLEANfalse
guidance_scaleFLOAT30.000.1–30
mask_blurINT300–512
maskoptMASK
debugoptBOOLEANfalseIf true, skip inpainting and output patch

Outputs (2)

NameTypeDescription
final_imageIMAGE
needs_inpaint_maskMASK