Camera Intrinsics
The Camera Intrinsics node
- intrinsics
The Camera Intrinsics node does exactly one thing: it turns a camera's intrinsics matrix, pasted in as text, into a typed INTRINSICS value ComfyUI can route around a graph. It sounds almost too dumb to need a node - until you've got a K matrix printed in a paper, copied out of a calibration tool, or pasted straight from a PyTorch terminal and there's no typed slot on the graph to hold it.
Why this exists
Modern geometry models like Depth Anything V3 don't just hand you a depth map anymore. They also estimate the camera: where it was, which way it looked, and what its lens was doing - the so-called intrinsics (the 3×3 K matrix: focal lengths fx/fy in pixels and the principal point cx/cy) and extrinsics (the 4×4 position + orientation pose). Other packs in the same camera pipeline (like ComfyUI-CameraPack's DA3ToLoad3DCamera) want those values as typed tensors, and this node is the manual entry point: you have the numbers, you paste them in, you get a tensor out.
How it works
Under the hood it's almost embarrassingly simple, and that's the point. You type (or paste) the matrix into a multiline text box, the node runs ast.literal_eval to parse it as a Python literal, coerces it to a float32 numpy array, and checks it's really 3×3. Then it wraps it in a PyTorch tensor with a batch dimension so the rest of the graph sees a [1, 3, 3] tensor.
One genuinely handy detail: it tolerates tensor(...) pastes. If you copy an intrinsics matrix straight out of a PyTorch printout, the node strips the tensor( wrapper before parsing. Fewer "why is this a string" moments than you'd expect from a text-input node.
The one input and the output
There's a single required input, matrix (a multiline text field), and one output, intrinsics (INTRINSICS).
The only field you'll ever set is matrix. The default is a sane placeholder:
[[1000, 0, 960],
[1000, 0, 540],
[0, 0, 1]]
The author's own tooltip gives the format: [[fx, 0, cx], [0, fy, cy], [0, 0, 1]]. Remember fx/fy are focal length in pixels, not millimeters - for a real camera, fx = f_mm * width / sensor_width_mm. The 960/540 defaults are just a 1920×1080 principal point. If you're feeding this from a depth-model output you'll usually grab the model's numbers instead, but for a known, fixed camera (your phone, a calibrated rig) hardcoding the matrix and reusing it is a perfectly legit workflow.
Installing
This is part of ComfyUI-CameraPack by PozzettiAndrea. In ComfyUI Manager, search "CameraPack", install, and restart. Or, the manual way:
cd ComfyUI/custom_nodes
git clone https://github.com/PozzettiAndrea/ComfyUI-CameraPack.git
Then restart ComfyUI. The pack is pure Python - its declared dependencies (numpy, torch) are already part of ComfyUI, so there are no extra model downloads or heavy installs. The node shows up under the 3d/camera category.
Where it bites
If the node throws, it's almost always because the paste isn't a clean literal: stray text, trailing commas, or a tensor(...) paste that already has a [1, 3, 3] shape baked in. It handles the (1, 3, 3) case by stripping the leading batch dim, but a [N, 3, 3] with N > 1 will fail with a "Expected 3×3 matrix" error - that's what the batch-slicing nodes in this pack are for. Keep the paste clean and it just works.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| matrix | STRING | [[1000, 0, 960], [0, 1000, 540], [0, 0, 1]] | 3x3 intrinsics matrix [[fx, 0, cx], [0, fy, cy], [0, 0, 1]] |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| intrinsics | INTRINSICS | — |