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: