llm_ticket3/utils/ocr_utils.py
2025-04-23 14:27:28 +02:00

102 lines
3.8 KiB
Python

# utils/ocr_utils.py
from PIL import Image, ImageEnhance
import pytesseract
import logging
import os
import io
logger = logging.getLogger("OCR")
def pretraiter_image(image_path: str) -> Image.Image:
"""
Prétraite l'image pour améliorer la qualité de l'OCR.
Args:
image_path: Chemin de l'image
Returns:
Image prétraitée
"""
try:
# Ouvrir l'image
with Image.open(image_path) as img:
# Convertir en niveaux de gris si l'image est en couleur
if img.mode != 'L':
img = img.convert('L')
# Améliorer le contraste
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.5) # Facteur de contraste 1.5
# Augmenter la netteté
enhancer = ImageEnhance.Sharpness(img)
img = enhancer.enhance(1.5) # Facteur de netteté 1.5
# Agrandir l'image si elle est petite
width, height = img.size
if width < 1000 or height < 1000:
ratio = max(1000 / width, 1000 / height)
new_width = int(width * ratio)
new_height = int(height * ratio)
img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
return img
except Exception as e:
logger.error(f"Erreur lors du prétraitement de l'image {image_path}: {e}")
return Image.open(image_path) # Retourner l'image originale en cas d'erreur
def extraire_texte_fr(image_path: str) -> str:
"""
Effectue un OCR sur une image en langue française.
Retourne le texte brut extrait (chaîne vide si aucun texte détecté ou en cas d'erreur).
Chaque appel est isolé et tracé dans les logs.
"""
try:
if not os.path.exists(image_path) or not os.access(image_path, os.R_OK):
logger.warning(f"Image inaccessible ou introuvable: {image_path}")
return ""
logger.info(f"Traitement OCR pour {image_path}")
# Configurer pytesseract
config = '--psm 3 --oem 3' # Page segmentation mode: 3 (auto), OCR Engine mode: 3 (default)
# Prétraiter l'image
img = pretraiter_image(image_path)
logger.info(f"Image prétraitée: dimensions={img.size}, mode={img.mode}")
# Réaliser l'OCR avec fallback
try:
texte = pytesseract.image_to_string(img, lang="fra", config=config)
except Exception as ocr_err:
logger.warning(f"Première tentative OCR échouée: {ocr_err}, tentative avec image originale")
# En cas d'échec, essayer avec l'image originale
with Image.open(image_path) as original_img:
texte = pytesseract.image_to_string(original_img, lang="fra", config=config)
# Nettoyer le texte
texte = texte.strip()
# Sauvegarder l'image prétraitée pour debug si OCR réussi
if texte:
try:
debug_dir = "debug_ocr"
os.makedirs(debug_dir, exist_ok=True)
img_name = os.path.basename(image_path)
img.save(os.path.join(debug_dir, f"pretreated_{img_name}"), format="JPEG")
logger.info(f"Image prétraitée sauvegardée dans {debug_dir}/pretreated_{img_name}")
except Exception as e:
logger.warning(f"Impossible de sauvegarder l'image prétraitée: {e}")
# Journaliser le résultat
if texte:
logger.info(f"OCR réussi [{image_path}] — {len(texte)} caractères: {texte[:100]}...")
else:
logger.warning(f"OCR vide (aucun texte détecté) pour {image_path}")
return texte
except Exception as e:
logger.error(f"Erreur lors de l'OCR de {image_path}: {e}")
return ""