Deep License Plate Recognition comes to Zoneminder

oZoneDev
oZoneDev
Jul 6, 2019 · 5 min read

TL;DR — You can now configure ALPR in the Event Server. It usually works pretty well, as long as you can configure your zones correctly to grab alarmed images that have the license plate. See this.

I can barely read the plate myself

(Updated Jul 12, 2019. OpenALPR support also added, thanks to Andrew B)

I have been thinking about adding license plate detection to ZM for a while. There was some work done several years ago on this front which used openALPR. However, I found openALPR too inaccurate to use. I had actually integrated openALPR to my Event Server several months ago, but never released it, because it never got a single plate right (even after calibration) from my camera view. My camera view is at an elevation (most folks who use ZM have cameras at an elevation, based on what I see)

In general, when Open ALPR was first made, it was quite cutting edge, but now, with the advent of CNNs, Attention Networks et. al, the reliance of complex rules for plate recognition have changed. In fact, today, if I were to do this myself, I’d do it the following way:

  • Train YOLOv3 to detect a license plate. This would involve getting large data sets of vehicles at all angles/elevations, marking boxes around license plates and training that network.
  • Given a detected plate, use some form of an attention network to bring out the text

While there are many license plate databases available in the wild, thinking about it and doing it are two entirely different things.

Isaac Connor recently pointed me to the folks at Plate Recognizer. They’ve done the hard work of training their own models and offer a cloud API which as of July 2019, offers a generous 2500 free API calls per month.

First, here is a comparative:

OpenALPR:

Plate Recognizer:

OpenALPR, to the best of my knowledge doesn’t use DNNs while Plate Recognizer does, so it’s not surprising.

That being said, OpenALPR does provide a lot more information when it does find a plate, including car model, make, year of manufacture and whole lot more.

So I decided to integrate Plate Recognizer into the Event Sever as a machine learning hook. I’d like to also add it to zmMagik, but I’m pretty sure I’ll exceed their API limit. Maybe some other day. Or maybe some of you would like to sign up to a paid plan and give me access — then I’ll integrate it with zmMagik too :). I’ll be honest though, Plate Recognizer’s pricing is very competitive. If I had a business that needs high quality ALPR I’d happily buy their plans. But I don’t. I’m doing this for fun.

I am told plate recognition is a big ask for many ZoneMinder users, so I hope you like it. And hopefully some of you buy their plans and help them succeed.

How to use it

Really very simple. They offer two models:

  • A cloud API version if you have internet
  • A locally hosted docker image if you don’t have internet (you’ll still need internet once in a while for them to check licenses). Very cool to have both models and done so easily

I integrated both.

In objectconfig.ini you will see:

[alpr]
# currently unused
alpr_service=plate_recognizer
# replace with your api key
alpr_key=<token>
# leave this as yes for now
alpr_use_after_detection_only=yes
# if yes, then it will log usage statistics of the ALPR service
alpr_stats=yes
# If you want to specify regions. See http://docs.platerecognizer.com/#regions-supported
#alpr_regions=['us','cn','kr']
# If you want to host a local SDK https://app.platerecognizer.com/sdk/
#alpr_url=https://localhost:8080

Read the comments — its pretty self explanatory.

My approach

To reduce the number of API calls, I first use YOLO to detect vehicles. If YOLO detects a vehicle, the I invoke the plate recognition API. So to get this to work, use this for the monitor that needs ALPR:

models = yolo,alpr,face # obviously, face is optional

As long as you have YOLO before alpr and YOLO is run, it will invoke ALPR if it finds a vehicle. Obviously, if you have:

models=face,yolo,alpr
detection_mode=first

Then if it finds a face, it won’t invoke yolo and will not invoke alpr. So use detection_mode=all if you have multiple models, or put yolo before face

Also, don’t just blindly enable alpr for all your monitors. Only enable it for the monitor where you need to read plates.

Maximizing changes of getting a license plate

Given the Event Server only has a total of 2 frames in which the license plate should show up (snapshot or alarm, or a custom fid), you’ll need to get intelligent with your zones. Here are my driveway zones.

For cars backing out of my garage, as long as the car is part of the preclusive zone, alarms won’t trigger (even if its in the active zone). Once a car is out of the preclusive zone and inside the active zone, the alarm will trigger. This would mean the front of the car is visible and therefore the license plate.

For cars coming into my driveway (primary usecase), it will first hit the active zone. Note that I’ve put it deep inside my driveway because cars turn in, and I’d like it as straight as possible.

Your use-case may be different. Get creative. Have fun.

zmNinja

zmNinja — the best open source surveillance mobile app for ZoneMinder NVR

oZoneDev

Written by

oZoneDev

A breath of fresh air for security and surveillance software

zmNinja

zmNinja

zmNinja — the best open source surveillance mobile app for ZoneMinder NVR

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade