Hurricane OCR - Thai License Plate Recognition π
π Model Description
Hurricane OCR is a high-performance OCR model specifically fine-tuned for reading Thai license plates. Built on top of SCB-10X's Typhoon-OCR 1.5 (2B) using LoRA (Low-Rank Adaptation), this model efficiently extracts structured information from license plate images with 86.7% accuracy.
π― Extracted Fields
| Field | Description | Example |
|---|---|---|
| π€ Plate Number | Full license plate number | ΰΈΰΈ 1234 |
| π Characters | Thai characters only | ΰΈΰΈ |
| π’ Digits | Numeric digits only | 1234 |
| π Province | Province name in Thai | ΰΈΰΈ£ΰΈΈΰΈΰΉΰΈΰΈΰΈ‘ΰΈ«ΰΈ²ΰΈΰΈΰΈ£ |
π Quick Start
Installation
pip install transformers peft torch pillow
Basic Usage
import torch
from transformers import AutoProcessor, AutoModelForVision2Seq
from peft import PeftModel
from PIL import Image
# Load processor and base model
base_model_name = "scb10x/typhoon-ocr1.5-2b"
processor = AutoProcessor.from_pretrained(base_model_name)
base_model = AutoModelForVision2Seq.from_pretrained(
base_model_name,
torch_dtype=torch.float16,
device_map="auto"
)
# Load LoRA adapter
model = PeftModel.from_pretrained(base_model, "Rattatammanoon/hurricane-ocr-tlpr-v1-LoRA")
model.eval()
# Process license plate image
image = Image.open("license_plate.jpg").convert("RGB")
pixel_values = processor(images=image, return_tensors="pt").pixel_values.to(model.device)
# Generate OCR output
with torch.no_grad():
generated_ids = model.generate(
pixel_values,
max_length=512,
num_beams=4,
early_stopping=True
)
text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(text)
Batch Processing
# Process multiple plates at once
images = [Image.open(f"plate{i}.jpg").convert("RGB") for i in range(5)]
pixel_values = processor(images=images, return_tensors="pt").pixel_values.to(model.device)
with torch.no_grad():
generated_ids = model.generate(pixel_values, max_length=512, num_beams=4)
texts = processor.batch_decode(generated_ids, skip_special_tokens=True)
for i, text in enumerate(texts):
print(f"Plate {i+1}: {text}")
π Training Details
| Parameter | Value |
|---|---|
| Base Model | scb10x/typhoon-ocr1.5-2b |
| Fine-tuning Method | LoRA (Low-Rank Adaptation) via PEFT |
| Training Data | 304 Thai license plate images |
| Accuracy | 86.7% |
| Languages | Thai (primary), English (digits) |
| Framework | PyTorch + Transformers + PEFT |
| Training Date | December 2025 |
Performance Metrics
- β Character Accuracy: 86.7%
- β Optimized for: Thai license plates (new & old formats)
- β Best Performance: Clean, cropped plate images (200-400px width)
π Output Format
The model outputs structured markdown text:
**Plate Number:** ΰΈΰΈ 1234
**Characters:** ΰΈΰΈ
**Digits:** 1234
**Province:** ΰΈΰΈ£ΰΈΈΰΈΰΉΰΈΰΈΰΈ‘ΰΈ«ΰΈ²ΰΈΰΈΰΈ£
You can easily parse this output:
import re
# Parse the OCR output
lines = text.strip().split('\n')
result = {}
for line in lines:
if '**' in line:
key, value = line.split(':', 1)
key = key.strip('*').strip()
result[key] = value.strip()
print(result)
# {'Plate Number': 'ΰΈΰΈ 1234', 'Characters': 'ΰΈΰΈ', ...}
π§ Advanced Usage
Custom Generation Parameters
Fine-tune the OCR output quality:
generated_ids = model.generate(
pixel_values,
max_length=512,
num_beams=5, # Increase for better quality (slower)
temperature=0.7, # Lower = more deterministic
top_p=0.9,
repetition_penalty=1.2,
early_stopping=True
)
Integration with Detection Pipeline
Combine with a license plate detector (e.g., YOLOv8):
from ultralytics import YOLO
# 1. Detect license plate region
detector = YOLO("path/to/plate_detector.pt")
results = detector("car_image.jpg")
# 2. Extract and process each detected plate
for result in results:
for box in result.boxes:
# Crop plate region
x1, y1, x2, y2 = map(int, box.xyxy[0])
plate_crop = image.crop((x1, y1, x2, y2))
# 3. Run Hurricane OCR
pixel_values = processor(images=plate_crop, return_tensors="pt").pixel_values
generated_ids = model.generate(pixel_values)
text = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(f"Detected plate: {text}")
π‘ Performance Tips
| Tip | Description |
|---|---|
| β Image Size | Resize plates to 200-400px width for best results |
| β Image Quality | Use clear, well-lit images |
| β Preprocessing | Crop tightly around the plate |
| β Batch Processing | Process multiple images at once for efficiency |
| β οΈ Limitations | Optimized for Thai plates only |
Recommended Preprocessing
from PIL import Image, ImageEnhance
def preprocess_plate(image_path):
img = Image.open(image_path).convert("RGB")
# Resize if needed (maintain aspect ratio)
if img.width > 400:
ratio = 400 / img.width
new_size = (400, int(img.height * ratio))
img = img.resize(new_size, Image.LANCZOS)
# Enhance contrast (optional)
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.2)
return img
π Use Cases
- π Parking Management Systems
- π¦ Traffic Monitoring & Analysis
- π’ Access Control Systems
- π Vehicle Fleet Management
- π Law Enforcement Applications
β οΈ Limitations
- Designed specifically for Thai license plates (both old and new formats)
- Performance may degrade with:
- Very low resolution images
- Heavily obscured or damaged plates
- Extreme lighting conditions
- Non-standard plate formats
π€ Contributing
Contributions are welcome! If you have suggestions or improvements:
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
π License
This model is licensed under Apache 2.0. See LICENSE for details.
- β Commercial use allowed
- β Modification allowed
- β Distribution allowed
- β Must include license and copyright notice
π Citation
If you use Hurricane OCR in your research or project, please cite:
@misc{hurricane-ocr-v1-2025,
author = {Rattatammanoon},
title = {Hurricane OCR - Thai License Plate Recognition},
year = {2025},
publisher = {Hugging Face},
journal = {Hugging Face Model Hub},
howpublished = {\url{https://huggingface.co/Rattatammanoon/hurricane-ocr-tlpr-v1-LoRA}}
}
π Acknowledgments
This project builds upon excellent work from:
- Base Model: SCB-10X Typhoon-OCR 1.5 (2B)
- Framework: Hugging Face Transformers
- PEFT Library: PEFT (Parameter-Efficient Fine-Tuning)
- Training Dataset: Custom Thai license plate dataset
Special thanks to the SCB-10X team for developing Typhoon-OCR! π
π§ Contact & Support
- π¨βπ» GitHub: @topzson
- π Issues: Report here
- π¬ Discussions: HuggingFace Discussions