Vuer

Depth Point Cloud -- Lidar Point Cloud from Depth Image

We can save 3D pointclouds effciently using Jpeg compression, by representing it as RGBA or grayscale images. In this example, we use a grayscale PNG image for depth. Note that PNG encoding and decoding can be 20 $\times$ slower than the FFT operations in a jpeg, so for visualization purposes, you can use jpeg for both color and depth.

Generate point clouds directly from depth images using the DepthPointCloud component.

Basic Example

python
import asyncio

from vuer import Vuer, VuerSession
from vuer.schemas import DepthPointCloud

vuer = Vuer(workspace="./rgb_depth", killport=True)


@vuer.spawn(start=True)
async def main(sess: VuerSession):
  sess.upsert @ DepthPointCloud(
    key="depth-point-cloud",
    depth=vuer.localhost_prefix / "depth.png",
    cmap="viridis",
    colorMode=4,
  )
  await asyncio.sleep(0.001)

  await sess.forever()

With Provider (Recommended for Multiple Point Clouds)

python
import asyncio

from vuer import Vuer, VuerSession
from vuer.schemas import DepthPointCloud, DepthPointCloudProvider

vuer = Vuer(workspace="./rgb_depth", killport=True)


@vuer.spawn(start=True)
async def main(sess: VuerSession):
  sess.upsert @ DepthPointCloudProvider(
    DepthPointCloud( key="pc-0", depth=vuer.localhost_prefix / "depth.png", position=[0, 0, 0] ),
    DepthPointCloud( key="pc-1", depth=vuer.localhost_prefix / "depth.png", position=[2, 0, 0] ),
    key="provider",
    frustumCulling=True,
  )

  await sess.forever()

DepthPointCloud Parameters

ParameterTypeDefaultDescription
depthstr(required)URL to 16-bit depth PNG image
rgbstrNoneURL to RGB image (uses depth grayscale if not provided)
positiontuple[0, 0, 0]Position in 3D space [x, y, z]
rotationtuple[0, 0, 0]Rotation in Euler angles [x, y, z]
scaletuple[1, 1, 1]Scale factors [x, y, z]
fovfloat58Vertical field of view in degrees (58 = RealSense D435)
pointSizefloat2.0Point size in pixels or world units
screenSpaceSizingboolTrueIf true, points have constant pixel size
cmapstrNoneColormap: "turbo", "viridis", "inferno", "jet", or None for RGB
colorModeint0Color mode (see table below)
depthMinfloat0.1Minimum depth for visualization mapping
depthMaxfloat50Maximum depth for visualization mapping
heightMinfloat-2Minimum height for visualization mapping
heightMaxfloat2Maximum height for visualization mapping
minYfloat-InfinityMinimum world Y for filtering - points below are discarded
maxYfloatInfinityMaximum world Y for filtering - points above are discarded
cxfloatwidth/2Principal point X in pixels (optical center X)
cyfloatheight/2Principal point Y in pixels (optical center Y)

Color Modes

ValueModeDescription
0depthColor by raw depth value
1camZColor by camera Z distance
2camDistColor by Euclidean distance from camera
3localYColor by local Y coordinate
4worldYColor by world Y coordinate (height)

Camera Intrinsics (cx/cy)

For cameras with off-center principal points (optical center), you can specify the cx and cy parameters to properly reconstruct the 3D point cloud. By default, they are centered at width/2 and height/2.

python
# Using camera intrinsics from calibration
sess.upsert @ DepthPointCloud(
    key="calibrated-pc",
    depth=vuer.localhost_prefix / "depth.png",
    rgb=vuer.localhost_prefix / "color.png",
    fov=58,           # Vertical FOV in degrees
    cx=320.5,         # Principal point X (pixels)
    cy=240.3,         # Principal point Y (pixels)
)

Common sources for camera intrinsics:

  • ROS camera_info: K[2] = cx, K[5] = cy
  • OpenCV calibration: cx, cy from the camera matrix
  • RealSense SDK: ppx, ppy from intrinsics

DepthPointCloudProvider Parameters

ParameterTypeDefaultDescription
frustumCullingboolTrueSkip rendering point clouds outside camera view
cullingMarginfloat2.0Margin multiplier for culling bounds
loddictNoneLevel-of-detail configuration with strides and distances
bakedictNoneBake configuration for depth processing
childrenlist[]Child DepthPointCloud elements