FaceCore - Raspberry Pi AI Face Recognition Access System
by ArlanArmanuly in Design > Software
28 Views, 0 Favorites, 0 Comments
FaceCore - Raspberry Pi AI Face Recognition Access System
FaceCore is a prototype access-control system that uses artificial intelligence to analyse a person standing in front of a camera. The system can distinguish between an acceptable face, glasses, an invalid face position and a possible picture attack.
If the face is valid, it proceeds to log in, or to a registration of the user.
The project combines a Raspberry Pi, a camera, a YOLO object-detection model, distance sensing, status indicators, a display and a custom laser-cut wooden enclosure. A web dashboard is also used to display the camera result, system status and access logs.
This Instructable explains the complete process, from collecting data and training the AI model to wiring the hardware and assembling the final enclosure.
Supplies
Electronic components
- Raspberry Pi
- Raspberry Pi power supply
- Camera or USB webcam
- 16x2 character LCD
- Ultrasonic distance sensor
- Push buttons
- Status LEDs
- Passive buzzer
- Breadboard or GPIO extension board
- Wires
Enclosure materials
- 4 mm plywood
- Tape
- Screws, glue or other mounting materials
- Cable ties where necessary
Software
- Python
- Ultralytics YOLO
- Roboflow
- OpenCV
- Gradio
- PostgreSQL
- Docker
- Inkscape
- Boxes.py
- Visual Studio Code
- Git and GitHub
Tools
- Laser cutter
- Computer for model training( can be done via roboflow with a subscription)
- Soldering equipment(optional)
- Measuring tools
Total cost: ~180-200€
Plan the System
Before building FaceCore, I divided the system into the following parts:
- Distance and presence detection
- Camera image capture
- YOLO image verification
- Face embedding extraction
- User registration and identity matching
- Access decision
- Physical feedback
- Web dashboard
- Database logging
The ultrasonic sensor first measures whether someone is standing in front of the device. The system becomes active when the measured distance is 90 cm or less.
After activation, and further action, the camera captures an image. The image is first processed by the custom YOLO model, which can detect four classes:
- access
- glasses
- no_access
- picture_attack
YOLO is not used to determine the identity of the person. It acts as a verification and filtering stage before face recognition.
Identity recognition is only started when:
- YOLO detects the access class
- the YOLO confidence is above the required threshold
- no picture attack is detected
- no invalid face condition is detected
- no glasses condition is detected
When these conditions are satisfied, the face-recognition module extracts a face embedding from the image. This embedding is compared with the embeddings of registered users stored in the PostgreSQL database.
If the closest matching embedding is within the accepted distance threshold, the system recognises the person and grants access. Otherwise, the person is treated as a guest and access is denied.
The final result is displayed through the LCD, RGB LED, buzzer and Gradio dashboard. The decision event is also logged.
Collect and Annotate the Dataset
The AI model requires labelled images before it can recognise the different situations.
I recorded short videos and extracted images showing:
- A normal visible face (access)
- A face wearing glasses (glasses)
- Invalid positions, such as closed eyes, covered/closed eyes or an extreme side angle (no_access)
- A face displayed on a phone (picture_attack)
The images were uploaded to Roboflow and labelled using bounding boxes. Every bounding box was assigned to one of the four project classes.
It is vital to collect photos of different people, in various environment, lighting, angles..
The dataset was divided into training, validation and test sets at a 80/10/10 proportion. Augmentations were used carefully to add variation. A total of 700 images were collected, 1700 including augmentation.
Train the YOLO Model
The model was trained using Ultralytics YOLO26. A nano-sized model was selected because the final system has to run on limited hardware.
The main training settings were:
- Image size: 960 pixels
- Model size: nano
- Type: object detection
- Training device: NVIDIA GPU
Example training command:
After training, I reviewed:
- Precision
- Recall
- mAP
- Confusion matrix
- Validation images
- Detection behaviour with the live camera
The best.pt weight file was selected for the final application.
Develop the Software and Dashboard
The FaceCore software is written mainly in Python and is divided into several modules.
The main processing pipeline performs the following tasks:
- Reads the distance from the ultrasonic sensor
- Captures an image from the camera
- Runs the custom YOLO model
- Reads the detected class and confidence
- Decides whether identity recognition is allowed
- Extracts a face embedding
- Loads registered users from the database
- Finds the closest matching identity
- Makes the final access decision
- Updates the hardware and dashboard
- Stores the event in the database
YOLO verification
The YOLO model is loaded from the trained best.pt file. Images are processed at an inference size of 960 pixels.
The model returns:
- detected class
- confidence score
- number of detections
- bounding boxes
- verification decision
The identity recognition stage is skipped when:
- a picture attack is detected
- the class is no_access
- glasses are detected
- no valid access class is detected
- the confidence is below the minimum threshold
This prevents a low quality or suspicious camera image from being used for identity matching.
Face recognition
After the YOLO verification succeeds, FaceCore searches for a face in the image and creates a numerical face embedding.
When the face_recognition Python library is available, the system uses its HOG-based face detector and face-encoding model.
If the library is unavailable, the application can use a simpler OpenCV fallback. The fallback detects the face with a Haar cascade, converts it to grayscale, resizes it and creates a normalised numerical vector.
The face embedding is compared with the embeddings of registered users. The application calculates the distance between the new embedding and every compatible stored embedding.
The user with the smallest distance is selected as the best candidate. The match is accepted only when the distance is below the configured threshold.
Dashboard
The Gradio dashboard shows:
- live or captured camera image
- YOLO bounding box
- detected YOLO class
- YOLO confidence (debug)
- recognised user name
- distance-sensor reading
- API status
- database status
- hardware status
- final access decision
- access logs
Possible final states include:
- Access granted to a recognised user
- Guest user
- Glasses detected
- Invalid face
- Picture attack detected
- No face found
- Person outside the active distance -> Idle
- Database or API error
Connect the Hardware
The electronic components were first tested separately before being combined.
The final system includes:
- USB camera for image capture
- HC-SR04 ultrasonic sensor for distance measurement
- 16x2 LCD for instructions and decisions
- RGB LED for visual status
- Metal push buttons for manual input
- Passive buzzer for sound feedback
- GPIO breakout board
- Breadboard
- Jumper wires
Each component was first tested with a small standalone Python script. After the individual tests worked, the hardware controls were integrated into the main application.
Extra care is required when connecting the HC-SR04 echo pin to a Raspberry Pi. Raspberry Pi GPIO pins use 3.3 V logic, while the echo output of the sensor can be 5 V.
Design and Enclosure
The enclosure protects the electronic components and gives the project a clean, finished appearance. I made my enclosure from 4 mm plywood using a laser cutter. However, the design could also be adapted for 3D printing or another method.
Generate the basic enclosure
I used the Console2 template from boxes.py as the starting point. This template creates an enclosure with a sloped front panel, which was suitable for mounting the display, camera, buttons and sensors.
Before downloading the design, I adjusted the template settings to match the material and the available laser cutter:
- Material thickness: 4 mm
- Sheet size: 450 × 600 mm
- Burn correction: 0 mm
- Inner corners: corner
It can also be modified to have removable parts if required.
Modify the SVG file
I opened the generated SVG in Inkscape and modified the panels to fit the FaceCore components.
I added or adjusted openings for all the sensors: Camera, LCD, LED, Buttons, Proximity Sensor, Power Supply.
I also removed the automatically generated panel labels and checked that all cutting lines used the correct stroke settings.
Laser cut the parts
I imported the finished SVG file into the laser-cutter software and positioned the panel inside the available sheet area.
The design was then cut from 4 mm plywood. After cutting, I removed the parts and checked the finger joints, openings and overall dimensions.
Test-fit and assemble the enclosure
Before using glue, I performed a dry fit to make sure that all the finger joints alligned correctly, as well as awhether my sensors fitted into the openings. if not - fix by tape or widen the opening manually.
After checking the fit, I assembled my electronics, fixed it, and only after that have i glued and fixed the parts, except for the roof which is used for maintenance.
Backend and Database
The backend connects the AI models, PostgreSQL database, Gradio dashboard and Raspberry Pi hardware into one complete system. It is responsible for processing camera images, recognising registered users, making the final access decision and storing the result.
The FaceCore backend is written in Python using FastAPI. PostgreSQL stores registered users, access attempts and hardware status events. Docker Compose is used to run the backend services in a consistent environment.
The Gradio dashboard and hardware controller run directly on the Raspberry Pi. They read the camera and sensors and send images and measurements to the FastAPI backend.
System architecture
The Raspberry Pi stack is located in the RPi directory of the project.
It contains three main parts:
- Docker services:
- PostgreSQL
- pgAdmin
- FastAPI backend
- AI processing:
- Custom YOLO model
- Face embedding extraction
- Identity matching
- Raspberry Pi application:
- USB camera
- Ultrasonic sensor
- LCD
- RGB LED
- Buttons
- Buzzer
- Gradio dashboard
The overall communication flow is:
The backend prevents face recognition from running when YOLO detects:
- picture_attack
- no_access
- glasses
- no valid access class
- confidence below the required threshold
This creates a two-stage verification process
Docker Compose services
The Docker configuration is stored in:
It starts three services:
PostgreSQL
PostgreSQL stores the persistent project data.
The container uses postgres:16-alpine
Its files are stored in a Docker volume. Because of this, users and access logs remain available when the containers are restarted or recreated.
The database volume should not be deleted unless all stored data is no longer needed.
pgAdmin
pgAdmin provides a web interface for viewing the PostgreSQL database.
It can normally be opened at:
I used pgAdmin to inspect the registered users, access logs and status events
FastAPI
The API container is built using:
It exposes the backend on port 8000.
The Docker image contains:
- FastAPI source code
- Backend Python dependencies
- YOLO model
- Face-recognition helper code
- Database storage code
The YOLO model is expected at:
API endpoints
The FastAPI application provides several endpoints.
System Checks
Checks whether the API is running and reports the active face-recognition backend.
Checks whether PostgreSQL is available.
Users
These endpoints list users, rename users and deactivate users
AI operations
Runs YOLO without performing identity matching.
Runs YOLO and, when the image is accepted, creates a face embedding and registers a new user.
Runs YOLO and face recognition, then returns access granted or access denied.
Logs and Hardware status
These endpoints provide access history and store hardware events such as:
- READY
- STANDBY
- ANALYZING
- ACCESS_GRANTED
- ACCESS_DENIED
- ERROR
Database structure
The database tables are created automatically when the backend starts.
FaceCore uses three main tables.
users
The users table stores registered people.
Important fields include:
- User ID
- Name
- Face embedding
- Recognition backend
- Registration image path
- Creation and update timestamps
access_logs
The access_logs table stores scan, registration and verification attempts.
It can contain:
- Event type
- Human-readable decision
- Result status
- YOLO class
- YOLO confidence
- Recognised user
- Face-matching distance
- Proximity measurement
- Original image path
- Annotated image path
- Additional JSON details
status_events
The status_events table stores events produced by the Raspberry Pi hardware application.
These events can include:
- Current system state
- LCD text
- Component name
- YOLO confidence
- Proximity distance
- Additional technical information
Face-recognition backend
The application supports two face-recognition methods.
The preferred backend is:
It creates a 128-number face descriptor.