Skip to main content

No project description provided

Project description

🚘 Plate ID OCR

Plate ID OCR is a lightweight OpenFilter-based filter that overlays OCR-processed license plate text and cropped plate images onto video frames.

It integrates seamlessly with:

PyPI version License: Apache 2.0 Build Status


✨ Features

  • 🖍️ Overlays OCR license plate text on the main frame
  • 🖼️ Displays cropped license plate image as a top-left inset
  • 🧠 Filters OCR output using a regex pattern for valid plates (e.g., ABC1234)
  • 🔄 Processes all received topics and returns main first
  • 🔀 Optional pass-through of upstream non-image frames via forward_upstream_data
  • 🧩 Designed to run after detection, cropping, and OCR filters in OpenFilter pipelines
  • ⚙️ Fully configurable via CLI, code, or environment variables

📦 Installation

Install the latest version from PyPI:

pip install filter-license-annotation-demo

Or install from source:

# Clone the repo
git clone https://github.com/PlainsightAI/filter-license-annotation-demo.git
cd filter-license-annotation-demo

# (Optional but recommended) create a virtual environemnt:
python -m venv venv && source venv/bin/activate

# Install the filter
make install

🚀 Quick Start (CLI)

Run a full license plate pipeline using the CLI:

openfilter run \
	- VideoIn \
		--sources 'file://example_video.mp4!loop' \
	- filter_license_plate_detection.filter.FilterLicensePlateDetection \
	- filter_crop.filter.FilterCrop \
		--detection_key license_plate_detection \
		--detection_class_field label \
		--detection_roi_field box \
		--output_prefix cropped_ \
		--mutate_original_frames false \
		--topic_mode main_only \
	- filter_optical_character_recognition.filter.FilterOpticalCharacterRecognition \
		--topic_pattern 'license_plate' \
		--ocr_engine easyocr \
		--forward_ocr_texts true \
	- filter_license_annotation_demo.filter.FilterLicenseAnnotationDemo \
		--cropped_topic_suffix license_plate \
	- Webvis

Or:

make run

Then open http://localhost:8000 to view annotated results.

Single-process Usage Script

Run the full pipeline in one process (with safe port spacing):

WEBVIS_PORT=8002 \
VIDEO_INPUT=./example_video.mp4 \
FILTER_CROPPED_TOPIC_SUFFIX=license_plate \
FILTER_FORWARD_UPSTREAM_DATA=true \
python scripts/filter_usage.py

Open http://localhost:8002.


🧰 Using from PyPI

After installing with:

pip install filter-license-annotation-demo

You can run the filter directly in code:

Standalone

from filter_license_annotation_demo.filter import FilterLicenseAnnotationDemo

if __name__ == "__main__":
    FilterLicenseAnnotationDemo.run()

Multi-filter Pipeline

from openfilter.filter_runtime.filter import Filter
from filter_license_plate_detection.filter import FilterLicensePlateDetection
from filter_crop.filter import FilterCrop
from filter_optical_character_recognition.filter import FilterOpticalCharacterRecognition
from filter_license_annotation_demo.filter import FilterLicenseAnnotationDemo
from openfilter.filter_runtime.filters.video_in import VideoIn
from openfilter.filter_runtime.filters.webvis import Webvis

if __name__ == '__main__':
    Filter.run_multi([
        (VideoIn, dict(
            sources='file://example_video.mp4!loop',
            outputs='tcp://*:5550',
        )),
        (FilterLicensePlateDetection, dict(
            sources='tcp://localhost:5550',
            outputs='tcp://*:5552',
        )),
        (FilterCrop, dict(
            sources='tcp://localhost:5552',
            outputs='tcp://*:5554',
            detection_key='license_plate_detection',
            detection_class_field='label',
            detection_roi_field='box',
            output_prefix='cropped_',
            mutate_original_frames=False,
            topic_mode='main_only',
        )),
        (FilterOpticalCharacterRecognition, dict(
            sources='tcp://localhost:5554',
            outputs='tcp://*:5556',
            topic_pattern='license_plate',
            ocr_engine='easyocr',
            forward_ocr_texts=True,
        )),
        (FilterLicenseAnnotationDemo, dict(
            sources='tcp://localhost:5556',
            outputs='tcp://*:5558',
            cropped_topic_suffix='license_plate',
        )),
        (Webvis, dict(
            sources='tcp://localhost:5558',
        )),
    ])

🔧 Configuration

Field Type Description Example
cropped_topic_suffix str Topic with cropped plate images "license_plate"
font_scale float Font size multiplier for overlay text 1.0
font_thickness int Thickness of text stroke 2
inset_size tuple Width and height of the inset image (200, 60)
inset_margin tuple Offset from top-left corner (10, 10)
debug bool Enable verbose debug logging true
forward_upstream_data bool Forward non-image frames from upstream true

Environment variables (examples):

export FILTER_CROPPED_TOPIC_SUFFIX=license_plate
export FILTER_FORWARD_UPSTREAM_DATA=true
export FILTER_FONT_SCALE=1.2
export FILTER_INSET_MARGIN=20x10

All fields are also supported as environment variables using the FILTER_ prefix (e.g., FILTER_FONT_SCALE=1.2).


🧪 Testing

Run all tests:

make test

Run individual test files:

pytest -v tests/test_filter_license_annotation_demo.py

🧩 How It Works

Filter Role
filter-license-plate-detection Detects license plates in frames
filter-crop Crops detected license plates
filter-optical-character-recognition Applies OCR to cropped license plate images
**This Filter** Overlays cropped plate image and OCR text on main frame

OCR text is filtered using a regex (^[A-Z]{3}[0-9]{4}$). If no valid OCR is detected in the current frame, the last valid plate is reused for continuity.


🤝 Contributing

We welcome contributions! See our CONTRIBUTING.md.

Tips:

  • Format with black
  • Lint with ruff
  • Add type hints and docstrings
  • Write tests for all features
  • Sign commits using DCO (git commit -s)

📄 License

Licensed under the Apache 2.0 License.


🙏 Acknowledgements

Thank you for using the Plate ID OCR Filter!

Questions or feedback? Open an issue.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

filter_license_annotation_demo-0.1.11-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file filter_license_annotation_demo-0.1.11-py3-none-any.whl.

File metadata

File hashes

Hashes for filter_license_annotation_demo-0.1.11-py3-none-any.whl
Algorithm Hash digest
SHA256 7603461f2bdbdb3d80b5bba1f3fb51efbb844c5a56ead7981cf4a6a9d94e7f3b
MD5 989b95354523def56d6ff43f19909c66
BLAKE2b-256 4ef22275140917c4cbbf0ccc4a64dd846450af9fa2bd22e3dfb03ab0fdbc4c45

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page