Automatic number-plate recognition (ANPR) is becoming more and more commonplace. Once the exclusive realm of the police, the technology used to accurately read car number-plates can now be found in supermarket and airport car parks.
It wasn’t long ago that ANPR technology was extremely expensive to purchase and implement. Now, even the Raspberry Pi has the ability to read number-plates with high accuracy using the Pi Camera Module and open-source software. Let’s demonstrate what’s possible by building a system to detect and alert when a car comes onto the driveway.
This tutorial was written by PJ Evans and first appeared in The MagPi 79. Click here to subscribe to The MagPi magazine.
ANPR Raspberry Pi: Pick a spot
First things first: where are we going to put it? Although this project has lots of applications, we’re going to see who’s home (or not) by reading number-plates of cars coming and going on a driveway. This means the Raspberry Pi is probably going to live outside; therefore, many environmental constraints come into place. You’ll need USB 5 V power to the Pi and a mounting position suitable for reading plates, although the software is surprisingly tolerant of angles and heights, so don’t worry too much if you can’t get it perfectly aligned.
Get an enclosure
As our Pi is going to live outside (unless you have a well-placed window), you’ll need an appropriate enclosure. For a proper build, get an IP67 waterproof case.
We’re opting for homemade, and are using a Raspberry Pi 3 A+ with the RainBerry – a 3D-printable case that, once you add some rubber seals, provides adequate protection. Make sure whatever you choose has a hole for the camera.
Prepare your Pi
As we don’t need a graphical user interface, Raspbian Stretch Lite is our operating system of choice. Any Pi can handle this task, although if you want the fastest image processing possible, you probably want to avoid the Zero models and get a nice, zippy Model 3B or 3B+. Get your operating system set up, make sure you’ve done the necessary sudo apt update && sudo apt -y upgrade and have configured WiFi if you’re not using Ethernet. Finally, make sure your Pi Camera Module is connected and enabled. You can check this by running sudo raspi-config and looking under ‘Interfacing Options’.
Install openALPR
Thankfully, we don’t need to be experts in machine learning and image processing to implement ANPR. An open-source project, openALPR provides fast and accurate processing just from a camera image. ‘ALPR’ is not a mistake: this US project is ‘Automatic License Plate Recognition’. Thanks to APT, installation is straightforward. At the command line, enter the following:
sudo apt install openalpr openalpr-daemon openalpr-utils libopenalpr-dev
This may take a while, as many supporting packages need to be installed, such as Tesseract, an open-source optical character recognition (OCR) tool. This, coupled with code that identifies a number-plate, is what works the magic.
Time for a test
Once installed, you’ll be unceremoniously dropped back to the command prompt. OpenALPR has installed a command-line tool to make testing its capabilities easier and they have also kindly provided a sample image. On the command line, enter the following:
cd
wget http://plates.openalpr.com/ea7the.jpg
This is a sample USA plate image and a tough one too. Wget grabs the file from the web and places it in your home directory. Let’s see if we can recognise it:
alpr -c us ea7the.jpg
All being well, you’ll see a report on screen. The most likely ‘match’ should be the same as the file name: EA7THE.
Install Python libraries
We can use openALPR in Python, too. First, install the libraries using pip. If you don’t have pip installed, run:
sudo apt install python-pip
To install the libraries:
pip install openalpr picamera python-pushover
Now test everything is working by running Python and enter the following code line by line at the >>> prompt:
import json
from openalpr import Alpr
alpr = Alpr("us", "/etc/openalpr/openalpr.conf", "/usr/share/openalpr/runtimedata")
results = alpr.recognizefile("/home/pi/ea7the.jpg")
print(json.dumps(results, indent=4))
alpr.unload()
If you’ve not seen JSON-formatted text before, this might seem a bit much, but you should see the correct plate number returned as the first result.
Get a Pushover token
So that we can get an alert when a car arrives or leaves, we’re using old favourite Pushover, which makes sending notifications to mobile phones a breeze. There’s a free trial, after which it’s a flat fee of $4.99 per device, with no subscription or limits. Once logged in, go to ‘Your Applications’ and make a note of your User Key. Then click ‘Create an Application/API Token’. Call it ‘ANPR’, leave all the other fields blank, and click ‘Create Application’. Now make a note of the API Token; you’ll need this and the User Key for your code.
Typing time
Now you have everything you need to create your ANPR application. Enter the code listing shown here or download it from GitHub. Save it as anpr.py in your home directory. Edit the file and enter your User and App tokens where prompted. Save the file, then test by entering:
python anpr.py
The code makes use of the Pi Camera Module and openALPR in tandem. Every five seconds, the camera takes a picture which is passed to openALPR for analysis. If a licence plate is found, we get the number. If there has been a change, an alert is sent to Pushover, which is then forwarded to any registered mobile devices.
Make your list
If you want to have more friendly names rather than just the plate number, try adding a Python dictionary just after the import statements, like this:
lookup = {
"ABC123": "Steve McQueen",
"ZXY123": "Lewis Hamilton"
}
Then change all instances of number_plate in the alert text as follows:
lookup[number_plate]
Now you’ll get a friendly name instead. See if you can handle what happens if the plate isn’t recognised.
Run on boot
A key part of any ‘hands-free’ Raspberry Pi installation is ensuring that in the event of a power failure, the required services start up again. There are many ways of doing this; we’re going use one of the simpler methods.
sudo nano /etc/rc.local
Find the final line, exit 0 and enter the following on the line above:
#Start ANPR Monitoring
/usr/bin/python /home/pi/anpr.py
Press CTRL+X then Y to save the file. Finally, run the earlier pip command again, using sudo this time to install the libraries for the root user:
sudo pip install openalpr picamera python-pushover
On reboot, the code will start up and run in the background.
Add logging and curfews
One use of this installation is to track the times cars come and go. This can be especially useful for young drivers who have curfew restrictions on their insurance. See if you can augment the code to check whether a registration plate has not been seen after a certain time. For example, if your younger family members have such a restriction, send them an alert to their phone if their car isn’t in the driveway 30 minutes beforehand. You might save them an insurance premium increase! Also, why not log all the comings and goings to a file? A bit of data analysis might help reduce car usage or fuel costs.
Make it your own
As ever, it’s over to you. Now you have the ability to track and record registration plates, there are many different applications for you to explore. Since all the analysis of the image is done locally, no internet connection is required for the system to work. Is there someone ‘borrowing’ your parking space at work? Catch ’em in the act! Why not take your Car Spy Pi on the road? It could record every vehicle you encounter, which may be useful should something untoward happen. Combine a Raspberry Pi Zero with a ZeroView and you’re all set.
from openalpr import Alpr from picamera import PiCamera from time import sleep import pushover # Pushover settings PUSHOVER_USER_KEY = "<REPLACE WITH USER KEY>" PUSHOVER_APP_TOKEN = "<REPLACE WITH APP TOKEN>" # 'gb' means we want to recognise UK plates, many others are available alpr = Alpr("gb", "/etc/openalpr/openalpr.conf", "/usr/share/openalpr/runtime_data") camera = PiCamera() pushover.init(PUSHOVER_APP_TOKEN) last_seen = None try: # Let's loop forever: while True: # Take a photo print('Taking a photo') camera.capture('/home/pi/latest.jpg') # Ask OpenALPR what it thinks analysis = alpr.recognize_file( "/home/pi/latest.jpg") # If no results, no car! if len(analysis['results']) == 0: print('No number plate detected') # Has a car left? if last_seen is not None: pushover.Client( PUSHOVER_USER_KEY).send_message( last_seen + " left", title="Driveway") last_seen = None else: number_plate = analysis['results'][0]['plate'] print('Number plate detected: ' + number_plate) # Has there been a change? if last_seen is None: pushover.Client( PUSHOVER_USER_KEY).send_message( number_plate + " has arrived", title="Driveway") elif number_plate != last_seen: pushover.Client( PUSHOVER_USER_KEY).send_message( number_plate + " arrived and " + last_seen + " left", title="Driveway") last_seen = number_plate # Wait for five seconds sleep(5) except KeyboardInterrupt: print('Shutting down') alpr.unload()