Portfolio
Emotion·Cam runs entirely in your browser · work in progress
FER-2013 test acc 🔒 0 bytes uploaded Source ↗
Under construction. The pipeline, the timings and the privacy demonstration are real and measured, but the classifier is still being improved — it is a 39k-parameter model on FER-2013 and there is no face detector yet, so align your face in the guide. Treat the predictions as a demonstration, not a reading of your mood.

1 Your camera

Neither the video nor the photo leaves this page. There is no upload, no server call and no API key — the model runs on your CPU, in this tab.

Rate 15 Hz
Smoothing 0.60
checking…

Align your face in the guide. Inference runs at the rate above, independently of the video frame rate — emotion moves on a human timescale, so 15 Hz is plenty and leaves the UI thread free. Space pauses.

2 What the network actually sees

input 48×48
grayscale, normalised
Tchebichef map 16×16
K² coefficients
what an interceptor
could reconstruct
Representation
Order K K = 32
Why this matters. A truncated moment map is a lossy, non-invertible encoding. At low K the reconstruction on the right is unrecognisable, so a device can encode on-site and transmit only coefficients — privacy handled by the representation itself rather than bolted on downstream. This is the mechanism from my PhD work on classroom engagement recognition, where the subjects are minors.

3 Prediction & cost

waiting for camera
enable the camera to begin

4 Measured, not quoted

capture
ms
transform
ms
inference
ms
total
ms
FLOPs / frame
headroom
fps
Trained on FER-2013, 28,709 faces, in a Kaggle notebook whose export step writes the exact int8 tensor layout this page reads back. Raw arm: test accuracy for 39k parameters, against a human ceiling of roughly 65% on this dataset.
What this demo actually shows. Three runs in, the moment arms lose to raw pixels on this dataset, and the reason is now pinned down. The K=48 arm is the full basis: no truncation, 100% of the energy, 82 dB reconstruction — an invertible rotation of the very same pixels. It still trails raw by 12 points. So the cost is not lost information, it is that a convolution's assumptions, locality and translation equivariance, do not hold in the moment domain. On a companion benchmark (FEI, 200 identities at 256×256) the same code beats raw pixels by 3 points using 55× fewer operations, so this is dataset-dependent, not a property of the transform. The privacy demonstration on the right is exact either way. There is no face detector yet, so align yourself in the guide.