Implementing Face Recognition on the Raspberry Pi

Introduction

The purpose of this project is to develop a basic face recognition system using picamera2 and OpenCV on the RPI. The major steps are as follows:

  • Set up work environment and install dependencies
  • Prepare training and test images
  • Write and debug the code
  • Run and evaluate the system

Setup The Environment

Equipment List

Here's the list of equipment that used for this project:

  • Raspberry Pi (3)
  • Power supply
  • Mouse connected to the RPI via USB
  • Keyboard connected to the RPI via USB
  • Display connected to the RPI via HDMI
  • One camera connected to the camera port on the RPI with a flex cable

I have a standard camera, but there's also a noir variant, which is designed to take pictures in the dark when used with an infrared light source.

Camera module connected to Raspberry Pi via flex cable

Create a Virtual Python Environment

Make a dedicated directory for this project and go there:

> mkdir Recognize

> cd Recognize

Create and activate the virtual environment:

> python3 -m venv face_recognition_env --system-site-packages

> source face_recognition_env/bin/activate

When you activate the virtual environment you should see its name (face_recognition) at the beginning of the command line prompt, in parentheses.

Info: You can deactivate the virtual environment by typing deactivate at the command prompt.

Verify Camera Operation

Test Camera with Built-In Tools

Verify that the camera is working and take a test photo with these two commands:

> rpicam-hello --list-cameras

> rpicam-still -o test.jpg

The first command should show a list of cameras with a response that looks like this:

list of cameras as returned with rpicap-hello command

The second command opens a preview window for a few seconds, saves the picture in a file called test.jpg, followed by a command line message saying: Still capture image received. You can use the built-in viewer to verify the picture.

Test picamera2 Integration

You can also use the following script to verify that your picamera2 integration is working:

# Quick test script
python3 -c "
from picamera2 import Picamera2
import time
picam2 = Picamera2()
picam2.start()
time.sleep(2)
picam2.capture_file('picamera2_test.jpg')
picam2.stop()
print('picamera2 test successful!')
"

The script should capture and save a picture called picamera2_test.jpg in your local directory, which you can inspect and verify with the viewer on your RPi.

Training and Test Images

Prepare Reference Images To Train the Model

I decided to use pictures of Nelson Mandela and Jimmy Carter for this project. There's a wide range of pictures of the two of them on the Internet, some from their younger days and others that were taken when the two were older.

I Created a folder called reference_images in the project directory, and added five clear photos each of Mandela and Carter. To keep the program simpler, I named the pictures like so: mandela_1.jpg, mandela_2.jpg, carter_1.jpg, etc.

Test Pictures

When you're ready to test the face recognition system, you'll have the option of directing the camera either to pictures on the computer screen or unsuspecting family members. Consider testing the following scenarios:

  1. Several pictures with only Jimmy Carter
  2. Several pictures with only Nelson Mandela
  3. Pictures of Jimmy Carter with others
  4. Pictures of Nelson Mandela with others
  5. Pictures not containing only unknown faces

The first two groups will be relatively easy true-positive pictures. Groups 3 and 4 will be more interesting to test, to see whether the algorithm will score true-positives and true-negatives, and no false-positives or false-negatives. Group 5 should be a confirmation of true-negatives and hopefully won't yield any false-positives.

The Python Script

Where to Find the Python Script

You can find the python script on GitHub: https://github.com/skaltounian/Recognize

Core Components of the Script

Here's what the core components do:

Face Database:

  • Process reference images from a designated folder
  • Extract facial features using the face_recognition library
  • Encode for each known face
  • Store the database locally using Python pickle

Camera Interface:

  • Use picamera2 for native Raspberry Pi camera integration
  • Implement image rotation using libcamera
  • Convert between RGB/BGR colour formats when needed

Face Recognition:

  • Real-time face detection using
  • Face encoding comparison using Euclidean distance
  • Configurable confidence thresholds (default: 60%)
  • Return recognized names with confidence percentages

Display System:

  • Live video feed with OpenCV GUI
  • Visual face detection frames (green for known, red for unknown)
  • Text labels showing names and confidence scores
  • On-screen rotation and status indicators

