A fully containerized, three-service application that performs real-time hand gesture recognition using a MediaPipe + PyTorch machine-learning client, stores gesture events inside MongoDB, and visualizes them through a Flask-based web dashboard.
This project demonstrates how separate services communicate inside a Dockerized micro-service architecture.
The system consists of three Dockerized services:
+------------------------+ +-----------------------+ +------------------------+
| Machine Learning | | MongoDB | | Web App |
| Client | --> | handsense database | --> | Dashboard (Flask) |
| (MediaPipe + PyTorch) | | Gesture_events | | Visualize gestures |
+------------------------+ +-----------------------+ +------------------------+
Runs locally or inside Docker.
It uses a webcam β detects hands using MediaPipe β predicts gestures using a PyTorch MLP β inserts events into handsense.gesture_events collection.
Stores gesture logs, statistics, and capture state toggles.
Reads gesture events from MongoDB and presents a dashboard showing:
- Live latest gesture
- Gesture distribution
- Recent event timeline
- Toggle capture control (
/api/control)
After all services run, you can visit:
βββ docker-compose.yml
βββ instructions.md
βββ LICENSE
βββ machine-learning-client
β βββ data
β β βββ hagrid_keypoints_X.npy
β β βββ hagrid_keypoints_y.npy
β βββ Dockerfile
β βββ models
β β βββ gesture_mlp.pt
β β βββ train_mlp.py
β βββ Pipfile
β βββ Pipfile.lock
β βββ src
β β βββ __init__.py
β β βββ extract_keypoints_from_hagrid.py
β β βββ live_mediapipe_mlp.py
β βββ tests
β βββ __init__.py
β βββ test_extract_keypoints_from_hagrid.py
β βββ test_live_mediapipe_mlp.py
βββ README.md
βββ web-app
βββ app.py
βββ Dockerfile
βββ Pipfile
βββ Pipfile.lock
βββ readme.txt
βββ static
β βββ audios
β β βββ among_us.mp3
β β βββ android_beep.mp3
β β βββ bom.mp3
β β βββ error.mp3
β β βββ playme.mp3
β β βββ rick_roll.mp3
β β βββ rizz.mp3
β β βββ sponge_bob.mp3
β β βββ uwu.mp3
β βββ hagrid_classes.json
β βββ images
β β βββ fist.png
β β βββ like.png
β β βββ ok.png
β β βββ one.png
β β βββ palm.png
β β βββ stop.png
β β βββ thinking.png
β β βββ three.png
β β βββ two_up.png
β βββ script.js
β βββ style.css
βββ templates
β βββ index.html
βββ tests
βββ __init__.py
βββ conftest.py
βββ test_app.py
The recommended workflow uses pipenv for dependency management.
pip install pipenvFrom project root:
docker compose up --buildThis starts:
| Service | URL | Purpose |
|---|---|---|
| web-app | http://localhost:5000 | Dashboard UI |
| mongodb | localhost:27017 | Database |
| ml-client | headless, no UI | Captures gestures + inserts into DB |
To stop:
docker compose downSince macOS Docker cannot access /dev/video0, we run the ML client on host machine:
cd machine-learning-client
pipenv install --dev
pipenv run python src/live_mediapipe_mlp.pyFeatures:
- Live webcam feed
- MediaPipe hand-tracking
- PyTorch gesture inference
- Inserts gesture records into
handsense.gesture_events - Press
qto quit
The database name is:
handsense
Collections automatically created:
| Collection | Purpose |
|---|---|
| gesture_events | ML client inserts gesture data |
| controls | Stores capture toggle state |
At first run the ML client ensures:
{
"_id": "capture_control",
"enabled": false
}Both ml-client and web-app use these:
| Variable | Description |
|---|---|
| MONGO_URI | Mongo connection string (default: mongodb://mongodb:27017) |
| MONGO_DB_NAME | Database name (default: handsense) |
| SECRET_KEY | Flask sessions |
See .env.example below.
Place this file in project root:
# MongoDB configuration
MONGO_URI=mongodb://mongodb:27017
MONGO_DB_NAME=handsense
# Flask secret
SECRET_KEY=dev-secretThen create an actual .env:
cp .env.example .envcd web-app
pipenv install --dev
pipenv run flask run --host=0.0.0.0 --port=5000Navigate to:
| Route | Description |
|---|---|
/ |
Dashboard UI |
/api/latest |
Latest gesture |
/api/latest_full |
Latest gesture (detailed) |
/api/control |
POST toggle capture |
/api/control/status |
GET capture control |
cd machine-learning-client
pipenv run pytest --cov=src
pipenv run pylint srccd web-app
pipenv run pytest --cov=.
pipenv run pylint app.pyCoverage must be β₯ 80%.
version: "3.9"
services:
mongodb:
image: mongo:6
container_name: mongodb
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
web-app:
build:
context: ./web-app
container_name: web-app
depends_on:
- mongodb
environment:
MONGO_URI: "mongodb://mongodb:27017"
MONGO_DB_NAME: "handsense"
FLASK_APP: "app.py"
FLASK_RUN_HOST: "0.0.0.0"
ports:
- "5000:5000"
ml-client:
build:
context: ./machine-learning-client
container_name: ml-client
depends_on:
- mongodb
environment:
MONGO_URI: "mongodb://mongodb:27017"
MONGO_DB_NAME: "handsense"
volumes:
mongo-data: