Siddhant Kumar
Project 052 · Security

Number-Plate Gate Logger.

Reads vehicle number plates at a gate to log and automate entry and exit — with the OCR, whitelist and privacy realities of real ANPR handled honestly.

Advanced 16–24 hours 32 min read VisionANPRGate
Jump to source Bill of materials
Number-Plate Gate Logger — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Advanced
Build time
16–24 hours
Indicative cost
₹6,000 – ₹10,000
Platform
Raspberry Pi 4 Model B (4 GB)
Category
Security
Last updated
28 July 2026
Contents — 27 sections

Project Overview

Reads vehicle number plates at a gate to log and automate entry and exit — with the OCR, whitelist and privacy realities of real ANPR handled honestly.

Automatic number-plate recognition (ANPR) turns a gate into something that recognises vehicles: it reads the plate of an approaching car, logs the entry or exit with a timestamp and image, and — for known vehicles on a whitelist — opens the gate automatically, so residents or staff never stop while visitors are handled by exception. It is one of the most visibly useful pieces of computer vision, and also one where the gap between a demo and a dependable system is wide, because plates in the real world are dirty, angled, glared, motion-blurred, and lit by headlights at night. This project builds a gate logger that treats those realities — and the privacy implications of recording vehicle movements — as core design problems, not afterthoughts.

The pipeline is a classic two-stage vision problem: first detect where the plate is in the camera frame (a small object-detection step that finds the plate region against a busy scene), then read the characters on it (an OCR step, ideally a recogniser trained on plates rather than generic text). Doing detection first is what makes the OCR reliable — feeding a tightly-cropped, deskewed plate to the recogniser instead of a whole noisy frame dramatically cuts errors. The result is matched against a whitelist of authorised plates to decide whether to open the gate, and every read — recognised or not — is logged with its confidence and a captured image so a human can verify or override.

The honesty is in the edges. OCR is never perfect, so the system reports a confidence and is designed to fail gracefully: a low-confidence or unrecognised read does not fling the gate open or slam it shut — it falls back to a human (an intercom, a guard, a visitor flow) rather than trusting a shaky guess, and near-matches (one ambiguous character) are handled deliberately. Because ANPR records where and when specific vehicles go, it is personal data, so the design keeps the plate database and logs access-controlled, is explicit about retention, and is framed for legitimate access control on private premises — not covert tracking. It is candid that lighting, angle and plate condition set a hard ceiling on accuracy, and that a good camera, IR illumination and a controlled approach geometry matter as much as the model. But built with those constraints respected, a plate-reading gate is a genuinely convenient, well-logged, and responsibly-run piece of access automation.

The dashboard of a modern car
A gate camera reads an approaching vehicle's plate to log and automate entry and exit. Photograph sourced from Wikimedia Commons — Car dashboard.jpg. Reused under the licence stated on that page; please check it before republishing.

What this project does

  • Detects the number plate in the camera frame, then reads its characters (OCR)
  • Matches the plate against a whitelist to automate gate entry/exit
  • Logs every read (recognised or not) with confidence, time and image
  • Falls back to a human on low-confidence/unknown plates instead of guessing
  • Handles day and night with a suitable camera and IR illumination
  • Treats plate data as personal data — access-controlled, retention-explicit
  • Automates known vehicles while visitors are handled by exception

Real-World Applications

SettingHow it is used
Residential society / gated community gatesAuto-opening for residents' registered vehicles, logged entry/exit, and a visitor exception flow.
Office / campus parkingStaff whitelist automation and complete vehicle logs for a controlled car park.
Small toll / access barriersAutomated barrier operation for authorised vehicles with an audited fallback.
Fleet / yard accessLogging and gating company vehicles in and out of a depot or yard.

Deployment contexts where a build of this kind earns its keep.

Features & Capabilities

  • Two-stage detect-then-read pipeline for reliable OCR
  • Confidence-gated decisions with graceful human fallback
  • Whitelist automation for residents/staff; exception flow for visitors
  • Full audit log with captured images
  • Day/night operation with IR and controlled approach geometry
  • Privacy-aware: access-controlled data, explicit retention
  • Honest about accuracy limits (lighting, angle, plate condition)

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelAdvanced
Estimated completion time16–24 hours
Indicative build cost₹6,000 – ₹10,000
Primary disciplineSecurity
Reference platformRaspberry Pi 4 Model B (4 GB)