Classes and Methods

  • Imports
  • Class CameraManager
    1. __init__
    2. setup_camera
    3. capture_frame
    4. camera_thread
    5. start_camera_thread
    6. get_latest_frame
    7. stop_camera
  • Class FaceDatabaseManager
    1. __init__
    2. load_image_and_encode
    3. build_face_database
    4. save_face_database
    5. load_face_database
    6. get_known_faces
  • Class FaceRecognizer
    1. __init__
    2. recognize_face
    3. draw_restults_on_frame
  • Class FaceRecognitionSystem
    1. __init__
    2. run_camera_recognition
  • main()

Face Recognition Pipeline

  1. Capture Frame: picamera2 captures RGB image
  2. Colour Conversion: RGB to BGR for OpenCV display, BGR to RGB for face_recognition
  3. Face Detection: Locates faces in the image
  4. Feature Extraction: Creates encoding for each detected face
  5. Comparison: Compares against known face database using Euclidean distance
  6. Classification: Matches below threshold are identified, others marked as "Unknown"
  7. Display: Draws bounding boxes and labels on the video feed

Run the System

Running the System

Once you're save the script, make it executable by typing:

> sudo chmod +x face_rec_picam2.py

Be sure that your virtual environment is active and run the python script:

> source face_recognition_env/bin/activate

> python face_rec_picam2.py

A Few Pictures of My Results

Carter true-positive training picture
Software recognizes training picture of Jimmy Carter.
Mandela true-positive training picture
Software recognizes training picture of Nelso Mandela.
Mandela and unknown persons
Software recognizes Nelson Mandela (T-P) and red frame with unknown persons (T-N).
Young Mandela still recognized
Software recognizes new image of younger Mandela (T-P).
Mandela multiple pictures recognized
Software recognizes Mandela in a few pictures, and misses a couple.

Some Things That Went Wrong

Installing dlib

This was a tough nut to crack. Having a slow RPI-3 made installing dlib difficult. Compilation took forever - that is, it didn't complete. Having an SSH connection to the RPI didn't help either. At some point, when I had walked away, my Windows computer went to sleep and lost network connection. When, on the next day, I tried to reconnect, the RPI failed to connect. So I rebuilt the RPI. Twice.

The solution was to:

  1. Ensure that the necessary prerequisites are installed
  2. Expand Swap memory, which is important for a well aged RPI-3

The RPI-3 has limited RAM, so building dlib can crash without enough virtual memory.

Reconfigure the swap memory by editing the configuration file with:

> sudo nano /etc/dphys-swapfile

Change the line CONF_SWAPSIZE=100 to CONF_SWAPSIZE=2048

Save and exit, then apply the changes by restarting the swap service with:

> sudo systemctl restart dphys-swapfile

To verify the new swap is active use the command:

> free -h

Look at the Swap: row, where you should see approximately 2.0G. If it still shows 100M or less, double check the file and restart the service again.

I'm glad I had Git and my code was already on GitHub.

Starting With a Clean Slate

At one point during the project I had gone down so many rabbit holes that I decided to start with a clean slate. One of the reasons for my troubles was that both Claude and ChatGPT assumed the RPi-3 was using libcamera, and I had to remind them (after much experimentation) that since I was running Bookworm we should be using rpicam.

To clean up:

  • Deactivate the virtual environment
  • Remove face_recognition_env
  • Keep all project files, including the python script and training pictures

> deactivate

> rm -rf face_recognition_env

> sudo apt remove libcamera-apps libcamera-tools

> sudo apt autoremove

> sudo apt autoclean # clean package cache

Then, make sure that rpicam is still available:

> rpicam-hello --version

> ls /usr/bin/rpicam*

Image Rotation

By default, the camera in my setup captured images upside down. This apparently prevents OpenCV2 from recognizing faces, given that all training data for face recognition has faces that are straight on and right side up. Here's how you can configure your camera to rotate the images:

from picamera2 import Picamera2
from libcamera import Transform

picam2 = Picamera2()
transform = Transform(rotation=180)

camera_configuration = picam2.create_preview_configuration(
	main={“size”: (640, 480), “format”: “RGB888”},
	transform=transform
)

References