Post

Adding Face Detection to your Pi Powered Motion Detector

Adding Face Detection to your Pi Powered Motion Detector

Back during //Build 2015 I was playing with the Project Oxford APIs — Microsoft’s computer vision platform, now called Azure AI Vision — and in parallel building some Raspberry Pi based AllJoyn projects. I ended up combining them: a Pi running the Motion app as a security camera, with a hook that sends every captured frame through Oxford’s face detection API.

Here’s how to build your own.

Hardware and software you need

Step 1: Get the Pi running

  1. Install Raspberry Pi OS on an SD card
  2. Connect camera, WiFi adapter (if needed), SD card
  3. Boot, run raspi-config — enable SSH, camera, set WiFi credentials
  4. Configure wireless if not done in raspi-config

Update everything and install Motion:

1
2
3
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install motion

Step 2: Hook Motion to the face detector

Motion has a configuration directive that runs a shell script whenever it captures a frame. Edit /etc/motion/motion.conf — around line 510 you’ll find the on_picture_save directive:

1
2
3
# Command to be executed when a picture (.ppm|.jpg) is saved (default: none)
# To give the filename as an argument to a command append it with %f
on_picture_save sh /home/pi/oxford/motion-picture-save.sh %f

This tells Motion to call your script with the captured filename every time motion is detected.

Step 3: The shell script

Create /home/pi/oxford/motion-picture-save.sh:

1
2
3
#!/usr/bin/env bash
echo $1
/usr/bin/python /home/pi/oxford/oxford.py $1

Make it executable:

1
chmod +x /home/pi/oxford/motion-picture-save.sh

Step 4: The face detection script

Create /home/pi/oxford/oxford.py. This sends the captured image to the Oxford face detection API and prints what it finds:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/usr/bin/env python
import sys
import urllib
import json
import requests

url = "https://api.projectoxford.ai/face/v1.0/detect"
headers = {
    'Content-type': 'application/octet-stream',
    'Ocp-Apim-Subscription-Key': 'YOUR_API_KEY_HERE',
}
params = {
    'returnFaceAttributes': 'age,gender,headPose',
    'returnFaceLandmarks': 'true',
}

if len(sys.argv) == 2:
    filename = sys.argv[1]
else:
    print("Usage: oxford.py <image_file>")
    sys.exit(0)

payload = open(filename, "rb").read()
try:
    resp = requests.post(url, params=params, data=payload, headers=headers)
    faces = resp.json()
    if faces:
        for face in faces:
            attrs = face.get('faceAttributes', {})
            print("Face detected — age: {age}, gender: {gender}".format(**attrs))
    else:
        print("No faces detected")
except Exception as e:
    print("Error: {0}".format(str(e)))

Install the dependencies:

1
pip install requests

Step 5: Run it

Start Motion:

1
sudo motion

Walk in front of the camera. Motion captures a frame, calls your shell script, which calls oxford.py, which hits the API and prints face attributes to the log. You’ll see output like:

1
Face detected — age: 38, gender: male

What this is actually useful for

On its own, printing to a log isn’t that interesting. But this is a skeleton you can build on:

  • Notify on unknown faces — store known face IDs and alert if a stranger is detected
  • Count people — track how many distinct faces appear over time
  • Log to a database — store detections with timestamps for later analysis
  • Push to Nitrogen or another IoT platform — stream detections as events

The Oxford/Azure Face API also returns face landmarks, emotion attributes, and can do face identification if you train it with a person group. The Python client library I wrote at the time wraps all of this cleanly if you want to go further than raw REST calls.

The Pi + Motion combination is solid for a low-cost always-on camera. Adding cloud vision on top of it is what turns it from a dumb motion sensor into something actually useful.

This post is licensed under CC BY 4.0 by the author.