Skills you should have (or will pick up)

  • Building a plate-detection + OCR (ANPR) pipeline
  • Camera/geometry/lighting setup for readable plates
  • Confidence gating and graceful fallback logic
  • Whitelist matching with near-match handling
  • Privacy-aware data handling and retention

Bill of Materials

Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.

ComponentKey specificationQtyApprox. cost
Raspberry Pi 4 Model B (4 GB)
Use an official 5 V 3 A supply — brown-outs from phone chargers corrupt SD cards.
Quad-core Cortex-A72 @ 1.8 GHz, 4 GB LPDDR4, Gigabit Ethernet, Wi-Fi 5, BT 5.0, 2× USB 3.0, 40-pin GPIO1₹5,800
Raspberry Pi Camera Module 3
Pi 5 uses a narrower 22-pin CSI cable — the old 15-pin ribbon will not fit.
12 MP IMX708, autofocus, HDR, 1080p50, CSI-2 ribbon1₹2,600
5 V single-channel opto-isolated relay module
Cut the JD-VCC jumper and feed the coil separately for true isolation.
SPDT contacts rated 10 A @ 250 VAC / 10 A @ 30 VDC, opto-isolated input1₹90
ESP32 DevKit V1 (ESP-WROOM-32)
Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC1₹450
microSD card 32 GB A1 class
For 24/7 loggers buy a high-endurance card — normal cards die in months.
A1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended1₹450
5 V 3 A regulated SMPS adapter
Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A.
100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection1₹350
ANPR-suitable camera + IR
Motion blur and night are the main failure sources
Global-shutter or fast camera with IR-pass/illumination for night plates1₹2,500
Gate/barrier interfaceRelay/dry-contact to the gate motor controller, with safety interlocks1₹600
Vehicle-present trigger
Trigger capture when a vehicle is in position
Loop detector / IR beam to capture at the right moment1₹700
Weatherproof camera housingIP-rated, sun-hooded, positioned for a controlled plate view1₹500

Estimated total: ₹14,040, excluding tools, shipping and consumables.

Tools and consumables

  • Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
  • Digital multimeter — continuity, DC volts and current ranges
  • Wire strippers, flush cutters and a small set of precision screwdrivers
  • Heat-shrink tubing and a heat gun (or a lighter, carefully)
  • A laptop with a USB port and the toolchain listed above

Hardware Specifications

PartSpecificationSupplyInterfaceReference
Raspberry Pi 4 Model B (4 GB)Quad-core Cortex-A72 @ 1.8 GHz, 4 GB LPDDR4, Gigabit Ethernet, Wi-Fi 5, BT 5.0, 2× USB 3.0, 40-pin GPIO5 V / 3 A USB-CGPIO, SPI, I²C, UART, CSI, DSIDatasheet
Raspberry Pi Camera Module 312 MP IMX708, autofocus, HDR, 1080p50, CSI-2 ribbon3.3 V via CSICSI-2Datasheet
5 V single-channel opto-isolated relay moduleSPDT contacts rated 10 A @ 250 VAC / 10 A @ 30 VDC, opto-isolated input5 V coilDigital (active-low)Datasheet
ESP32 DevKit V1 (ESP-WROOM-32)Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC3.3 V logic / 5 V USBUART, SPI, I²C, I²S, CAN, PWMDatasheet
microSD card 32 GB A1 classA1 rated, 10 MB/s random write, UHS-I, endurance-grade recommended3.3 VSDIO / SPIDatasheet
5 V 3 A regulated SMPS adapter100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection5 VDC barrel / USBDatasheet

Consolidated electrical and interface specifications for every active part in the build.

Power Budget & Supply Sizing

Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.

LoadSupply railTypical current (mA)Notes
Raspberry Pi 4 Model B (4 GB)5 V / 3 A USB-C1200Use an official 5 V 3 A supply — brown-outs from phone chargers corrupt SD cards.
Raspberry Pi Camera Module 33.3 V via CSI250Pi 5 uses a narrower 22-pin CSI cable — the old 15-pin ribbon will not fit.
5 V single-channel opto-isolated relay module5 V coil70Cut the JD-VCC jumper and feed the coil separately for true isolation.
ESP32 DevKit V1 (ESP-WROOM-32)3.3 V logic / 5 V USB160Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
microSD card 32 GB A1 class3.3 V100For 24/7 loggers buy a high-endurance card — normal cards die in months.
5 V 3 A regulated SMPS adapter5 V3000Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A.

