Retour aux projets
ALPR 5 semaines 2 pers.

Reconnaissance automatique de plaques d'immatriculation

Système ALPR complet sans Deep Learning (Vision Classique + Machine Learning), avec benchmarks rigoureux Python vs C++.

Python C++17 OpenCV Random Forest CMake Google Test
Aperçu du projet ALPR

Contexte & Problématique

La reconnaissance automatique de plaques d’immatriculation (ALPR) est une brique essentielle des systèmes de transport intelligents et du contrôle d’accès routier. L’objectif de ce projet était d’analyser des flux d’images haute résolution et de localiser la plaque d’immatriculation d’un véhicule avec précision, indépendamment du type de véhicule ou de l’environnement.

Les Défis Techniques


Vue d’ensemble du Workflow

Pour résoudre ce problème de manière robuste, nous avons structuré le traitement selon un pipeline séquentiel en 4 grandes étapes :

01 Image Brute Full HD 1080p
02 Prétraitement Resize & Gris
03 Génération ROI Filtres & Morpho
04 Features HOG Vecteur 293D
05 Classification Random Forest
06 Résultat Plaque Localisée
  1. Prétraitement : Normalisation d’échelle et réduction des canaux de couleur.
  2. Génération de candidats (ROI) : Extraction multi-échelles des zones rectangulaires à forte probabilité de contenir une plaque.
  3. Extraction de caractéristiques : Représentation numérique de chaque candidat par un vecteur de descripteurs géométriques et HOG.
  4. Classification & Validation : Évaluation des candidats par un modèle Machine Learning et sélection du meilleur candidat.

Le Pipeline Algorithmique Étape par Étape

1. Prétraitement de l’Image

La première étape consiste à préparer l’image pour stabiliser les dimensions des objets et accélérer les calculs ultérieurs :

1. Image Originale 2. Image Prétraitée
Originale Prétraitée

2. Détection & Extraction des Candidats (ROI)

Pour éviter de balayer naïvement toute l’image, qui serait extrêmement lent, nous générons un ensemble restreint de Régions d’Intérêt (ROI) candidates en combinant 3 branches complémentaires :

  1. Branche Principale (Morphologie + Sobel) : Amplification du contraste local des caractères (filtre MMLPF), suivie d’un filtre de Sobel vertical, d’un seuillage d’Otsu et d’une fermeture morphologique ($17 \times 3$).
  2. Branche Suréchantillonnée ($\times 2$) : Application du même pipeline sur l’image agrandie à $2\times$ sa taille afin de capturer les plaques très petites ou éloignées.
  3. Branche Canny : Détection adaptative des contours basée sur la médiane des intensités de l’image.

Filtrage géométrique indépendant : Chaque branche filtre immédiatement ses propres régions candidates selon leur surface ($50 \text{ px} \le \text{aire} \le 40\,000 \text{ px}$) et leur ratio d’aspect ($1.0 \le w/h \le 8.0$) afin d’éliminer d’emblée les faux candidats évidents.

Étapes de la Branche Principale :

1 : Filtre MMLPF 2 : Sobel Vertical
MMLPF Base Sobel Base
3 : Seuil d’Otsu 4 : Fermeture
Otsu Base Fermeture Base
5 : Candidats extraits
CCA Base

Fusion des 3 branches & Dédoublonnage NMS

De la même manière, la Branche Suréchantillonnée ($\times 2$) et la Branche Canny extraient et filtrent leurs propres candidats. L’ensemble des régions retenues par les 3 branches est ensuite regroupé puis dédoublonné via une suppression non-maximale (NMS basée sur l’IoU) pour éliminer les chevauchements.

Candidats fusionnés (3 branches) et dédoublonnés via NMS
Candidats fusionnés (3 branches) et dédoublonnés via NMS

3. Signature Numérique (Descripteur HOG & Geométrie)

Chaque patch candidat retenu est découpé et redimensionné à une taille fixe de $64 \times 32$ pixels, puis converti en un vecteur de 293 caractéristiques :


4. Classification & Localisation Finale

Chaque vecteur de caractéristiques est soumis à un classifieur Random Forest (cv::ml::RTrees). Le modèle attribue un score de confiance à chaque candidat et la région avec le score positif le plus élevé est retenue comme plaque finale.

Résultat final de la détection de plaque
Résultat final de la détection de plaque

Démarche d’Ingénierie : Du Prototype Python au C++17

Le projet a évolué en deux étapes majeures :

1. Prototype Python (PoC)

Permet de prototyper rapidement le pipeline avec scikit-learn et OpenCV Python, de valider les filtres morphologiques et d’entraîner le modèle de classification.

2. Portage C++17 & Module Personnalisé MyCV

Afin d’atteindre les performances temps réel requises et de s’affranchir des abstractions opaques d’OpenCV, nous avons réécrit le pipeline en C++17 et conçu un module sur-mesure MyCV comprenant :


Résultats & Benchmarks

Évaluation rigoureuse réalisée sur le jeu de test du dataset UFPR-ALPR (1 440 images de test) :

Performances d’Inférence

Implémentation Vrais Positifs (TP) Précision Rappel F1-Score Temps moyen
Python 955 0.8580 0.6632 0.7481 468.50 ms
C++17 (Optimisé) 963 0.8629 0.6687 0.7535 402.28 ms
C++17 (MyCV) 955 0.8504 0.6632 0.7452 583.67 ms

Enseignements Clés des Benchmarks