Automatic license plate recognition using YOLOv8 and EasyOCR, with ROI filtering, FIFO output, and screenshot support.
Project description
ParkOCR
ParkOCR is a Python library for automatic license plate recognition using YOLOv8 for detection and OCR for text recognition. It is designed to work with RTSP streams (e.g., IP cameras), webcams, or video files.
✨ Features
- YOLOv8 for plate localization (supports
n,s,m,l,xmodels). - Multiple OCR backends (EasyOCR or RapidOCR).
- Two installation options: lite (~90MB) or full (~950MB).
- ROI filtering: only detect plates inside a defined region.
- Headless mode (no window display).
- Prevents freezing on the same consecutive plate.
- Optional FIFO output for inter-process communication.
- Screenshot saving:
screenshot=None: disabledscreenshot="full": saves full framescreenshot="roi": saves only the region of interest
- Performance optimizations (v0.2.0+):
- Async processing with threading (non-blocking detection)
- Camera buffer clearing (reduces latency)
- Frame downscaling for faster inference
- Performance monitoring and logging
📦 Installation
ParkOCR requires Python 3.12+.
Lite Version (Recommended for CPU)
Lightweight installation using ONNX Runtime (~90MB total):
pip install parkocr[lite]
Best for:
- Systems without GPU
- Low-resource environments
- Docker containers
- Edge devices
Full Version
Complete installation using PyTorch (~950MB total):
pip install parkocr[full]
Best for:
- Systems with GPU
- Maximum accuracy requirements
- Development and experimentation
Check Installed Backend
from parkocr import get_available_backend
print(get_available_backend()) # 'lite', 'full', or 'none'
✅ Requirements
- Python 3.12 or higher
- OpenCV (installed automatically)
- Lite: ONNX Runtime + RapidOCR
- Full: PyTorch + EasyOCR + Ultralytics
🚀 Usage
Basic example
from parkocr.detector import Detector
detector = Detector(
rtsp_url="rtsp://user:password@192.168.0.100:554/onvif1",
model_size=0, # 0=nano, 1=small, 2=medium, 3=large, 4=xlarge
headless=True,
screenshot="roi", # options: None, "full", "roi"
)
detector.run()
With FIFO output
detector = Detector(
rtsp_url="rtsp://user:password@192.168.0.100:554/onvif1",
fifo_output="/tmp/plates_fifo",
headless=True
)
detector.run()
Now another process can read detected plates from /tmp/plates_fifo.
With callback
def on_plate(plate):
print("Detected plate:", plate)
detector = Detector(
rtsp_url="rtsp://user:password@192.168.0.100:554/onvif1",
on_detect=on_plate,
headless=True
)
detector.run()
🚀 Performance Optimization
CPU-Only Systems (No GPU)
For systems without dedicated GPUs, use these settings for optimal performance:
detector = Detector(
rtsp_url="rtsp://camera_url",
model_size=0, # Use nano model (fastest)
inference_scale=0.4, # Downscale to 40% (faster inference)
buffer_clear_frames=3, # Clear 3 frames from buffer
process_interval_s=0.5, # Process every 0.5s
headless=True, # Disable display for production
enable_performance_logging=True # Monitor bottlenecks
)
Expected Performance on CPU:
- Intel i5-10400 / Ryzen 5 3600: ~500-800ms per detection
- Intel i7-12700 / Ryzen 7 5800X: ~300-500ms per detection
Systems with GPU
For GPU-enabled systems, you can use higher quality settings:
detector = Detector(
rtsp_url="rtsp://camera_url",
model_size=2, # Medium model (better accuracy)
inference_scale=1.0, # Full resolution
buffer_clear_frames=1, # Minimal buffer clearing
process_interval_s=0.3, # Faster processing
)
Note: GPU support will be added in a future version. Current version (0.2.0) is CPU-optimized.
Performance Tips
- Reduce
inference_scale: Lower values (0.3-0.5) significantly speed up YOLO at minimal accuracy cost - Use smaller model:
model_size=0(nano) is 3-5x faster than larger models - Increase
process_interval_s: If you don't need real-time processing, increase to 1.0-2.0s - Enable
buffer_clear_frames: Reduces latency by skipping old frames (2-4 recommended) - Use
headless=True: Disabling display saves CPU cycles - Optimize ROI: Smaller ROI = less area to process
- Enable logging: Use
enable_performance_logging=Trueto identify bottlenecks
Common Issues
Symptom: High CPU usage, system freezes
Solution: Reduce inference_scale to 0.3-0.4, use model_size=0, increase process_interval_s
Symptom: Detection lag (detecting plates that already passed)
Solution: Increase buffer_clear_frames to 3-5
Symptom: Missing some plates
Solution: Decrease process_interval_s, reduce buffer_clear_frames, or increase inference_scale
⚙️ Parameters
Core Parameters
- rtsp_url (str): RTSP stream, file path, or webcam index.
- model_size (int): 0=
n, 1=s, 2=m, 3=l, 4=x. Larger = more accurate, slower. - conf_thresh (float): YOLO detection confidence threshold (default: 0.5).
- roi (tuple[int, int, int, int] | None): Region of interest (x1, y1, x2, y2). Defaults to central ROI.
- headless (bool): Disable display windows and overlays (default: False).
- window_size (tuple[int, int]): Window size for display (default: 1280x720).
Processing Parameters
- process_interval_s (float): Seconds between detection cycles (default: 1.0).
- freeze_seconds (float): How long to display detection result, non-blocking (default: 0.5).
- ocr_langs (list[str]): OCR languages for EasyOCR (default: ["en"]).
- min_ocr_conf (float): Minimum OCR confidence (default: 0.30).
Output Parameters
- on_detect (callable): Callback called with detected plate text.
- fifo_output (str | None): Path to FIFO file to send plates.
- screenshot (str | None):
None,"full", or"roi".
Performance Parameters (v0.2.0+)
-
inference_scale (float): Scale factor for frame downscaling before YOLO (0.0-1.0, default: 0.5). Lower values = faster inference but less accurate. Recommended: 0.3-0.5 for CPU, 1.0 for GPU.
-
buffer_clear_frames (int): Number of frames to skip from camera buffer before processing (default: 2). Helps reduce latency caused by buffered frames. Recommended: 2-4 for most setups.
-
enable_performance_logging (bool): Enable detailed timing logs for each detection stage (default: False). Useful for identifying performance bottlenecks.
Backend Parameters (v0.3.0+)
- backend (str | None): Force specific backend ('lite' or 'full'). If None, auto-detects based on installed packages. Use this to explicitly select a backend when both are installed.
📂 Project structure
parkocr/
├── __init__.py
├── detector.py # Main Detector class
├── backends.py # Backend abstraction (ONNX/PyTorch)
README.md
pyproject.toml
📝 License
MIT © 2025 João Luiz Thomazetti
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
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 parkocr-0.3.1.tar.gz.
File metadata
- Download URL: parkocr-0.3.1.tar.gz
- Upload date:
- Size: 11.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ef12bd4f274d7c3f7fba6f80c65225a8c3ba8d250710b1ef0a6403caa471880
|
|
| MD5 |
bf5bab3a32b00bf441af71706b6baa7f
|
|
| BLAKE2b-256 |
4035581845549a5f3165a8cfb3d9afec834825a9a9bccfc4a2be18bb5c0c6d72
|
File details
Details for the file parkocr-0.3.1-py3-none-any.whl.
File metadata
- Download URL: parkocr-0.3.1-py3-none-any.whl
- Upload date:
- Size: 11.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0af9fb84302c24c1ea4efc8422f44780bf6c4606b78c645a35ea1f86575cd58e
|
|
| MD5 |
b559b98daaabf34d221e45e530b7ca2e
|
|
| BLAKE2b-256 |
a7acf20748b8841ad308befaeed99afcda4cd2c748eb58a4217974632f53ef5c
|