📄 README.md

kinect-view

A virtual camera synthesized live from a fixed three-camera rig.

kinect-view captures a Microsoft Kinect v2 (RGB + depth) flanked by two webcams, and every frame turns the depth measurements directly into a Gaussian-splat scene — flat, footprint-sized surface splats colored from the cameras, with no training or optimization pass. A WebGPU splat renderer then draws that scene from a virtual camera positioned anywhere between the physical cameras, producing a view that no single real camera could take.

Parts of the subject the cameras cannot see (such as the far side of the face) are covered by a head-and-shoulders ellipsoid fitted per frame and recolored from the side cameras.

The rendered output is delivered as:

  • an egui window for viewing the virtual-camera image and steering the virtual camera interactively
  • a virtual webcam on Linux (via v4l2loopback) that tools such as Teams or Slack pick up as an ordinary camera

Targets Ubuntu 24.04 (x86-64) and Windows on ARM64.

Status

Build-order steps 1–2 are complete. The full pipeline runs on synthetic data through the real depth path: a software Kinect emits raw millimetre depth maps plus RGB (with deterministic sensor noise), and splatgen culls the background, removes fliers, bilateral-filters the depth, estimates normals, and assembles footprint-sized surfel splats — which Brush renders live from a virtual camera steered between the rig's side cameras, shown in the egui viewer. The whole chain, GPU rendering included, runs headlessly in tests (software Vulkan), noise included.

Recorded datasets have an on-disk format (replay::recording): a directory with recording.toml (camera, fps, frame count) plus raw frame_NNNN.depth/frame_NNNN.rgb files. Real Kinect recordings can be converted into that shape; synthetic ones are generated for dev/CI.

  • cargo run -p sink — the viewer (needs a GPU, or lavapipe/Vulkan)
  • cargo test --workspace — unit, GPU-integration, and headless UI tests

Configuration

Everything is configurable three ways — CLI arguments, environment variables (KINECT_VIEW_*), and a TOML file — with later layers winning: CLI > environment > file > defaults. Every setting exists in all three.

kinect-view --rig-left-position=-0.6,0,0 --source-fps 24
KINECT_VIEW_RIG_RIGHT_POSITION=0.6,0,0 kinect-view
kinect-view --config-file rig.toml
# rig.toml — each camera has an identifier, position, rotation,
# resolution, and intrinsics.
rig_left_id = "left-cam"
rig_left_position = [-0.6, 0.0, 0.0]
rig_left_look_at = [0.0, 0.0, 2.0] # or rotation_deg / rotation_quat
rig_left_resolution = [640, 480]
rig_left_intrinsics = [554.256, 415.692, 320.0, 240.0]

scene_subject_position = [0.0, 0.0, 2.0]
source_fps = 30.0
background = [0.10, 0.10, 0.12]

kinect-view --help lists every setting with its environment variable.

Workspace layout

Crate Role
rig Shared types: camera poses and intrinsics, the virtual camera, splat batches, frame sources
capture Kinect v2 RGB + depth (kinect-one) and two webcams (nokhwa), timestamp frame sync
replay Recorded / synthetic rig datasets, so development and CI run without hardware
splatgen Depth filtering, normals, footprint-sized surfel splats, ellipsoid-proxy fill
render Brush renderer integration (WebGPU/Burn) and the virtual camera
sink egui viewer/steering UI and the v4l2loopback virtual webcam (Linux)

See PLAN.md for the full plan.