SHARP Ray-Distance -> Planar Depth
The unit conversion panorama pipelines need
- image
- intrinsics
- extrinsics
- image
- extrinsics
- intrinsics
This is a small node solving a real, easy-to-miss problem: depth maps aren't all measured the same way. Panorama/equirectangular depth uses "ray distance" - the straight-line distance from the camera to a point, measured along that specific pixel's viewing ray. SHARP's own depth predictions, and most planar monocular depth models (MoGe2, DA3, and friends), use "planar z" - depth measured along the optical axis, ignoring which pixel it is. Mix the two conventions without converting and you get plausible-looking but genuinely wrong geometry. SharpPredictGaussiansFromMetricDepth's own documentation puts a number on it: at a 90° face corner, the difference between the two conventions is roughly 73%. This node exists to convert between them before that becomes your problem.
How it works
It multiplies the incoming depth by a per-face cosine-map term derived straight from the camera intrinsics - 1 / sqrt(((u-cx)/fx)² + ((v-cy)/fy)² + 1), per the node's own description - which converts ray-distance depth into planar depth. It's smart about the intrinsics format going in, too: it auto-detects whether they're normalized (fx around 0.5 for a 90° FOV - a "PanoPack" style convention) or already in pixel space (fx in the hundreds - SHARP's own convention), and always emits pixel-K on the output, so everything downstream sees the same units regardless of what came in.
The inputs and outputs that matter
- image (required) - depth in ray-distance convention, e.g. straight out of a panorama-face split.
- intrinsics (required) - per-face camera intrinsics, either normalized or pixel-space; auto-detected.
- extrinsics (optional) - pure pass-through. It's not used in the actual math, since the conversion depends only on intrinsics.
Outputs: image (now in planar-z convention), extrinsics / intrinsics (pass-through, intrinsics guaranteed pixel-K).
Installing it
Manager: search "Sharp," install highest (nightly if that build is flaky). Or Install via Git URL: https://github.com/PozzettiAndrea/ComfyUI-Sharp.git. Manual: clone, pip install -r requirements.txt --upgrade, python install.py, restart.
Common issues
The failure mode this node prevents doesn't announce itself. If you feed ray-distance depth (say, cut out of an equirect panorama via ProjectDepthToPanorama) directly into SharpPredictGaussiansFromMetricDepth with its depth_convention still set to the default planar_z, you don't get an error - you get gaussians that are subtly warped toward or away from the camera, worst right at the edges of each panorama face where the geometric difference between the two conventions is largest. If your merged panorama gaussians look distorted specifically near face seams, this mismatch is the first thing to check: either route the depth through this node first, or flip depth_convention to ray_distance on the consuming node directly - functionally equivalent, but running it through this node makes the conversion explicit and reusable if you need that depth for more than one downstream node.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Per-face depth in ray-distance convention (e.g. the output of PanoramaSplit on a depth panorama). Shape [B, H, W, 3] or [B, H, W]. | |
| intrinsics | INTRINSICS | Per-face camera intrinsics. Accepts either normalized K (fx~=0.5 for 90° fov, PanoPack convention) or pixel K (fx in the hundreds, Sharp convention) — auto-detected. The output intrinsics socket emits pixel-K so all downstream consumers see the same units. | |
| extrinsicsopt | EXTRINSICS | Pass-through to the extrinsics output. Not used in the cos-map computation (purely intrinsic-dependent). |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| extrinsics | EXTRINSICS | — |
| intrinsics | INTRINSICS | — |