Facial recognition on a Raspberry Pi 5: what actually fits
Privara runs its whole recognition pipeline on the device. The hard part was not the model, it was deciding what the device should never try to do.
The easy version of access control is a camera that ships frames to a server and waits for an answer. The version Privara needed was one that keeps working when the network does not, which meant the inference had to happen on the device. On a Raspberry Pi 5 that constraint forces a set of decisions more about restraint than about clever modelling.
Pick the frame rate you can actually afford
Recognition does not need to run at the camera's full frame rate. Running detection on a sampled stream, and only entering the recognition path once a face is present, keeps the device responsive at the door while leaving headroom. The first version tried to do everything on every frame and ran hot and slow. Sampling fixed both.
Liveness is not optional
A system that matches a photograph is not an access-control system. The pipeline checks for the cues that separate a live face from a printed image before it accepts a match, which rules out the simplest spoof without pretending to be a hard biometric guarantee.
Keep the enrolment path boring
Face data is sensitive, so enrolment runs through an authenticated path onto the Node.js and Express backend, with records in MongoDB and JWT protecting the endpoints. The device holds only what it needs to match, and the management app talks to the backend rather than to the door directly.
camera -> sample frame
-> detect face (YOLOv8)
-> liveness check
-> match against enrolled embeddings
-> grant + log, or denyThe result
The finished system recognized enrolled faces with over 95% accuracy at sub-second latency, entirely on the device. The interesting lesson was that most of the work was deciding what to leave out: sampling instead of streaming, a narrow liveness check instead of a research-grade one, and a plain enrolment flow instead of a clever one.