# 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 ""