Skip to content
Tomer Naydnov
← All workEARLIER ENGINEERING / SOURCE STUDY

THE RULES BEHIND THE SOFTWARE

License Plate Recognition

A computer-vision pipeline that follows vehicles from motion detection to plate recognition and operator playback.

ENGINEERING / EXPLAINED
TRACK 04PLATE
01Motion

Find candidates

02Track

Keep an identity

03Read

Crop → OCR

04Refine

Compare readings

Code-native explanation of the implementation. Illustrative data.

CONTEXT
University capstone
MY ROLE
Developer · computer vision & pipeline integration
TIMELINE
Nov 2024 - Jul 2025
EVIDENCE
Source reviewed · illustrative diagrams

AT A GLANCE

One frame, four decisions

Movement becomes a tracked vehicle, a cropped plate and a refined reading. OpenCV, YOLO and PaddleOCR connect through Python services, Redis queues and a desktop viewer, so an operator can inspect the recognition path.

My contribution +

My development work covered motion detection, data preparation, model training and fine-tuning, and recognition-pipeline integration.

WHAT THE SYSTEM HANDLES

The interesting parts.

01

Find the movement. Keep the identity.

Optical flow, vehicle detection and centroid tracking turn consecutive frames into persistent vehicle tracks.

Implementation details
  • Farneback flow with magnitude/area filtering
  • Vehicle detections filtered by motion overlap and class
  • Centroid association and disappearance handling
02

Give each plate a second look.

Associate a plate with its vehicle, prepare the crop for OCR, then retain stronger repeated readings.

Implementation details
  • Spatial plate-to-vehicle association
  • CPU PaddleOCR with image preprocessing
  • Format checks and look-alike character correction
  • Repeated equal-or-better-confidence readings mark a track stable
03

Let the stages run at different speeds.

Video acquisition, edge inference, OCR and desktop display communicate through queues and HTTP.

Implementation details
  • Redis input/output queues
  • Bounded in-process worker queue with frame dropping
  • Separate OCR service receiving a cropped image
  • PyQt operator playback controls
04

Inspect the whole recognition path.

The repository preserves annotated frames and evaluation scripts for component detections and complete plate results.

Implementation details
  • Ground-truth bounding-box annotations
  • Precision/recall/F1 computation
  • Exact and explicitly thresholded partial plate matching

STRUCTURE & JUDGMENT

How the parts fit.

File / RTSP input

User-supplied video; OpenCV acquisition.

→ Video service

Video service

FastAPI controls and nominal4fps frame acceptance.

→ Redis frame_queue

Redis frame_queue

Pickled frames; queue itself has no configured bound.

→ Edge worker queue

Edge worker queue

30 in-process slots and four workers.

→ Motion + vehicle tracks

Motion + vehicle tracks

Farneback motion, YOLO vehicle filtering, centroid matching.

→ Plate association

Plate association

YOLO plate candidates aligned to tracked vehicles.

→ OCR service

OCR service

JPEG crop over HTTP → preprocessing → PaddleOCR → format validation.

→ Recognition state

Recognition state

Equal-or-higher-confidence text and repeated observations.

→ Redis visual_frame_queue

Redis visual_frame_queue

Annotated800×600 output frames.

→ PyQt viewer

PyQt viewer

Playback controls and annotated video display.

→ Video service
  • Python
  • OpenCV / Farneback optical flow
  • Ultralytics YOLO11
  • PaddleOCR2.10.0 / PaddlePaddle2.6.2
  • NumPy / SciPy
  • FastAPI
  • Redis
  • Docker Compose
  • PyQt5

Use motion as a gate before new vehicle inference.

The active path skips new YOLO vehicle inference when it has no motion candidates.

WHY IT MATTERSA missed motion region can suppress a useful vehicle candidate. Existing tracks can still lead to plate inference while they age out.

Preserve vehicle identity across frames.

Centroid tracking lets repeated plate crops contribute to one vehicle record instead of treating each frame independently.

WHY IT MATTERSDistance/disappearance thresholds can confuse occlusion or nearby vehicles; no tracking-quality benchmark is published.

Split inference and display into service boundaries.

Acquisition, edge processing, OCR and desktop rendering have different costs and control needs.

WHY IT MATTERSSerialization, queue backlog and synchronous OCR requests introduce extra failure and latency points; no end-to-end latency results were measured.

Check likely plate formats after OCR.

Pattern checks and look-alike substitutions reject or correct some raw OCR strings.

WHY IT MATTERSA valid format is not proof of the correct plate; generic patterns and correction order can bias ambiguous results.

Expose operator controls around the pipeline.

Loading, pausing, resuming and skipping footage support inspection of recognition behavior.

WHY IT MATTERSThe current file picker and container paths need coordination; the UI updates status even when API errors are only logged.

Scope, limitations & what I would revisit

  • No runtime or accuracy claim from this audit. Source-only review; models were not loaded, services were not started and evaluation scripts were not executed. No source-published model/end-to-end accuracy result found.
  • Unauthorized-vehicle alerts are not wired into the current service path. The current edge endpoint always calls visualize(frame, True). List authorization exists in a stale legacy path. Describe the current system as plate recognition and operator visualization, with authorization as earlier prototype logic.
  • ROI, direction classification and fusion helpers are historical/experimental. RegionAdjuster is unused by current prediction; image fusion, multiple-threshold preprocessing and weighted majority voting are defined but not called by the current OCR path.
  • Four workers share sequential model/tracker state. All workers receive one EdgeService; its prev_frame and tracker state can be touched across frames. Tracker methods lock portions of state, but EdgeService.lock is not used around prediction. Ordering and concurrency behavior need runtime evaluation.
  • Queue and network behavior are prototype-grade. The Python queue is bounded, but Redis input/output lists are not; the poller busy-loops and OCR HTTP calls have no timeout. Do not describe the complete system as fully bounded or fault tolerant.
  • Startup clears Redis globally. Both video startup and the new-architecture tester call flushall. Any future local execution must use an isolated Redis container and ports.
  • Evaluation contracts need reconciliation. New tester expects tracked_plates, but no active production caller invokes log_results; older tests import missing classes or call superseded signatures. Syntax parsing passed but does not prove tests pass.
  • Videos and reproducible training history are absent. Full videos are ignored, model weights are tracked, and this revision has no training script/configuration or held-out benchmark report. My development, data preparation and training work are described above; this source snapshot does not provide a reproducible training record.
  • Desktop paths and container mounts differ. A path picked on Windows is sent directly to the service, while Compose mounts only ./recordings at /app/recordings. A future run must map/copy only authorized local fixtures.