Henry Bao
Resume
Computer Vision · Human–Robot Interaction

Webcam Gesture
+ Pseudo-Depth

A real-time monocular hand interface that combines MediaPipe geometry, a custom gesture classifier, a safety-aware command interpreter, and a backend-agnostic Franka cube-stacking controller.

Robotics / Vision

July 2026

ML + robotics engineer

Python, OpenCV, MediaPipe, PyTorch, PyBullet

End-to-end prototype

Open-palm gesture detected by the webcam dashboard with landmark skeleton and pseudo-depth overlay
Live hand geometry and pseudo-depth dashboard RGB webcam · MediaPipe landmarks · relative depth visualization

A gesture demo is not yet a safe robot interface.

A standard webcam can recognize a hand, but it does not measure physical depth, custom gestures can flicker frame to frame, and directly mapping predictions to robot motion creates false activations and unsafe behavior.

Perception, intent, and control are separated.

The project converts webcam landmarks into invariant features, runs built-in and custom classifiers in parallel, debounces high-level commands through a safety state machine, and sends typed events into a simulator-independent robot backend.

One pipeline from pixels to a robot task.

The visual dashboard is only the front end. The core contribution is the interface between uncertain perception and deterministic robot control.

videocam

1. Webcam perception

OpenCV captures RGB frames; MediaPipe returns 21 hand landmarks, handedness, built-in gestures, and relative landmark z.

arrow_forward
gesture

2. Gesture inference

A canonical 63-D feature vector feeds an optional MLP for finger heart, pinch, OK sign, and unknown.

arrow_forward
health_and_safety

3. Safety interpreter

Confidence thresholds, debounce, cooldown, conflict resolution, and a latched emergency stop convert labels into typed commands.

arrow_forward
precision_manufacturing

4. Robot execution

The same cube-stacking state machine runs on a deterministic mock backend or a PyBullet Franka Panda.

The model sees pose, not screen position.

Wrist-centered

Subtract landmark 0 to remove translation in the image.

Palm-width scaled

Normalize by the distance from index MCP to pinky MCP for scale invariance.

Handedness canonicalized

Mirror left hands into a right-hand coordinate frame.

Relative z retained

Preserve MediaPipe geometry without presenting it as metric depth.

# 21 landmarks × (x, y, z) → 63-D vector
points = landmarks - landmarks[wrist]
scale = ||points[index_mcp] - points[pinky_mcp]||
points = points / max(scale, epsilon)

if handedness == "Left":
    points[:, 0] *= -1

features = points.astype(float32).reshape(63)
Closed-fist gesture detected in the real-time webcam dashboard
Closed-fist recognition at arm's lengthBuilt-in MediaPipe label remains visible beside custom-ML rejection

Strong offline recognition, reported with the right caveat.

The classifier was evaluated on session-disjoint samples. Public-data results are useful for engineering validation, but can be optimistic because classes came from different source datasets.

96.8%
0.939
812
0.899

Gestures become commands only after stability checks.

Emergency priority

Open palm triggers a deterministic, latched stop with a shorter confirmation window.

Debounce + cooldown

Normal commands must persist for several frames and cannot immediately re-fire.

Typed events

The robot receives structured emergency-stop, resume, reject, confirm, and gripper-toggle events—not raw strings.

The controller completes a nine-stage cube stack.

A deterministic state machine moves from home to source, grasp, lift, target placement, release, retreat, and done. The controller is independent of the physics backend, so tests run on a mock robot while the same interface drives a PyBullet Franka.

headless testsPyBullet GUIstop + resumereject + retry
Terminal output showing the Franka cube-stacking task progressing through motion stages and completing
Franka cube-stacking execution traceHOME → GRASP → LIFT → RELEASE → DONE

Honest pseudo-depth

The colored surface visualizes relative landmark geometry. A one-point palm-size calibration estimates range, but the project never claims an RGB webcam is LiDAR or ToF.

Graceful ML fallback

Missing, incompatible, or low-confidence custom checkpoints degrade to MediaPipe-only operation without crashing the camera loop.

Backend abstraction

Perception and task logic do not import the simulator. This keeps unit tests fast and makes a future real-robot adapter possible.

The prototype proves the complete interaction loop.

The next milestone is temporal control: swipe-based Cartesian nudges, push/pull depth commands, two-hand interaction, and validation on a single-camera labeled dataset to measure false activations under realistic domain shift.

Real-time monocular gesture and robot-control prototype