Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vitals — see your own heartbeat

A $0, laptop-only "reveal the invisible" art piece (part of the Unseen art project). Point the webcam at your face; it amplifies the otherwise-invisible color change of blood flowing under your skin so you watch your pulse, and shows a live BPM + waveform — all rendered on black. Pure Rust, real-time, from-scratch DSP.

Status (2026-06-06)

Part State How verified
Webcam capture (nokhwa/V4L2, warmup) working live: negotiates 1280x720@30, decodes RGB
3-thread pipeline (capture/process/render) working headless snapshot + live run, no drops
Temporal band-pass (4th-order biquad cascade) verified unit tests: passes in-band, rejects out-of-band
rPPG BPM estimator (FFT + band-pass prefilter) verified unit tests: recovers 50/72/88/132 BPM ±3, gates low-SNR
BPM gate (prominence) + EMA tracker verified unit tests: drowned pulse gated; tracker smooths/holds
EVM color magnification + skin gate verified unit tests: static=unchanged, in-band=amplified, skin mask
EVM motion magnification (DoG) verified unit tests: static=unchanged, in-band feature amplified
Mode toggle (color / motion) working live run, key M, both stages kept warm
Hybrid render: vignette + bloom + waveform + BPM working live run renders, no panic; bloom visible

11/11 unit tests pass (cargo test). The DSP + magnification cores are verified on synthetic signals. The visual effect itself needs a real lit face in frame — verify it per below.

Requirements

  • Linux — developed and tested on Pop!_OS; capture goes through V4L2 (/dev/video0) via nokhwa. nokhwa is cross-platform, so macOS/Windows may work, but they're untested.
  • A webcam, and a recent Rust toolchain (rustup).
  • Good, steady light on your face. rPPG reads a ~1% skin-color change; in a dark room there's nothing to amplify. Face a lamp/window; avoid flicker and big movements.

Build & run

git clone https://github.com/oneKn8/vitals && cd vitals
cargo run --release run        # the live window  (use --release for smooth 30fps)
cargo test                     # the DSP test suite
cargo run -- snapshot          # dev: dump one composited frame to snapshot.png (no window)
cargo run -- probe             # dev: dump one raw camera frame to probe.png

Controls (live window)

Key Action
M switch mode: PULSE (color flush) ↔ MOTION (amplified movement)
Up / Down (or + / -) amplification alpha up / down
Space freeze (stop adding magnification — compare to raw)
F toggle fullscreen
Esc / Q quit

Using it

  1. Run it, sit ~50cm away, face inside the faint "align face here" box, well lit.
  2. Hold still ~10s. The BPM locks once enough signal is buffered; the red waveform along the bottom is your live pulse signal.
  3. Nudge alpha up until the flush across your face is visible but not noisy (start ~40). Too high = blotchy noise; Space freezes it so you can compare against raw.

How it works

camera -> downscale+mirror -> magnify -> vignette + bloom on black. Two magnify modes, both fed every frame (so the toggle has no settling flash):

  • Color/PULSE: per-pixel temporal band-pass in the heart-rate band, amplified, gated by a YCbCr skin mask (only the face flushes), upsampled and added back.
  • MOTION: a Difference-of-Gaussians luminance band, temporally band-passed and amplified, exaggerating tiny movement.

In parallel, the mean green of a face ROI feeds an FFT-based rPPG estimator (zero-phase band-pass prefilter, Hann window, parabolic peak, prominence gate, EMA-smoothed) for a stable BPM + the waveform. Full design + rationale in DESIGN.md.

Deferred (genuine next steps, not blockers)

  • wgpu HDR bloom — current bloom is a CPU bright-pass + blur (LDR); true HDR additive bloom wants the wgpu render backend (macroquad is GLES/no-HDR). Render layer is isolated.
  • Face detection (rustface) to auto-place the ROI instead of the fixed center box.
  • Hardware AE/WB lock — blocked by a panic in v4l 0.14's control enumeration on this webcam; mitigated in software by the band-pass. Would need a raw VIDIOC_S_CTRL ioctl.

Privacy

Camera frames are processed in memory and never written to disk; only numeric features leave the frame. (probe/snapshot are dev-only and dump a PNG, which is git-ignored.)

License

MIT © 2026 Shifat Islam Santo

About

See your own heartbeat: real-time Eulerian video magnification + rPPG on a webcam, in Rust. Reveals the invisible color pulse of blood flow and amplifies micro-motion, on black.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages