Perspective -> 180 Pano (No Black Fill)
Perspective still to 180° panorama, with edge-stretch instead of black holes
- images
- panorama_images
- mask
- info
You have a regular perspective photo or a flat frame and you want a square 180° panorama out of it - a half-sphere view for a VR180 player. The obvious approach projects the image onto a hemisphere, and the parts of the panorama the photo can't cover come out as black voids that you then have to outpaint. This node from the Muffins-Flat-2-Panoramic pack does that projection but refuses to bake the black in: pixels the source can't reach get edge-stretched from the nearest real pixel, so the panorama comes out filled everywhere. Black is the natural result of most naive implementations and it's exactly what makes the next outpainting step fight a hard void edge; this node skips that fight.
How it works
It's a straightforward perspective-to-180° projection. The node builds a grid of directions across a square output canvas - longitude spans ±90°, latitude ±90°, so the output is the front half-sphere - rotates it by roll and pitch, then shoots those directions through a pinhole camera model of your input. vfov sets the lens width; the effective focal length comes from your image height. Where a direction lands outside the input, sampling clamps to the edge pixel instead of black, which is the entire "NoBlack" in the name. A real ComfyUI MASK output still reports where the true holes are, so you can outpaint exactly the stretched regions if you want to replace the smeared edge-stretch with generated content.
Inputs you'll touch
vfov(default 60) - how wide the source lens is. Match it to your shot or the projection looks wrong.roll/pitch- level the horizon / point the view.pano_width/pano_height- the canvas size; note it forces a square output because it's a 180 hemisphere. Defaults to 2048×2048.auto_canvas/canvas_scale- instead of manual sizing, derive the output from input size × scale, rounded to a multiple of 64.tight_crop+crop_margin+crop_mode- the mask-shrinker. Withtight_cropon, it crops to the bounding box of the real content (plus a margin) so the stretched/hole area is smaller, thencrop_modedecides whether to resize back up (crop_and_resize, default) or keep the crop (crop_only).
Outputs: panorama_images, mask (white = areas that need filling), and info summarizing everything.
How it fits the pack
This is one of the pack's earlier perspective helpers - the "older generation" alongside Perspective2Panorama and its SmallMask sibling. The newer, more polished flow is Pano Outpaint Canvas → outpaint → apply panoramic / Convert To VR, which is what the author's published workflows use. But if your source is a perspective still rather than a fisheye, and you specifically want a square 180 canvas with edge-stretch fill, this node is the direct route and it's perfectly usable on its own. The output is batch-aware, so a stack of frames projects consistently.
Install
Same repo as all the Muffins nodes, and requirements.txt is just numpy - nothing heavy, no model downloads. ComfyUI Manager: search "Muffins-Flat-2-Panoramic-node". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/Ragamuffin20/Muffins-Flat-2-Panoramic-node.git
cd Muffins-Flat-2-Panoramic-node
python -m pip install -r requirements.txt
Restart ComfyUI. One honest caveat: edge-stretch is a great starting canvas and a lousy final look, so plan on an outpainting pass over the mask regions - that's precisely what the mask output is for.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| roll | FLOAT | 0.00-180–180 | — |
| pitch | FLOAT | 0.00-89.9–89.9 | — |
| vfov | FLOAT | 60.001–179 | — |
| auto_canvas | BOOLEAN | false | — |
| canvas_scale | FLOAT | 1.501–4 | — |
| pano_width | INT | 2048256–16384 | — |
| pano_height | INT | 2048256–16384 | — |
| tight_crop | BOOLEAN | true | — |
| crop_margin | FLOAT | 0.100–1 | — |
| crop_mode | COMBO | crop_and_resize | 2 options: crop_and_resize, crop_only |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| panorama_images | IMAGE | — |
| mask | MASK | — |
| info | STRING | — |