Summed typical draw is 4780 mA. With a 1.5× design margin the supply should deliver at least 7200 mA continuously at the stated rail voltage.

Software Requirements & Development Environment

Reference toolchain: Raspberry Pi OS Bookworm (64-bit) + Python 3.11 + VS Code Remote-SSH. Anything newer normally works; anything older may lack the board definitions used here.

  • Flash Raspberry Pi OS (64-bit) with Raspberry Pi Imager; pre-configure Wi-Fi, hostname and SSH in the Imager settings so the board comes up headless.
  • Update first: sudo apt update && sudo apt full-upgrade -y, then reboot.
  • Work inside a virtual environment — python3 -m venv ~/venv && source ~/venv/bin/activate. Bookworm blocks system-wide pip install by design.
  • Enable the buses you need with sudo raspi-config → Interface Options (I²C, SPI, Serial, Camera).
  • Develop over VS Code Remote-SSH so you edit on your laptop but run on the Pi.

Required libraries

LibraryWhy it is neededInstall
Python 3.11+Runtime for the analysis, training and service code.sudo apt install python3 python3-venv python3-pip
OpenCV 4.10+Frame capture, colour conversion, drawing and classical CV operators.pip install opencv-python
PyTorch 2.4+Model definition, autograd and GPU training.pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
Ultralytics YOLO 8.3+Training and inference API for YOLOv8/v11 detectors.pip install ultralytics
FastAPI + Uvicorn 0.115+Typed async REST API with automatic OpenAPI docs.pip install fastapi uvicorn[standard]
SQLite 3.45+Zero-configuration embedded database for local logs.Bundled with Python (`import sqlite3`)
Picamera2 0.3.20+libcamera-based capture API for Pi Camera modules.sudo apt install python3-picamera2

Block Diagram

The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.

Number-Plate Gate Logger — system block diagramFunctional block diagram of the Number-Plate Gate Logger system. CaptureTrigger + cameravehicle in positionIR (night)illuminationReadDetect platelocalise regionOCRread characters + confDecideWhitelistknown vehicle?Gate / fallbackopen or humanRecordLog + imageauditedrightrightnone
Number-Plate Gate Logger — system block diagram

Circuit Diagram & Wiring

Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.

Number-Plate Gate Logger — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsRaspberry Pi 4 ModelB (4 GB)5 V / 3 A USB-CPi cameraCSIPlate image captureVehicle triggerGPIOCapture-now(loop/beam)IR illuminatorGPIONight lightingGate relayGPIOOpen barrier(whitelisted)ESP32 (gate I/O)GPIOBarrier control +interlocksmicroSD/SSDLog + image store5V supplyPi power
Number-Plate Gate Logger — wiring schematic
PeripheralPeripheral pinController pinSignal
Pi cameraCSICSIPlate image capture
Vehicle triggerOUTGPIOCapture-now (loop/beam)
IR illuminatorENGPIONight lighting
Gate relayINGPIOOpen barrier (whitelisted)
ESP32 (gate I/O)UARTGPIOBarrier control + interlocks
microSD/SSDbusLog + image store
5V supply+/–Pi power

Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.

Wiring explanation

  • Trigger capture from a loop detector or IR beam when the vehicle is in the read position, rather than processing video continuously — cleaner images, less compute.
  • Add IR illumination for night plates (many plates are retroreflective and read well under IR) and control camera exposure to freeze motion.
  • Interface the gate through a relay/dry-contact to the barrier's own controller, keeping the barrier's safety interlocks (obstruction sensing) intact.
  • Position and hood the camera for a controlled, near-frontal plate view at the trigger point; geometry is half the accuracy.
  • Store images and logs on reliable local storage (SD/SSD); treat them as personal data with access control.
A USB webcam
The camera captures the plate at the trigger point; detection then OCR turns the image into characters. Photograph sourced from Wikimedia Commons — Webcam.jpg. Reused under the licence stated on that page; please check it before republishing.

System Architecture

Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.

