Skip to main content
All case studies

Computer Vision · Real-Time Inference · Backend Engineering

Real-Time Hand-Sign Recognition Backend

A modular computer-vision backend that detects a hand through a webcam and classifies numerical signs from 1 to 10, stabilising per-frame predictions with a mode window.

Academic · Working prototype
Role
Software Engineer — computer vision and backend
Period
2025

Stages covered

  • Build
  • Operate

At a glance

2025

Landmarks per hand
21
Feature vector length
63
Smoothing window
10

Vision

  • OpenCV
  • MediaPipe Tasks Hand Landmarker

Model

  • scikit-learn
  • joblib

Service

  • Python 3.11
  • Flask

Overview

A Python backend that turns a webcam stream into a stable numeric prediction. MediaPipe's Hand Landmarker locates 21 landmarks on a single hand, those coordinates become a 63-value feature vector, a scikit-learn model classifies the sign, and a mode-based smoothing window converts noisy per-frame output into a prediction that is steady enough to act on. Both the raw and the stabilised prediction are exposed, so the consumer can choose responsiveness or reliability.

Landmarks per hand
21
Feature vector length
6321 landmarks × 3 coordinates
Smoothing window
10frames, mode-based

Problem

Per-frame classification of a live video stream is unusable straight out of the model. A hand in motion, a moment of partial occlusion, or a single blurred frame produces a prediction that flickers between neighbouring classes several times a second.

The recognition problem was largely solved by the landmark model. The engineering problem was turning a sequence of individually plausible guesses into one answer a consumer can act on.

Constraints

  • Must run at interactive frame rates on ordinary consumer hardware, with no GPU assumed
  • One hand only, which bounds the feature vector and keeps the model small
  • Ten classes, signs 1 through 10
  • Latency budget tight enough that the output still feels like a response to the user's gesture

Role and contribution

Software Engineer — computer vision and backend

  • Built the capture and detection pipeline on OpenCV and MediaPipe
  • Designed the landmark-to-feature-vector transformation
  • Trained and persisted the sign classifier
  • Implemented the mode-based smoothing window and the raw/stable output split
  • Structured the backend into replaceable modules per pipeline stage

System design

Architecture

Inference pipeline

A webcam frame is captured with OpenCV and passed to the MediaPipe Hand Landmarker, which returns 21 landmarks for a single detected hand. Those landmarks are flattened into a 63-value feature vector and classified by a scikit-learn model loaded from disk with joblib, producing a raw per-frame prediction. The raw prediction enters a 10-frame window whose mode becomes the stable prediction. The Flask API exposes both the raw and the stable value.

Vision
  • OpenCV
  • MediaPipe Tasks Hand Landmarker
Model
  • scikit-learn
  • joblib
Service
  • Python 3.11
  • Flask

From landmarks to features

The Hand Landmarker returns 21 points for a detected hand, each with three coordinates. Flattened, that is a fixed 63-value vector per frame — small enough for a classical model to classify in well under the frame budget, and stable enough in structure that no per-frame reshaping is needed.

Using landmarks rather than raw pixels is what makes the model this cheap. The expensive perception work is done by the landmarker; the classifier only has to separate ten shapes in a low-dimensional space.

Raw versus stabilised prediction

The raw prediction is the classifier's opinion about the current frame. It is immediate and it flickers. The stable prediction is the mode of the last ten raw predictions: a single frame of noise cannot move it, but a genuine change of sign moves it once the majority of the window agrees.

Both values are returned. A consumer that wants responsiveness — a live debug overlay, for example — can read the raw value; a consumer that will take an action reads the stable one. Choosing for the consumer would have been the wrong call, because the right trade-off depends on what the prediction is used for.

Modular structure

Each stage — capture, detection, feature extraction, classification, smoothing, API — is a separate module with a narrow interface. The practical benefit showed up during tuning: the smoothing window could be changed, and the classifier swapped, without touching capture or detection.

Known limitation: no wrist-relative normalisation

The current version feeds landmark coordinates to the classifier without first translating them relative to the wrist. The model therefore sees a sign made at the left of the frame as different from the same sign made at the right, and has to spend capacity learning that they are equivalent.

This is a real weakness, not a stylistic one: it makes accuracy depend on where the hand sits in frame and on distance from the camera. The fix is to translate all landmarks into a wrist-anchored frame of reference and scale by hand size before classification, which should improve generalisation without changing the pipeline's shape.

Key decisions and trade-offs

Decision

Stabilise output with a mode-based smoothing window

Context
Frame-by-frame classifications fluctuate, even when the hand is holding one sign.
Alternatives considered
  • Return every raw prediction directly
  • Require N identical consecutive frames before emitting a change
  • Average class probabilities across frames
Chosen approach
The mode of a rolling 10-frame window, exposed alongside the raw prediction.
Reason
The mode is robust to isolated outliers without demanding a run of perfect frames, and it needs no probability calibration from the classifier.
Trade-off
Output lags a genuine change of sign by roughly half a window. Exposing the raw value as well means a consumer that cannot afford that delay is not forced to accept it.
Outcome
Isolated misclassified frames no longer reach consumers of the stable prediction.

Decision

Classify landmarks rather than raw image pixels

Context
The alternative is a convolutional model trained on hand images.
Alternative considered
  • A CNN over cropped hand regions
Chosen approach
MediaPipe landmarks flattened into a 63-value vector, classified by a scikit-learn model.
Reason
Landmarks carry the geometry the task actually depends on and discard lighting, background and skin tone. The result runs at interactive rates on a CPU and trains on a small dataset.
Trade-off
Total dependence on the landmarker: if it fails to detect a hand, there is no fallback path to a prediction.

Result

  • A working real-time pipeline from webcam to stabilised prediction on ordinary CPU hardware
  • Per-frame flicker eliminated from the stable output without a perceptible loss of responsiveness
  • A modular backend where the model and the smoothing strategy can be replaced independently

Lessons learned

  • The model was the easy part. Making its output usable over time was the actual engineering.
  • Exposing both the raw and the smoothed value avoided guessing which trade-off the consumer needs.
  • Choosing a good intermediate representation — landmarks over pixels — bought more than any amount of model tuning would have.
  • Skipping wrist-relative normalisation was a shortcut that quietly costs accuracy; the fix belongs in the feature stage, not the model.

Next improvements

  • Translate landmarks relative to the wrist and scale by hand size before classification
  • Evaluate accuracy across hand positions and distances to quantify the current normalisation gap
  • Handle the no-hand-detected case as an explicit class rather than an absence of prediction
  • Extend beyond a single hand and beyond ten static signs