Skip to content

Commit 9ce7a5b

Browse files
authored
Merge pull request #81 from ankandrew/ankandrew/country-recognition
Region recognition support
2 parents cb20d1e + 6d0e8e3 commit 9ce7a5b

63 files changed

Lines changed: 4195 additions & 1626 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ insert_final_newline = true
1010

1111
[*.py]
1212
indent_size = 4
13-
max_line_length = 100
13+
max_line_length = 120

.gitignore

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,47 @@ Desktop.ini
176176

177177
# Notebooks
178178
**/.ipynb_checkpoints/
179+
180+
# Trained models
181+
**/trained_models/
182+
183+
# Model artifacts
184+
*.keras
185+
*.h5
186+
*.hdf5
187+
*.weights.h5
188+
189+
# TensorFlow ckpts
190+
checkpoint
191+
*.ckpt
192+
*.ckpt.*
193+
*.index
194+
*.data-*
195+
196+
# TF SavedModel
197+
saved_model/
198+
**/saved_model/
199+
**/saved_model.pb
200+
**/variables/
201+
202+
# Training outputs / logs
203+
logs/
204+
**/logs/
205+
runs/
206+
tb_logs/
207+
tensorboard/
208+
209+
# ONNX related
210+
*.onnx
211+
*.ort
212+
213+
# Other Export formats
214+
*.tflite
215+
*.mlmodel
216+
*.mlpackage
217+
218+
# Accelerator caches/artifacts
219+
*.engine
220+
*.plan
221+
trt_engine_cache/
222+
tensorrt/

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.0] - 2026-03-13
9+
10+
### Added
11+
12+
- New `cct-xs-v2-global-model` and `cct-s-v2-global-model` with plate region recognition support for 65+ countries.
13+
- Optional region-aware training, validation, and inference flow, including `plate_region` dataset support.
14+
- New region evaluation metrics, including `val_region_macro_f1`, plus per-region evaluation in validation.
15+
- New CCT v2 model configs, parameterized plate configs, and focal loss support for region classification.
16+
- Inference now returns `PlatePrediction`, exposing region outputs when available.
17+
- Export pipeline improvements for multi-output models, plus support for selecting the ONNX opset version.
18+
- Expanded dataset validation and annotation checks, including region validation and warnings on unexpected columns.
19+
20+
### Changed
21+
22+
- V2 pre-trained models were trained on roughly 3x more data than the v1 generation.
23+
- V2 training now includes empty plates built from backgrounds, noise, textures, and other padded-plate negatives.
24+
- Region recognition now includes an `Unknown` class trained mainly with synthetic data.
25+
- Updated the new CCT v2 models to use `silu` instead of `gelu` to avoid export issues with some library versions.
26+
- Added the corrected `attention_layout` behavior so split projection dimensions are distributed per head instead of reusing the full `projection_dim`.
27+
- The shipped v2 `xs` and `s` pre-trained models both exceed `0.99` `val_region_macro_f1` on a held-out validation split with more than `114_000` samples.
28+
- Transformer blocks and training defaults are more configurable, including projection validation, loss weighting, and milder augmentations.
29+
- Inference now removes the pad character by default from decoded output.
30+
- TFLite export now uses LiteRT via `ai-edge-litert` following TensorFlow deprecation changes.
31+
32+
### Fixed
33+
34+
- Fixed region recognition mismatches during validation.
35+
- Fixed `EarlyStopping` metric selection when training single-head models.
36+
- Fixed learning-rate decay step calculation to account for warmup steps.
37+
838
## [1.0.2] - 2025-09-03
939

1040
### Added
@@ -62,4 +92,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6292
- Add option to visualize only predictions which have low char prob.
6393
- Add onnxsim for simplifying ONNX model when exporting.
6494

95+
[1.1.0]: https://github.com/ankandrew/fast-plate-ocr/compare/v1.0.2...v1.1.0
6596
[0.1.6]: https://github.com/ankandrew/fast-plate-ocr/compare/v0.1.5...v0.1.6

