Equirectangular Perspective Extract
Point a virtual camera at your panorama and pull out a real-looking photo
- image
- perspective_image
This is the node that makes a 360° panorama feel like a camera again. Equirectangular Perspective Extract plants a pinhole camera somewhere inside your panorama, points it at whatever direction you choose, and renders what that camera would see as a normal, rectilinear photo - no fisheye, no stretching.
It's the difference between "here's a 360° image" and "here's a picture of the cafe's front door." You set yaw (look left/right), pitch (look up/down), roll (tilt), and FOV (how wide the lens is), and it extracts a clean perspective frame. This is the workhorse for taking one panorama and generating many flat views from it - a scene shot once, reframed a dozen ways for different crops, thumbnails, or img2img seeds.
How it works
The node simulates a pinhole camera. Each pixel of the output image maps to a ray out of the virtual camera, which is intersected with the sphere and converted to latitude/longitude, then sampled from the equirectangular source. The projection is done as an inverse remap - OpenCV cv2.remap with BORDER_WRAP on the CPU path, torch.grid_sample on the GPU path (bilinear/nearest only, same caveat as the Rotate node).
Because it's a true perspective projection, straight lines in the world come out straight in the frame - until the FOV gets wide, at which point rectilinear projection does its famous edge-stretching thing. That's not a bug; it's what a wide-angle rectilinear lens does, and knowing it means you know why an 80° FOV looks "natural" while a 160° one looks like a kaleidoscope.
Inputs that matter
image(required) - equirectangular tensor (B,H,W,C) in [0,1].yaw_rotation/pitch_rotation/roll_rotation- where the camera points and how it's banked, all in degrees. Default 0/0/0 looks at the front of the panorama, level.fov_degrees- horizontal field of view, default 90°, range 1–179°. Start at 90; go narrower for a "telephoto" feel, wider only if you accept the edge stretch.output_width/output_height(both default 1024) - the extracted frame's pixel size. This is your image-2-image staging area, so size it like you'd size a generation.interpolation(lanczos default) andbackend(auto/cpu/gpu) - the usual LatLong pair; GPU falls back to bilinear for non-bilinear/nearest requests.
Output is a single perspective_image.
Installing it
Standard pack install - Manager search "LatLong", or:
cd ComfyUI/custom_nodes
git clone https://github.com/cedarconnor/comfyui-LatLong
cd comfyui-LatLong
pip install -r requirements.txt
Restart ComfyUI. Node under LatLong. Deps: numpy, opencv-python, scipy, torch, Pillow; no model downloads.
Gotchas
The two things that catch people: FOV and pitch. Wide FOVs (above ~120°) produce heavy edge distortion that reads as "broken" if you didn't expect it - if your edges look bent, narrow the FOV before you blame the node. And remember the equirectangular has thin pixel density at the poles, so pointing the camera almost straight up or down gives you a soft, smeared image; keep the camera near the horizon band for crisp results. Extract a good frame, run it through img2img, and you've got a very controllable way to re-imagine specific parts of a 360° scene.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Equirectangular input image tensor (B,H,W,C) in [0,1]. | |
| yaw_rotationopt | FLOAT | 0.0-180–180 | Camera yaw (degrees). |
| pitch_rotationopt | FLOAT | 0.0-90–90 | Camera pitch (degrees). |
| roll_rotationopt | FLOAT | 0.0-180–180 | Camera roll (degrees). |
| fov_degreesopt | FLOAT | 90.01–179 | Horizontal field of view for the perspective camera (degrees). |
| output_widthopt | INT | 102432–8192 | Output width of the perspective view in pixels. |
| output_heightopt | INT | 102432–8192 | Output height of the perspective view in pixels. |
| interpolationopt | COMBO | lanczos | Resampling filter used during perspective remap. |
| backendopt | COMBO | auto | Processing backend. Auto uses GPU if available (bilinear/nearest). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| perspective_image | IMAGE | — |