Winter 2025/2026

Vote with your body, not a ballot.

A camera-based voting toolkit.

nuiVote logo

Natural User Interface Design

Natural User Interface

/ˈnætʃə˞ɹəl ˈjuzə˞ˈɪntə˞ ˌfeɪs/

Built for the university module “Natural User Interfaces”, nuiVote asks a simple question: what if casting a vote felt completely natural — no mouse, no keyboard, no ballot? The answer is a camera-based voting toolkit with four interchangeable interfaces. Stand in a zone, raise a hand gesture, hold up a coloured card, or simply change your expression — a single webcam reads the room while a web dashboard tallies every vote live.

View on GitHub
Python · MediaPipe · Next.js

Highlights

Several people standing across different zones of a room while a camera counts how many stand in each.
Your body is the ballot.
One question. Four ways to answer.
A person voting in front of a laptop webcam with empty hands — no phone, no clicker, no ballot in sight.
Nothing to install. Nothing to hold.
A group raising many hands toward a single camera, each hand individually detected and counted.
Up to thirty hands, counted at once.
A large auditorium of people voting by gesture, captured by one camera at the front of the room.
From a meeting room to a lecture hall.

Interfaces
Four ways to answer.
One natural vote.

Several people standing across three zones of a room while a webcam counts how many stand in each.

Spatial voting. Stand to be counted. A webcam divides the room into zones — Yes, Abstain, No — and MediaPipe's person detection tallies how many people stand in each. Your position in space is your vote, and the totals stream straight to a live chart.

A hand held up in a thumbs-up gesture in front of a webcam, recognised and counted as a vote.

Gesture voting. Raise a hand. MediaPipe reads 21 landmarks per hand to recognise Thumbs Up, Thumbs Down, Peace, Open Hand or Fist — up to thirty hands at once. An optional YOLOv8 stage pushes detection to room scale, and a built-in trainer lets you teach it brand-new gestures.

A person holding up a coloured paper card toward a webcam, detected by its colour as a vote.

Paper voting. Hold up a card. Pure OpenCV colour detection counts green, red and blue sheets straight from the HSV feed — no machine-learning model at all — with shape and skin-tone filtering so only real cards make the count.

A close-up of a face being analysed by a facial-landmark mesh that maps a smile to a vote.

Face voting. Just look. MediaPipe FaceMesh turns expression into intent — a smile counts as Yes, a frown as No, a neutral face as Abstain. It is the most effortless ballot of all, and asks nothing of your hands.

A web dashboard showing a live bar chart of votes with the active question displayed above it.

One live dashboard. A Next.js web app ties it together. Set a single question that appears as a banner on every camera feed, launch any interface, and watch votes climb in real time on a live chart — complete with vote history and a dark mode for the room.

Under the hood
Built like a product,
not a demo.

A diagram of a two-stage pipeline: a YOLO box around a person feeding into a MediaPipe hand-landmark detector.

Two-stage detection. For room-scale voting, YOLOv8 first spots people across the frame, then hands each region to MediaPipe for precise landmarks — distance accuracy on a frozen snapshot, while the live preview stays smooth.

A training screen capturing hand-landmark samples for a new custom gesture.

Teach it new gestures. A training mode captures hand-landmark samples — with handedness and a timestamp — into a portable JSON dataset, so the recogniser can grow well beyond its five built-in gestures.

A camera feed with the active vote question shown as a banner across the top.

One question, everywhere. A single shared JSON file holds the active question. The web app and every Python engine read it live and paint it as a banner over the camera feed, so the room always knows what it is answering.

The web dashboard rendering a vote chart from prepared demo data with no camera attached.

No camera? No problem. A static demo mode feeds the dashboard prepared results, so the whole flow — question, vote and live chart — can be shown without a webcam in the room.

A terminal running the pytest suites for each voting engine, all passing.

Built to be tested. Each engine is its own modular Python package with its own pytest suite and a clean programmatic API, exposing structured vote output that any external tool can read.