README.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
[![Documentation Status](https://img.shields.io/badge/docs-latest-brightgreen.svg)](https://ankandrew.github.io/fast-plate-ocr/)
1414
[![image](https://img.shields.io/pypi/l/fast-plate-ocr.svg)](https://pypi.python.org/pypi/fast-plate-ocr)
1515

16-
![Intro](https://raw.githubusercontent.com/ankandrew/fast-plate-ocr/4a7dd34c9803caada0dc50a33b59487b63dd4754/extra/demo.gif)
16+
![Intro](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/readme_demo.gif)
1717

1818
---
1919

@@ -27,10 +27,10 @@ The idea is to use this after a plate object detector, since the OCR expects the
2727
## Features
2828

2929
- **Keras 3 Backend Support**: Train seamlessly using **[TensorFlow](https://www.tensorflow.org/)**, **[JAX](https://github.com/google/jax)**, or **[PyTorch](https://pytorch.org/)** backends 🧠
30-
- **Augmentation Variety**: Diverse **training-time augmentations** via **[Albumentations](https://albumentations.ai/)** library 🖼️
3130
- **Efficient Execution**: **Lightweight** models that are cheap to run 💰
3231
- **ONNX Runtime Inference**: **Fast** and **optimized** inference with **[ONNX runtime](https://onnxruntime.ai/)**
3332
- **User-Friendly CLI**: Simplified **CLI** for **training** and **validating** OCR models 🛠️
33+
- **Region Recognition (Optional)**: Predict **region/country** of the license plate 🌍
3434
- **Model HUB**: Access to a collection of **pre-trained models** ready for inference 🌟
3535
- **Train**/**Fine-tune**: Easily train or **fine-tune** your own models 🔧
3636
- **Export-Friendly**: Export easily to **CoreML**, **TFLite**, or **ONNX** formats 📦
@@ -39,10 +39,12 @@ The idea is to use this after a plate object detector, since the OCR expects the
3939

4040
Optimized, ready to use models with config files for inference or fine-tuning.
4141

42-
| Model Name | Size | Arch | b=1 Avg. Latency (ms) | Plates/sec (PPS) | Model Config | Plate Config | Val Results |
43-
|--------------------------|------|---------------------------------------------------------------------------------------------------------------------------|-----------------------|------------------|----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
44-
| `cct-s-v1-global-model` | S | [CCT](https://ankandrew.github.io/fast-plate-ocr/1.0/training/config/model_config/#compact-convolutional-transformer-cct) | **0.5877** | **1701.63** | [model_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v1_global_model_config.yaml) | [plate_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v1_global_plate_config.yaml) | [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v1_global_val_results.json) |
45-
| `cct-xs-v1-global-model` | XS | [CCT](https://ankandrew.github.io/fast-plate-ocr/1.0/training/config/model_config/#compact-convolutional-transformer-cct) | **0.3232** | **3094.21** | [model_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v1_global_model_config.yaml) | [plate_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v1_global_plate_config.yaml) | [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v1_global_val_results.json) |
42+
| Model Name | Size | Arch | b=1 Avg. Latency (ms) | Plates/sec (PPS) | Model Config | Plate Config | Val Results |
43+
|--------------------------|------|------------------------------------------------------------------------------------------------------------------------------|-----------------------|------------------|----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
44+
| `cct-s-v2-global-model` | S | [CCT](https://ankandrew.github.io/fast-plate-ocr/latest/training/config/model_config/#compact-convolutional-transformer-cct) | **0.6758** | **1479.61** | [model_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v2_global_model_config.yaml) | [plate_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v2_global_plate_config.yaml) | [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v2_global_val_results.json) |
45+
| `cct-xs-v2-global-model` | XS | [CCT](https://ankandrew.github.io/fast-plate-ocr/latest/training/config/model_config/#compact-convolutional-transformer-cct) | **0.4664** | **2144.14** | [model_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v2_global_model_config.yaml) | [plate_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v2_global_plate_config.yaml) | [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v2_global_val_results.json) |
46+
| `cct-s-v1-global-model` | S | [CCT](https://ankandrew.github.io/fast-plate-ocr/latest/training/config/model_config/#compact-convolutional-transformer-cct) | **0.5877** | **1701.63** | [model_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v1_global_model_config.yaml) | [plate_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v1_global_plate_config.yaml) | [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_s_v1_global_val_results.json) |
47+
| `cct-xs-v1-global-model` | XS | [CCT](https://ankandrew.github.io/fast-plate-ocr/latest/training/config/model_config/#compact-convolutional-transformer-cct) | **0.3232** | **3094.21** | [model_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v1_global_model_config.yaml) | [plate_config.yaml](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v1_global_plate_config.yaml) | [results](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/cct_xs_v1_global_val_results.json) |
4648

4749
> [!TIP]
4850
> 🚀 Try the above models in [Hugging Spaces](https://huggingface.co/spaces/ankandrew/fast-alpr).
@@ -84,32 +86,33 @@ To predict from disk image:
8486
```python
8587
from fast_plate_ocr import LicensePlateRecognizer
8688

87-
m = LicensePlateRecognizer('cct-xs-v1-global-model')
89+
m = LicensePlateRecognizer('cct-s-v2-global-model')
8890
print(m.run('test_plate.png'))
8991
```
9092

91-
<details>
92-
<summary>Run demo</summary>
93+
If your model includes a **region head** (and `plate_regions` is defined in the plate config), predictions
94+
also include `region`. The `region_prob` field is populated when `return_confidence=True`:
9395

94-
![Run demo](https://github.com/ankandrew/fast-plate-ocr/blob/ac3d110c58f62b79072e3a7af15720bb52a45e4e/extra/inference_demo.gif?raw=true)
96+
```python
97+
from fast_plate_ocr import LicensePlateRecognizer
9598

96-
</details>
99+
m = LicensePlateRecognizer('cct-s-v2-global-model')
100+
pred = m.run('test_plate.png', return_confidence=True)[0]
101+
print(pred.region, pred.region_prob)
102+
```
97103

98-
To run model benchmark:
104+
To run a model benchmark:
99105

100106
```python
101107
from fast_plate_ocr import LicensePlateRecognizer
102108

103-
m = LicensePlateRecognizer('cct-xs-v1-global-model')
109+
m = LicensePlateRecognizer('cct-s-v2-global-model')
104110
m.benchmark()
105111
```
106112

107-
<details>
108-
<summary>Benchmark demo</summary>
109-
110-
![Benchmark demo](https://github.com/ankandrew/fast-plate-ocr/blob/ac3d110c58f62b79072e3a7af15720bb52a45e4e/extra/benchmark_demo.gif?raw=true)
111-
112-
</details>
113+
For more examples and the full API, see the
114+
[Inference Guide](https://ankandrew.github.io/fast-plate-ocr/latest/inference/running_inference/) and
115+
[Reference](https://ankandrew.github.io/fast-plate-ocr/latest/reference/).
113116

114117
## Training
115118

@@ -130,6 +133,8 @@ preparing your dataset to training and exporting the model.
130133
For full details on data preparation, model configs, fine-tuning, and training commands, check out the
131134
[docs](https://ankandrew.github.io/fast-plate-ocr/1.0/training/intro/).
132135

136+
For **region recognition** and export-friendly activations, use the v2 models.
137+
133138
## Contributing
134139

135140
Contributions to the repo are greatly appreciated. Whether it's bug fixes, feature enhancements, or new models,

config/latin_plate_config_v2.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Config for Latin-alphabet plates
2+
3+
# Max number of plate slots supported. This represents the number of model classification heads.
4+
max_plate_slots: 10
5+
# All the possible character set for the model output.
6+
alphabet: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
7+
# Padding character for plates which length is smaller than MAX_PLATE_SLOTS. It should still be present in the alphabet.
8+
pad_char: '_'
9+
# Image height which is fed to the model.
10+
img_height: 64
11+
# Image width which is fed to the model.
12+
img_width: 128
13+
# Keep the aspect ratio of the input image.
14+
keep_aspect_ratio: false
15+
# Interpolation method used for resizing the input image.
16+
interpolation: linear
17+
# Input image color mode. Use 'grayscale' for single-channel input or 'rgb' for 3-channel input.
18+
image_color_mode: rgb
19+
plate_regions: [ 'Albania', 'Andorra', 'Argentina', 'Armenia', 'Australia', 'Austria', 'Azerbaijan', 'Bahrain',
20+
'Belarus', 'Belgium', 'Bosnia and Herzegovina', 'Brazil', 'Bulgaria', 'Cambodia', 'Canada', 'Croatia',
21+
'Cyprus', 'Czech Republic', 'Denmark', 'Estonia', 'Finland', 'France', 'Georgia', 'Germany',
22+
'Gibraltar', 'Greece', 'Guernsey', 'Hungary', 'Iceland', 'Indonesia', 'Ireland', 'Israel', 'Italy',
23+
'Latvia', 'Liechtenstein', 'Lithuania', 'Luxembourg', 'Malaysia', 'Malta', 'Mexico', 'Moldova',
24+
'Monaco', 'Montenegro', 'Netherlands', 'New Zealand', 'North Macedonia', 'Norway', 'Poland',
25+
'Portugal', 'Qatar', 'Romania', 'San Marino', 'Serbia', 'Singapore', 'Slovakia', 'Slovenia', 'Spain',
26+
'Sweden', 'Switzerland', 'Thailand', 'Turkey', 'United States', 'Ukraine', 'United Kingdom', 'Vietnam',
27+
'Unknown' ]

docs/index.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Fast & Lightweight License Plate OCR
22

3-
![Intro](https://raw.githubusercontent.com/ankandrew/fast-plate-ocr/4a7dd34c9803caada0dc50a33b59487b63dd4754/extra/demo.gif)
3+
![Intro](https://github.com/ankandrew/fast-plate-ocr/releases/download/arg-plates/readme_demo.gif)
44

55
`fast-plate-ocr` is a **lightweight** and **fast** OCR framework for **license plate text recognition**. You can train
66
models from scratch or use the trained models for inference.
@@ -15,10 +15,10 @@ The idea is to use this after a plate object detector, since the OCR expects the
1515
### Features
1616

1717
- **Keras 3 Backend Support**: Train seamlessly using **[TensorFlow](https://www.tensorflow.org/)**, **[JAX](https://github.com/google/jax)**, or **[PyTorch](https://pytorch.org/)** backends 🧠
18-
- **Augmentation Variety**: Diverse **training-time augmentations** via **[Albumentations](https://albumentations.ai/)** library 🖼️
1918
- **Efficient Execution**: **Lightweight** models that are cheap to run 💰
2019
- **ONNX Runtime Inference**: **Fast** and **optimized** inference with **[ONNX runtime](https://onnxruntime.ai/)**
2120
- **User-Friendly CLI**: Simplified **CLI** for **training** and **validating** OCR models 🛠️
21+
- **Region Recognition (Optional)**: Predict **region/country** of the license plate 🌍
2222
- **Model HUB**: Access to a collection of **pre-trained models** ready for inference 🌟
2323
- **Train**/**Fine-tune**: Easily train or **fine-tune** your own models 🔧
2424
- **Export-Friendly**: Export easily to **CoreML**, **TFLite**, or **ONNX** formats 📦
@@ -46,12 +46,15 @@ Run **OCR** on a **cropped** license plate image using [`LicensePlateRecognizer`
4646
```python
4747
from fast_plate_ocr import LicensePlateRecognizer
4848

49-
m = LicensePlateRecognizer("cct-xs-v1-global-model")
49+
m = LicensePlateRecognizer("cct-s-v2-global-model")
5050
print(m.run("test_plate.png"))
5151
```
5252

5353
For **more examples** and input formats (NumPy arrays, batches, etc.), see the [**Inference Guide**](inference/running_inference.md).
5454

55+
If your model includes a **region head** and `plate_regions` is defined, predictions include `region`.
56+
The `region_prob` field is populated when `return_confidence=True`.
57+
5558
### Use it with FastALPR
5659

5760
If you prefer not to use `fast-plate-ocr` directly on **cropped plates**, you can easily leverage it through **FastALPR**,

0 commit comments

Comments
 (0)