😺NKD fSpy Camera
Find the Camera That Took the Photo, From Two Pairs of Vanishing Lines
- image
- camera_info
- image
- fov_vertical
- focal_length_mm
- width
- height
A generated object floating on top of a photo instead of standing in it is usually a camera problem, not a model problem. If you want something added to a shot to share its perspective, you need the shot's lens. That's what fSpy Camera is for: you drag two pairs of vanishing lines over a photo and it solves the camera that took it. It's the fSpy workflow - the open-source camera-matching app and its Blender importer - brought inside ComfyUI so you never have to leave the graph to do it.
How it works
The 2-point vanishing-point solve is a classic. Each pair of lines you draw (along floorboards, table edges, a building's roofline) intersects at a vanishing point. Two vanishing points give you the focal length - the constraint is f² = -(Fu − P)·(Fv − P), the dot product of the two VP directions from the principal point - and the camera's orientation. The node carries the name as credit and implements the same solve; the package is GPL-3.0 like fSpy itself.
One honest limit: it solves orientation and FOV only. There's no absolute camera position, because fSpy can't know scene scale without a reference distance. The camera is placed at a nominal distance looking at the origin, which is all you need for matching perspective.
What you set and what you get
- image - the reference photo, from a Load Image node. It also passes through unchanged, so you don't need a second copy to feed downstream.
- fspy_state - the JSON of your line placements. You won't type this; you drag the vanishing lines on the node's viewport, and this widget just stores the result (which is how the state survives a workflow save).
Outputs are the useful part:
- camera_info (
LOAD3D_CAMERA) - wire this into NKD Preview 3D so your model sits in the photo's real perspective. - focal_length_mm - wire this into NKD Perspective Unwarp's Metric mode and the flattened aspect ratio comes out true instead of estimated.
- fov_vertical, plus width and height - handy scalars if anything else in your graph wants the lens numbers.
Install and troubleshooting
Same as the whole pack: ComfyUI Manager → search "NKD VFX Tools" → install → restart. No models to download.
Practical advice from the mechanism: pick lines that are actually parallel in the real world, and place each pair far enough apart that they intersect cleanly. Near-parallel lines make the solve fragile or fail outright, and if both vanishing points get assigned to the same axis the solve returns nothing - the third axis is derived from the two you pick. Don't expect a full 3D tracker out of this; it's a lens and an orientation, which is exactly the right tool for making added objects sit in the shot rather than on top of it.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Reference photo (e.g. from a Load Image node). Also passed through to Preview3D's bg_image. | |
| fspy_state | STRING | {"mode": "2point", "vp1": [[0.15, 0.35], [0.45, 0.3], [0.15, 0.65], [0.45, 0.7]], "vp2": [[0.55, 0.3], [0.85, 0.35], [0.55, 0.7], [0.85, 0.65]], "principalPoint": {"mode": "center"}, "vp1Axis": "x+", "vp2Axis": "z+", "origin": [0.5, 0.5], "distance": 5.0} | — |
Outputs (6)
| Name | Type | Description |
|---|---|---|
| camera_info | LOAD3D_CAMERA | — |
| image | IMAGE | — |
| fov_vertical | FLOAT | — |
| focal_length_mm | FLOAT | — |
| width | INT | — |
| height | INT | — |