Number-Plate Gate Logger — architecture stackLayered architecture from hardware to user interface. Hardware layerRaspberry Pi 4 Model B (4 GB) · Raspberry Pi Camera Module 3Driver layerpython · opencv · torch · ultralyticsApplication logicsampling loop · filtering · thresholds · state machinePresentation layerlocal display · serial console · logged output
Number-Plate Gate Logger — architecture stack

Working Principle

ANPR is a pipeline, and its reliability comes from doing the easy discriminative step before the hard generative one. Detection first: a lightweight object detector finds the plate's bounding box in the frame — a well-defined, robust task even in a cluttered scene. Only then does the OCR run, and it runs on a small, tightly-cropped, deskewed image of just the plate. This ordering matters enormously: a character recogniser fed a whole scene must cope with background text, varied scale and clutter and fails often, while the same recogniser fed a clean plate crop is far more accurate. Detection also lets the system normalise geometry (rotate/warp the plate to a canonical front-on view) before reading, removing much of the angle-induced error.

The OCR stage is where real-world plates fight back. Plates are read by a model that maps the cropped image to a character string, ideally one trained on plates (their fonts, spacing, regional formats) rather than generic text. Its accuracy is bounded by the input: motion blur from a moving car, glare and low contrast in bright sun, darkness and headlight flare at night, and dirt or damage on the plate itself all degrade the read. This is why the physical setup — a fast enough exposure to freeze motion, IR illumination that exploits plates' retroreflectivity at night, and a controlled approach geometry so the plate is near-frontal at the trigger point — is not optional polish but a determinant of accuracy equal to the model. The system also uses format priors (a region's plates follow patterns) to catch and correct impossible reads.

Because OCR is probabilistic, the whole system is designed around confidence and graceful failure. Every read carries a confidence, and the gate logic is gated on it: a high-confidence match to a whitelisted plate opens the gate automatically; anything below the confidence bar, or not on the whitelist, does not trigger a blind action but falls back to a human path — an intercom to a guard, a visitor-registration flow, a manual open. Near-matches (a single ambiguous character, an O/0 or 8/B confusion) are handled deliberately, either by choosing the whitelist entry within an edit-distance of one if unambiguous, or by escalating to a human. This "automate the confident majority, human-handle the uncertain minority" design is what makes ANPR useful without being dangerous — it never lets a shaky guess open a barrier or wrongly turn a resident away, and it always logs the captured image so a person can adjudicate.

ANPR also carries a duty because it is surveillance of people via their vehicles. A log of which plates passed a gate, when, is personal data that reveals movements and patterns, so responsible design keeps the plate database and the read logs access-controlled, sets an explicit retention policy (keep what the access-control purpose needs, no more), and frames the system for legitimate premises access rather than covert tracking of individuals. Combined with the accuracy honesty — that lighting, angle and plate condition impose a real ceiling and a good camera and geometry matter as much as any model — this yields a system that is convenient and well-logged where it works, safe where it is unsure, and respectful of the fact that reading plates means recording people.

The maths behind it

Two-stage recognition

plainTwo-stage recognition
frame → detector → plate box → crop+deskew → OCR → string,conf

Detection localises; OCR reads the CROP, not the frame.
Geometry normalisation (perspective warp to front-on)
before OCR removes much angle-induced error.

Confidence-gated decision

plainConfidence-gated decision
read (plate P, confidence c):

  if c > C_HI and P ∈ whitelist        → open gate, log entry
  elif c > C_HI and dist(P, whitelist)=1 (unambiguous) → open, flag
  else                                  → human fallback, log read

Never open on low confidence or a blind guess.

Near-match (edit distance) handling

plainNear-match (edit distance) handling
For read P and whitelist W:
  best = argmin_{w∈W} levenshtein(P, w)
  d    = levenshtein(P, best)

  d = 0            → exact match
  d = 1 & unique   → likely OCR slip (O/0, 8/B): accept w/ flag
  d ≥ 2 or tie     → treat as unknown → human fallback

Format priors (regional plate pattern) reject impossible reads.

Program Flowchart

The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.

Number-Plate Gate Logger — firmware flowchartControl flow through the main program loop. Vehicle trigger firesCapture frame(s)Detect plate regionOCR the plate crop(confidence)Confident and onwhitelist?Open gate; log entryHuman fallback; log readOpen gate; log entryHuman fallback; log readStore image + result
Number-Plate Gate Logger — firmware flowchart

