Optimiser la précision de l'OCR
La qualité en entrée détermine la qualité en sortie
Comme le rappelait l’équipe Mistral lors de leur webinaire Document AI : c’est du « garbage in, garbage out ». La qualité de l’extraction OCR dépend directement de la qualité du document source. Dans cette leçon, vous apprendrez les techniques pour maximiser la précision de vos extractions.
Qualité d’image et résolution
Résolution minimale recommandée
Pour des résultats optimaux :
- Documents imprimés : 200 DPI minimum, 300 DPI recommandé
- Écriture manuscrite : 300 DPI minimum
- Tableaux complexes : 300 DPI recommandé
- Documents historiques : 400 DPI ou plus
Pré-traitement des images
Avant d’envoyer un document à l’API, appliquez ces corrections si nécessaire :
from PIL import Image, ImageEnhance, ImageFilter
import io
import base64
def pre_traiter_image(chemin_image: str) -> str:
"""Pré-traite une image pour améliorer l'extraction OCR."""
img = Image.open(chemin_image)
# 1. Conversion en niveaux de gris
img = img.convert("L")
# 2. Augmentation du contraste
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.5)
# 3. Augmentation de la netteté
img = img.filter(ImageFilter.SHARPEN)
# 4. Binarisation (seuillage)
img = img.point(lambda x: 0 if x < 128 else 255, "1")
# Conversion en base64
buffer = io.BytesIO()
img.save(buffer, format="PNG")
return base64.b64encode(buffer.getvalue()).decode("utf-8")
Correction de l’orientation
Les documents scannés sont souvent mal orientés. Corrigez l’angle avant l’envoi :
from PIL import Image
def corriger_orientation(chemin_image: str) -> Image.Image:
"""Corrige l'orientation d'une image scannée via les métadonnées EXIF."""
img = Image.open(chemin_image)
# Utilisation des données EXIF pour corriger l'orientation
try:
exif = img._getexif()
if exif:
orientation = exif.get(274) # Tag EXIF orientation
rotations = {3: 180, 6: 270, 8: 90}
if orientation in rotations:
img = img.rotate(rotations[orientation], expand=True)
except (AttributeError, KeyError):
pass
return img
Optimisation par type de document
Documents imprimés standards
Pour les factures, contrats et rapports :
# Configuration optimale pour documents imprimés
ocr_response = client.ocr.process(
model="mistral-ocr-latest",
document={
"type": "document_base64",
"document_base64": document_base64
},
table_format="markdown" # Extraction explicite des tableaux
)
Documents manuscrits
L’écriture manuscrite nécessite plus de soin :
- Utilisez des scans de haute résolution (300+ DPI)
- Augmentez le contraste entre l’encre et le papier
- Évitez la binarisation agressive qui peut effacer les traits fins
- Le modèle gère bien les écritures manuscrites multilingues
Scans de mauvaise qualité
Pour les documents dégradés :
from PIL import Image, ImageFilter, ImageEnhance
def ameliorer_scan(chemin: str) -> Image.Image:
"""Améliore un scan de mauvaise qualité."""
img = Image.open(chemin)
# Réduction du bruit
img = img.filter(ImageFilter.MedianFilter(size=3))
# Augmentation du contraste
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(2.0)
# Augmentation de la luminosité si trop sombre
enhancer = ImageEnhance.Brightness(img)
img = enhancer.enhance(1.2)
return img
Traitement par lots (Batch)
Pour traiter de gros volumes, utilisez le service Batch Inference de Mistral :
import os
import json
from pathlib import Path
from mistralai import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
def traiter_dossier(dossier: str) -> dict:
"""Traite tous les PDF d'un dossier."""
resultats = {}
chemin = Path(dossier)
for fichier in chemin.glob("*.pdf"):
print(f"Traitement de {fichier.name}...")
with open(fichier, "rb") as f:
import base64
doc_b64 = base64.b64encode(f.read()).decode("utf-8")
try:
response = client.ocr.process(
model="mistral-ocr-latest",
document={
"type": "document_base64",
"document_base64": doc_b64
},
table_format="markdown"
)
resultats[fichier.name] = {
"pages": len(response.pages),
"contenu": "\n\n".join(
p.markdown for p in response.pages
)
}
except Exception as e:
resultats[fichier.name] = {"erreur": str(e)}
return resultats
Vérification de la qualité
Après extraction, validez la qualité avec des heuristiques simples :
def verifier_qualite(markdown: str) -> dict:
"""Vérifie la qualité d'une extraction OCR."""
indicateurs = {
"longueur": len(markdown),
"mots": len(markdown.split()),
"lignes_vides_ratio": markdown.count("\n\n") / max(len(markdown), 1),
"caracteres_speciaux_ratio": sum(
1 for c in markdown if not c.isalnum() and c not in " \n\t.,;:!?-"
) / max(len(markdown), 1),
}
# Alertes
if indicateurs["mots"] < 10:
indicateurs["alerte"] = "Très peu de texte extrait"
elif indicateurs["caracteres_speciaux_ratio"] > 0.3:
indicateurs["alerte"] = "Ratio élevé de caractères spéciaux"
return indicateurs
Bonnes pratiques récapitulatives
- Résolution : 300 DPI minimum pour tout document non trivial
- Contraste : augmentez le contraste avant l’envoi si le document est pâle
- Orientation : corrigez l’angle de rotation des scans
- Format : préférez PDF natif quand disponible (meilleure qualité que les scans)
- Tableaux : utilisez
table_format="markdown"ou"html"explicitement - Batch : traitez par lots pour les gros volumes et parallélisez les appels
- Validation : vérifiez systématiquement la qualité de l’extraction
Points clés à retenir
- La qualité du document source est le facteur principal de précision
- Le pré-traitement d’image (contraste, netteté, binarisation) améliore les résultats
- Adaptez votre approche au type de document (imprimé, manuscrit, dégradé)
- Utilisez le batch processing pour les gros volumes
- Validez toujours la qualité de l’extraction avant exploitation