Sommaire
L' aperçu
Lorsque vous souhaitez extraire des chiffres à partir d'images, qu'il s'agisse de codes postaux, de relevés de compteurs ou de totaux sur des factures, il existe deux chemins principaux en Python : l'itinéraire de bas niveau (à l'aide d'OpenCV) et l'itinéraire de haut niveau (à l'aide d'outils d'OCR prédéfinis tels que Mindee).
Cet article s'adresse aux développeurs qui souhaitent comprendre les deux : nous expliquerons comment créer un outil de reconnaissance numérique de base en utilisant Ouvrez CV, puis comparez-la avec les solutions OCR modernes en utilisant SDK Python de Mindee et la librairie DocTR. Nous aborderons également le prétraitement pratique des images, le tri des contours et les cas d'utilisation réels.
Pourquoi la reconnaissance numérique ?
La reconnaissance numérique est une sous-tâche utile de l'OCR. Elle apparaît dans :
- Chèques bancaires
- Lectures de compteurs des services publics
- Formulaires et factures
- Tickets de stationnement
- Codes-barres des produits
- Solveurs de Sudoku (oui, vraiment)
Le défi ? Les chiffres sont souvent déformés, écrits à la main, scannés ou photographiés dans des conditions loin d'être idéales. C'est pourquoi une reconnaissance solide est essentielle.
Partie 1 — Création d'un système de reconnaissance numérique à partir de zéro avec OpenCV
Commençons par l'itinéraire classique de vision par ordinateur utilisant OpenCV et K-Nearest Nearest Neighbors.
Étape 1 — Formation sur OpenCV digits.png
OpenCV est livré avec une image pré-étiquetée appelée digits.png—une grille de 50 x 100 d'images de 20 x 20 chiffres, totalisant 5 000 chiffres manuscrits.
Nous allons diviser cela en kits d'entraînement et de test.
import numpy as np
import cv2 as cv
img = cv.imread(cv.samples.findFile('digits.png'))
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# Split into individual digit cells (20x20 pixels)
cells = [np.hsplit(row, 100) for row in np.vsplit(gray, 50)]
x = np.array(cells)
train = x[:, :50].reshape(-1, 400).astype(np.float32)
test = x[:, 50:100].reshape(-1, 400).astype(np.float32)
# Labels: 250 of each digit 0–9
labels = np.repeat(np.arange(10), 250)[:, np.newaxis]
train_labels = labels.copy()
test_labels = labels.copy()
Entraînez et testez un modèle kNN de base :
knn = cv.ml.KNearest_create()
knn.train(train, cv.ml.ROW_SAMPLE, train_labels)
ret, result, neighbours, dist = knn.findNearest(test, k=5)
accuracy = (result == test_labels).mean() * 100
print(f"Test accuracy: {accuracy:.2f}%")Très bien, surtout compte tenu de la simplicité du modèle.
Étape 2 — Reconnaître les chiffres dans une nouvelle image
Simulons maintenant un cas d'utilisation réel : vous avez une photo avec une séquence de chiffres et vous souhaitez les reconnaître.
A) Pré-traitement et détection des contours
Nous allons convertir l'image en niveaux de gris, définir un seuil et extraire des chiffres individuels à l'aide de contours.
def extract_digits_from_image(img_path):
img = cv.imread(img_path)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
blur = cv.GaussianBlur(gray, (5, 5), 0)
_, thresh = cv.threshold(blur, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)
contours, _ = cv.findContours(thresh, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
digit_regions = []
bounding_boxes = []
for cnt in contours:
x, y, w, h = cv.boundingRect(cnt)
if h > 10 and w > 5:
roi = thresh[y:y+h, x:x+w]
resized = cv.resize(roi, (20, 20))
digit_regions.append(resized)
bounding_boxes.append((x, y, w, h))
# Sort digits left to right
sorted_digits = [x for _, x in sorted(zip(bounding_boxes, digit_regions), key=lambda b: b[0][0])]
return sorted_digits
B) Reconnaître les chiffres
Une fois les chiffres extraits et triés, nous pouvons les classer :
def recognize_digits(digit_images, knn_model):
results = []
for digit_img in digit_images:
sample = digit_img.reshape((1, 400)).astype(np.float32)
ret, result, _, _ = knn_model.findNearest(sample, k=5)
results.append(int(result[0][0]))
return results
Utilisation :
digits = extract_digits_from_image("sample_digits.png")
predictions = recognize_digits(digits, knn)
print("Detected digits:", predictions)
Partie 2 — Les limites de l'OCR classique
Construire à partir de zéro vous permet de contrôler et de mieux comprendre le pipeline, mais :
- Le modèle ne reconnaît que les chiffres
- Vous devez segmenter les caractères manuellement
- Il est sensible au bruit, à l'inclinaison et aux changements de police
- La précision est correcte mais pas comparable à celle d'une production
Si vous souhaitez reconnaître du texte réel dans différentes polices, mises en page ou langues, vous avez besoin de meilleurs outils.
{{cta-awareness-1= » /in-progress/global-blog-elements "}}
Partie 3 — Utilisation des outils d'OCR de Mindee
Mindee fournit des API OCR modernes et des outils open source tels que Docteur R prêts à l'emploi pour les documents imprimés et numérisés, les reçus, les factures, etc.
Vous n'avez pas besoin de créer votre propre classificateur ou votre propre logique de segmentation, il vous suffit d'ajouter une image.
Option 1 — Utilisation du SDK Python de Mindee
Installez le SDK :
pip install mindee
Reconnaissez les champs structurés tels que les totaux, les dates et les montants des taxes :
import mindee
client = mindee.Client(api_key="your_api_key")
doc = client.source_from_path("path/to/receipt.jpg")
result = client.parse(mindee.product.ReceiptV4, doc)
print(result.document)
✅ Exemple de sortie :
total_amount: 42.80
date: 2025-04-08
tax: 4.28
C'est idéal pour les développeurs qui souhaitent une extraction structurée au niveau des champs sans travail de machine learning.
{{cta-consideration-1= » /in-progress /global-blog-elements «}}
Option 2 — Utilisation de DocTR pour l'OCR générale de textes et de chiffres
Installation avec le backend PyTorch :
pip install "python-doctr[torch]"
OCR sur n'importe quelle image (PDF, photo, numérisation) :
from doctr.io import DocumentFile
from doctr.models import ocr_predictor
model = ocr_predictor(pretrained=True)
doc = DocumentFile.from_images(["path/to/image.jpg"])
result = model(doc)
# View predictions
for page in result.pages:
for block in page.blocks:
for line in block.lines:
print(" ".join([word.value for word in line.words]))
✅ Sortie :
ORDER NUMBER: 123456
TOTAL: $89.99
DocTR gère la détection de la mise en page, le regroupement de lignes et la reconnaissance des caractères, le tout en quelques lignes de code.
Conclusion
OpenCV est un excellent outil pédagogique qui fonctionne bien pour les cas d'utilisation étroitement contrôlés, tels que la reconnaissance numérique des formulaires numérisés. Mais si vous créez quelque chose destiné aux clients, ou si vous souhaitez simplement éviter les tracas liés au prétraitement et au réglage du modèle, le SDK et DocTR de Mindee sont des solutions prêtes à l'emploi.
En tant que développeur, vous avez toujours le contrôle total, avec une meilleure précision et moins de maux de tête.
À propos


.webp)
.webp)

.webp)