Build point clouds from depth maps with correct intrinsics handling and export to .ply. Use when you need help with skill depth to pointcloud.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill skill-depth-to-pointcloud --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Skill Depth To Pointcloud?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-skill-depth-to-pointcloud)More formats (shields.io, HTML) on the badges page.
---
name: skill-depth-to-pointcloud
description: Build point clouds from depth maps with correct intrinsics handling and export to .ply. Use when you need help with skill depth to pointcloud.
license: CC-BY-NC-SA-4.0
phase: 4
lesson: 26
metadata:
version: 1.0.0
tags: [depth, point-cloud, 3d, intrinsics]
---
# Depth to Point Cloud
Turn a depth map plus a colour image into a textured point cloud, exportable for visualisation or further 3D work.
## When to use
- Visualising depth predictions as an actual 3D scene.
- Bootstrapping a sparse 3D reconstruction from a single image.
- Producing input for 3DGS training when SfM fails.
- Comparing predicted depth against LiDAR ground truth.
## Inputs
- `depth`: `(H, W)` numpy array of depths in the same units you want in the output (metres recommended).
- `rgb`: `(H, W, 3)` numpy array of colours (uint8 or float32 [0, 1]).
- `intrinsics`: `(fx, fy, cx, cy)` in pixel units.
- Optional `depth_scale`: multiplier to convert predicted depth units to metres.
## Pipeline
1. **Validate** — depth must be positive and finite everywhere you plan to include. Mask out invalid pixels.
2. **Lift** — `X = (u - cx) * d / fx`, `Y = (v - cy) * d / fy`, `Z = d` per pixel.
3. **Pair** with RGB — each 3D point gets an `(r, g, b)` triple from the matching pixel.
4. **Export** — PLY (portable), `.xyz` (lightweight), `.pcd` (Open3D-native), `.las`/`.laz` (geospatial).
## Implementation template
```python
import numpy as np
def depth_to_point_cloud(depth, intrinsics, depth_scale=1.0, min_depth=0.1, max_depth=100.0):
H, W = depth.shape
fx, fy, cx, cy = intrinsics
v, u = np.meshgrid(np.arange(H), np.arange(W), indexing="ij")
z = depth.astype(np.float32) * depth_scale
valid = (z > min_depth) & (z < max_depth) & np.isfinite(z)
x = (u - cx) * z / fx
y = (v - cy) * z / fy
points = np.stack([x, y, z], axis=-1)
return points, valid
def write_ply(path, points, colors=None, valid_mask=None):
p = points.reshape(-1, 3)
if valid_mask is not None:
p = p[valid_mask.flatten()]
lines = [
"ply",
"format ascii 1.0",
f"element vertex {p.shape[0]}",
"property float x", "property float y", "property float z",
]
if colors is not None:
c = colors.reshape(-1, 3).astype(np.uint8)
if valid_mask is not None:
c = c[valid_mask.flatten()]
lines += ["property uchar red", "property uchar green", "property uchar blue"]
lines.append("end_header")
with open(path, "w") as f:
f.write("\n".join(lines) + "\n")
if colors is not None:
for pt, col in zip(p, c):
f.write(f"{pt[0]:.4f} {pt[1]:.4f} {pt[2]:.4f} {col[0]} {col[1]} {col[2]}\n")
else:
for pt in p:
f.write(f"{pt[0]:.4f} {pt[1]:.4f} {pt[2]:.4f}\n")
```
## Report
```
[export]
input depth shape: (H, W)
valid points: <N> of <H*W>
output format: ply | xyz | pcd | las
coordinate system: camera (+X right, +Y down, +Z forward)
scale: metres | millimetres | normalised
```
## Rules
- Always mask invalid depth (zero, NaN, inf, saturated); including them produces a cloud of garbage points at the origin.
- For prediction from a relative-depth model, do NOT export as metric; prefix output filename with `relative_` to signal the convention.
- Keep the camera coordinate convention consistent (OpenCV: +X right, +Y down, +Z forward). Swap signs if the downstream tool expects OpenGL (+Y up).
- For dense scenes (> 1M points), offer a subsample parameter; PLY files > 500 MB are awkward to load everywhere.
- Never silently clip depth to produce "reasonable" output; clip explicitly with warned thresholds so users know what was discarded.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!