No project description provided
Project description
🚘 License Plate Annotation Demo Filter
License Plate Annotation Demo Filter is a lightweight OpenFilter-based demo filter that overlays OCR-processed license plate text and cropped plate images onto video frames.
It integrates seamlessly with:
✨ 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) - 🧩 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.
🧰 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 | "cropped_main" |
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 |
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 License Plate Annotation 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file filter_license_annotation_demo-0.1.3-py3-none-any.whl.
File metadata
- Download URL: filter_license_annotation_demo-0.1.3-py3-none-any.whl
- Upload date:
- Size: 10.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c81fca72ca0a81b29edcc33dac48fe0b5bf676aa60de15cfa771b5264d66e298
|
|
| MD5 |
5bac38ab994c53dd332be8f9657d82b9
|
|
| BLAKE2b-256 |
552c18f070c0dd1322bb6a05a850a5df5c0e50c2fbf945231880058e71b90892
|