Assembly Instructions

Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.

  1. Set up capture geometry and trigger

    Mount the camera for a controlled, near-frontal view of the plate at the point a vehicle stops, hooded against sun. Add a loop detector or IR beam to trigger capture when the vehicle is in position.

    Add IR illumination for night, and set the exposure fast enough to freeze approach motion.

  2. Build the detect-then-read pipeline

    Run a plate detector to localise and crop the plate, deskew it to a front-on view, then OCR the crop to a string with a confidence. Apply regional format priors to sanity-check the read.

  3. Wire the gate and logging

    Interface the barrier through a relay to its own controller (keeping its safety interlocks), and store every read — image, string, confidence, decision — to access-controlled local storage.

Step-by-Step Implementation Guide

Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.

  1. Decide with confidence gating and fallback

    Match the read against the whitelist with near-match handling, open the gate only on a confident (exact or unambiguous near) match, and otherwise fall back to a human — logging the image and result either way.

    pythongate-decision.py
    from Levenshtein import distance
    
    C_HI = 0.85          # confidence bar for automatic action
    
    def decide(plate, conf, whitelist):
        if conf < C_HI:
            return "human", "low confidence"          # never guess the gate open
        if plate in whitelist:
            return "open", "exact match"
        # tolerate a single unambiguous OCR slip (O/0, 8/B, ...)
        near = [w for w in whitelist if distance(plate, w) == 1]
        if len(near) == 1:
            return "open", f"near match -> {near[0]} (flagged)"
        return "human", "unknown vehicle"
    
    def handle_read(plate, conf, image, whitelist, log, gate):
        action, reason = decide(plate, conf, whitelist)
        log.append(plate=plate, conf=conf, action=action,
                   reason=reason, image=image)          # always log + image
        if action == "open":
            gate.open()
        else:
            gate.request_human()                        # intercom / visitor flow
    if conf < C_HI:Any read below the confidence bar goes straight to a human — a shaky OCR result never operates the barrier.
    if plate in whitelist:A confident exact match to an authorised vehicle opens the gate automatically — the convenient common case.
    near = [w for w in whitelist if distance(plate, w) == 1]A single unambiguous character slip (a classic O/0 or 8/B confusion) is tolerated and flagged, so common OCR errors do not needlessly turn a resident away.
    log.append(Every read — automatic or human-handled — is logged with its image, so decisions are auditable and a person can verify or correct.
    gate.request_human()The uncertain minority falls back to an intercom or visitor flow rather than a blind action, the graceful-failure design at the heart of usable ANPR.
  2. Log, store and respect privacy

    Store the image, plate, confidence and decision to access-controlled storage with an explicit retention policy, and expose logs only to authorised operators.

Complete Source Code

The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.

pythonanpr_gate.py
#!/usr/bin/env python3
"""
Number-Plate Gate Logger — Raspberry Pi ANPR

Two-stage detect-then-read pipeline, confidence-gated gate control with
human fallback, whitelist (with near-match) matching, and audited,
privacy-aware logging with captured images.
"""
import time, cv2
from Levenshtein import distance
from ultralytics import YOLO          # plate detector (fine-tuned)
from plate_ocr import read_plate      # OCR model returning (text, conf)

C_HI = 0.85
detector = YOLO("plate_detect.pt")

def capture():
    # triggered by loop/beam when a vehicle is in position
    return picam_capture()            # returns a BGR frame

def detect_and_read(frame):
    res = detector(frame, verbose=False)[0]
    if not len(res.boxes):
        return None, 0.0, None
    # take the most confident plate box
    box = max(res.boxes, key=lambda b: float(b.conf))
    x1, y1, x2, y2 = map(int, box.xyxy[0])
    crop = frame[y1:y2, x1:x2]
    crop = deskew(crop)               # warp to a front-on view
    text, conf = read_plate(crop)     # OCR the clean crop
    return normalise(text), conf, crop

def decide(plate, conf, whitelist):
    if plate is None or conf < C_HI:
        return "human", "low confidence / no plate"
    if plate in whitelist:
        return "open", "exact match"
    near = [w for w in whitelist if distance(plate, w) == 1]
    if len(near) == 1:
        return "open", f"near match -> {near[0]} (flagged)"
    return "human", "unknown vehicle"

def main(whitelist, gate, db):
    while True:
        wait_for_vehicle_trigger()               # loop/beam
        set_ir(is_dark())
        frame = capture()
        plate, conf, crop = detect_and_read(frame)
        action, reason = decide(plate, conf, whitelist)

        db.log(plate=plate, conf=conf, action=action,
               reason=reason, image=crop, ts=time.time())   # audit + image
        if action == "open":
            gate.open()                          # barrier keeps its interlocks
        else:
            gate.request_human()                 # intercom / visitor flow
        db.enforce_retention()                   # purge beyond policy

if __name__ == "__main__":
    main(load_whitelist(), Gate(), PlateDB())
def detect_and_read(frame):Runs detection first to find and crop the plate, then OCRs only that clean, deskewed crop — the two-stage ordering that makes the read reliable.
box = max(res.boxes, key=lambda b: float(b.conf))Picks the most confident plate region when several are found, avoiding reading a reflection or a background sign.
crop = deskew(crop) # warp to a front-on viewNormalises the plate's geometry before OCR, removing much of the error a tilted or angled plate would cause.
if plate is None or conf < C_HI:No plate or low confidence means a human handles it — the gate is never operated on an uncertain read.
db.enforce_retention() # purge beyond policyOld records are purged per the retention policy, so the system keeps only the movement data its access-control purpose needs — privacy by design.

Configuration & Calibration

Configuration steps

  • Set the confidence bar (C_HI), the whitelist, and regional plate-format priors.
  • Configure the camera exposure/IR and the vehicle trigger for your gate geometry.
  • Set the retention policy and access controls for the plate database and image logs.
  • Configure the gate interface and ensure the barrier's own safety interlocks remain active.

Calibration procedure

An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.

  1. Geometry and exposure

    Tune camera position, angle and exposure at the trigger point until day plates are captured sharp and near-frontal; verify IR gives readable night plates.

  2. Confidence bar

    Set C_HI by reviewing real captures: high enough that wrong-opens are ~zero, low enough that most known vehicles auto-open.

  3. Whitelist / near-match

    Validate that exact and single-slip near-matches behave as intended and that ambiguous cases go to a human.

Dataset, Model & Training

Dataset

ANPR uses two learned components: a plate detector and a character recogniser. Both benefit from data matching your region's plates and your camera's conditions (angle, night IR), so fine-tuning on locally-captured plates markedly improves accuracy over a generic model.

Regional plate formats (character counts, allowed patterns) act as strong priors that catch impossible reads.

DatasetSizeLicenceUse here
Open ANPR / plate datasetsThousands–tens of thousandsVaries (check per set)Base plate detection + OCR
Your-gate capture setHundreds–thousandsYour own footageFine-tune to camera, angle, night
Synthetic platesGeneratedSelf-generatedAugment character coverage/formats

Data preprocessing

  • Crop to the detected plate box and deskew/warp to a canonical front-on rectangle.
  • Normalise contrast (and handle IR imagery for night), then resize to the OCR model's input.
  • Apply regional format priors to validate/repair the character string.
Number-Plate Gate Logger — ML pipelineFrom raw data through training to deployed inference. 1Trigger + capturevehicle in position2Detect plateobject detector3Deskew cropfront-on warp4OCRchars + confidence5Format priorvalidate/repair6Decide + loggate / human
Number-Plate Gate Logger — ML pipeline

Model architecture

A compact object detector (e.g. a small YOLO) localises the plate; a sequence recogniser (CNN + CTC, or a small transformer OCR) reads the characters from the crop.

On a Raspberry Pi, use lightweight/quantised models and trigger inference only on a vehicle event to stay real-time.

Layer / stageShape or configurationPurpose
Detectorsmall YOLO (plate class)Localise the plate region robustly
Rectifyperspective warpFront-on normalisation before OCR
OCRCNN + CTC / small OCR transformerRead variable-length plate strings
Priorsregional format regexReject/repair impossible reads

Hyperparameters

HyperparameterValueWhy
detector input~640 pxBalance speed and small-plate recall
OCR input~normalised 32×128Standard plate-crop size
C_HI (confidence bar)~0.85Trade auto-open rate vs wrong-open risk
near-match edit distance1Tolerate a single unambiguous OCR slip

Training process

  • Fine-tune the detector on plates in your scene geometry and lighting; train/fine-tune the OCR on plate crops including night-IR imagery.
  • Augment with blur, glare, rotation and partial occlusion so the models are robust to real approach conditions.
  • Validate on held-out real gate captures, tracking read accuracy separately for day and night.

Evaluation, Metrics & Deployment

The decisive metrics are end-to-end plate-read accuracy and, operationally, the auto-open rate versus the wrong-open rate.

MetricValueWhat it tells you
Plate read accuracy (day)~95%+Exact-string accuracy on good day captures
Plate read accuracy (night)lowerIR/exposure dependent; the hard case
Auto-open ratetarget high for knownFraction of known vehicles handled without a human
Wrong-open ratetarget ~0The costly error — gated hard by confidence

Figures from the reference training run described above — reproduce them before trusting your own changes.

Read accuracy by condition (illustrative)Why lighting and geometry dominate ANPR accuracy. Good day, frontal97 %Angle/glare82 %Night (no IR)55 %Night (with IR)88 %
Read accuracy by condition (illustrative)

Deployment

  • Run detection + OCR on the Pi triggered by a vehicle event; keep models quantised for real-time performance.
  • Keep the plate database and image logs on access-controlled local storage with enforced retention.
  • Provide a human-in-the-loop path for low-confidence/unknown reads and a way to correct/label captures to improve the models.

Inference example

pythonread.py
# End-to-end read for one capture (detect -> deskew -> OCR -> validate).
def read(frame, region_regex):
    box = detect_plate(frame)                 # localise
    if box is None:
        return None, 0.0
    crop = deskew(frame[box.slice])           # front-on warp
    text, conf = ocr(crop)                    # chars + confidence
    text = repair_with_prior(text, region_regex)   # format validation
    return text, conf

Testing Procedure & Expected Output

Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.

TestWhat you should see
Known plate, good day lightRead confidently, gate auto-opens, logged with image
Known plate with one OCR slipNear-match accepted and flagged; gate opens
Unknown plateHuman fallback; read logged with image
Low-confidence/blurred readNo auto action; falls back to human
Night captureIR gives a readable plate; day-only model may need night data
Check retention/accessOld records purged; logs only accessible to authorised operators

Bench-test checklist. If a row fails, stop and fix it before moving on.

Expected output

The dashboard shows a log of entries/exits with plate, confidence, time, decision and a captured image, and lets an operator handle fallbacks and correct reads.

jsongate-log.json
{
  "plate": "MH12AB1234",
  "confidence": 0.93,
  "action": "open",
  "reason": "exact match",
  "time": "2026-07-27T09:02:41",
  "image": "/logs/20260727-090241.jpg"
}

A confident exact match auto-opens for a resident and is logged with its image; a low-confidence or unknown read would instead route to a human, still logged, never blindly acted on.

A wall-mounted CCTV surveillance camera
Confident whitelisted reads open the barrier automatically while uncertain ones fall back to a human — every read logged. Photograph sourced from Wikimedia Commons — CCTV camera.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Poor read accuracy

Likely cause. Bad geometry, blur, glare or night without IR

Fix. Fix camera angle/exposure; add IR; trigger capture when the vehicle is in position

Wrong vehicle let in

Likely cause. Confidence bar too low or near-match too loose

Fix. Raise C_HI; require unambiguous near-match; add format priors

Residents often sent to human

Likely cause. Confidence bar too high or plates dirty

Fix. Tune C_HI; improve capture; add their plates as captured and label corrections

OCR confuses O/0, 8/B

Likely cause. Inherent character ambiguity

Fix. Use plate-format priors and single-edit near-matching; train on more examples

Privacy concern

Likely cause. Unbounded retention / open access to logs

Fix. Set explicit retention, purge automatically, restrict log access to authorised operators

The Python script crashes with "externally-managed-environment" on pip install

Likely cause. Raspberry Pi OS Bookworm marks the system Python as managed by apt, and refuses global pip installs.

Fix. Create and activate a virtual environment — python3 -m venv ~/venv && source ~/venv/bin/activate — and install there. Use --system-site-packages if you also need apt-installed modules such as picamera2.

The Pi reboots or shows a lightning-bolt icon under load

Likely cause. Under-voltage. The supply sags below 4.63 V when the CPU and peripherals ramp up.

Fix. Use the official supply for your model (5 V 3 A for Pi 4, 5 V 5 A for Pi 5) and a short, thick USB-C cable. Check with vcgencmd get_throttled — anything other than 0x0 means power problems.

Performance Optimisation

  • Trigger inference on a vehicle event, not on continuous video, to save compute and get cleaner frames.
  • Detect then OCR the crop; do not OCR whole frames.
  • Use quantised/lightweight models on the Pi for real-time reads.
  • Store images efficiently and enforce retention so storage does not grow unbounded.
  • Pin the hot loop to one core with taskset and leave the others free for the OS.
  • Prefer MJPEG over raw YUY2 when capturing from USB cameras — the decode cost is far lower than the USB bandwidth cost.
  • Log to a tmpfs RAM disk and flush to the SD card once a minute; per-sample SD writes are what kills cards.
  • Run the service under systemd with Restart=always so a crash never means a dead deployment.
  • For battery builds use deep sleep between samples: an ESP32 drops from ~160 mA awake to about 10 µA asleep, which is the difference between days and months of runtime.
  • Profile before optimising — print micros() deltas around each stage and fix the slowest one first.

Safety Precautions

  • Plate/movement data is personal data — access-control it, set explicit retention, and use it for legitimate premises access, not covert tracking.
  • Keep the barrier's own safety interlocks (obstruction sensing) active; ANPR only requests open/close.
  • Never auto-act on a low-confidence read; always provide a human fallback and an audit image.
  • Comply with local ANPR/CCTV and data-protection law, including signage where required.
  • Mains voltage kills. Anything on the load side of the relay is at 230 V. Do not work on a powered circuit, and never leave exposed mains wiring on a bench where someone could touch it.
  • Keep at least 6 mm of creepage between the mains and low-voltage sides of any board you make, and never route mains tracks under the microcontroller.
  • Have a qualified electrician do the final installation into a consumer unit or wall fitting. In most jurisdictions this is a legal requirement, not a suggestion.
  • Fit an RCD/RCBO upstream and fuse the load appropriately for its rating.
  • Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
  • Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
  • Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.

Maintenance

  • Clean the camera/IR optics; dirt and glare degrade reads.
  • Re-tune geometry/exposure seasonally and after any camera movement.
  • Retrain/fine-tune the models with corrected captures, especially for night.
  • Review retention/access and purge as policy requires.
  • Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
  • Rotate the microSD card annually and keep an image of the working system. Cards used as loggers wear out silently.
  • Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
  • Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.

Future Improvements & Upgrades

A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.

  • Add make/model/colour as corroborating features to catch cloned plates.
  • Add a resident self-service portal to register/deregister vehicles.
  • Add two-camera capture (front/rear) for higher read reliability.
  • Federate multiple gates with a shared, access-controlled vehicle registry.
  • Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
  • Add connectivity — an ESP32 and an MQTT publish turn a local gadget into something you can graph, alert on and analyse over months.
  • Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
  • Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
  • Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
  • Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.

Frequently Asked Questions

Why detect the plate before reading it?

Feeding OCR a whole noisy frame is unreliable. Localising and cropping the plate first — and warping it front-on — gives the recogniser a clean input and dramatically improves accuracy.

What happens when the read is uncertain?

It falls back to a human. The gate only auto-opens on a confident exact (or single-slip near) match to the whitelist; anything else goes to an intercom or visitor flow, always logged with the captured image.

Why is night harder?

Low light and headlight glare wreck ordinary captures. IR illumination exploits plates' retroreflectivity and a fast exposure freezes motion — geometry and lighting matter as much as the model.

Isn't this surveillance?

It records vehicle movements, which is personal data, so it must be run responsibly: access-controlled logs, explicit retention, legitimate access-control purpose, and compliance with local law — not covert tracking of individuals.

Can someone beat it with a cloned plate?

A plate alone is spoofable, which is why higher-security setups corroborate with make/model/colour or pair ANPR with a second credential, and why every read is logged with an image for human review.

References & Learning Resources

These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.

  1. Automatic number-plate recognition — overviewReference
  2. Optical character recognitionReference
  3. YOLO object detectionUltralytics
  4. CTC sequence recognition (OCR)Reference
  5. ANPR and data protection considerationsICO