mirror of
https://github.com/Ladebeze66/llm_ticket3.git
synced 2025-12-16 00:06:53 +01:00
0705-17:12
This commit is contained in:
parent
211a570559
commit
6b96513438
@ -7,9 +7,9 @@ from pathlib import Path
|
|||||||
|
|
||||||
from ..base_agent import BaseAgent
|
from ..base_agent import BaseAgent
|
||||||
from ..utils.pipeline_logger import sauvegarder_donnees
|
from ..utils.pipeline_logger import sauvegarder_donnees
|
||||||
from utils.ocr_cleaner import clean_text_with_profiles # AJOUT
|
from utils.ocr_avance.ocr_cleaner import clean_text_with_profiles
|
||||||
from utils.ocr_utils import extraire_texte
|
from utils.ocr_brut.ocr_utils import extraire_texte
|
||||||
from utils.image_preparer import prepare_image_for_llama_vision
|
from utils.ocr_avance.image_preparer import prepare_image_for_llama_vision
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("AgentVisionOCR")
|
logger = logging.getLogger("AgentVisionOCR")
|
||||||
@ -161,7 +161,9 @@ This prompt is designed to generalize across all web portals, technical forms, o
|
|||||||
|
|
||||||
# ✅ Étape 3 : Préparation de l'image pour le modèle Vision
|
# ✅ Étape 3 : Préparation de l'image pour le modèle Vision
|
||||||
image_stem = Path(image_path).stem
|
image_stem = Path(image_path).stem
|
||||||
vision_ready_path = os.path.join("debug_ocr", f"vision_ready_{image_stem}.png")
|
# Utiliser le nouveau chemin pour les résultats OCR avancé
|
||||||
|
os.makedirs("results/ocr_avance", exist_ok=True)
|
||||||
|
vision_ready_path = os.path.join("results/ocr_avance", f"vision_ready_{image_stem}.png")
|
||||||
prepare_image_for_llama_vision(image_path, vision_ready_path)
|
prepare_image_for_llama_vision(image_path, vision_ready_path)
|
||||||
|
|
||||||
# Étape 4 : Appel au modèle avec image traitée
|
# Étape 4 : Appel au modèle avec image traitée
|
||||||
@ -176,6 +178,15 @@ This prompt is designed to generalize across all web portals, technical forms, o
|
|||||||
getattr(self.llm, "modele", "llama3-vision-90b-instruct"))
|
getattr(self.llm, "modele", "llama3-vision-90b-instruct"))
|
||||||
model_name = model_name.replace(".", "-").replace(":", "-").replace("_", "-")
|
model_name = model_name.replace(".", "-").replace(":", "-").replace("_", "-")
|
||||||
|
|
||||||
|
# Sauvegarde du résultat dans results/ocr_avance
|
||||||
|
try:
|
||||||
|
result_dir = "results/ocr_avance"
|
||||||
|
os.makedirs(result_dir, exist_ok=True)
|
||||||
|
with open(f"{result_dir}/ocr_{image_stem}.txt", "w", encoding="utf-8") as f:
|
||||||
|
f.write(cleaned_text)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[OCR-LLM] Erreur sauvegarde texte: {e}")
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"extracted_text": cleaned_text,
|
"extracted_text": cleaned_text,
|
||||||
"image_name": image_name,
|
"image_name": image_name,
|
||||||
|
|||||||
63
docs/ARCHITECTURE_OCR.md
Normal file
63
docs/ARCHITECTURE_OCR.md
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Architecture OCR Réorganisée
|
||||||
|
|
||||||
|
## Structure des Répertoires
|
||||||
|
|
||||||
|
```
|
||||||
|
project/
|
||||||
|
│
|
||||||
|
├── utils/
|
||||||
|
│ ├── ocr_brut/ # OCR basique (Tesseract)
|
||||||
|
│ │ ├── ocr_utils.py # Fonctions d'extraction de texte
|
||||||
|
│ │ ├── ocr_preprocessor.py # Prétraitement d'images pour OCR
|
||||||
|
│ │ └── README.md # Documentation
|
||||||
|
│ │
|
||||||
|
│ ├── ocr_avance/ # OCR avancé (Llama Vision)
|
||||||
|
│ │ ├── image_preparer.py # Préparation pour modèle Llama Vision
|
||||||
|
│ │ ├── ocr_cleaner.py # Nettoyage et amélioration du texte
|
||||||
|
│ │ ├── ocr_clean_dict.json # Dictionnaire de correction OCR
|
||||||
|
│ │ ├── hallucination_filter.json # Filtres pour hallucinations
|
||||||
|
│ │ ├── translation_clean_dict.json # Corrections pour traduction
|
||||||
|
│ │ └── README.md # Documentation
|
||||||
|
│ │
|
||||||
|
│ └── __init__.py # Compatibilité avec imports existants
|
||||||
|
│
|
||||||
|
├── agents/
|
||||||
|
│ └── llama_vision/
|
||||||
|
│ └── agent_vision_ocr.py # Agent principal utilisant les modules OCR
|
||||||
|
│
|
||||||
|
├── results/
|
||||||
|
│ ├── ocr_brut/ # Résultats OCR Tesseract
|
||||||
|
│ ├── ocr_avance/ # Résultats OCR Llama Vision
|
||||||
|
│ └── README.md # Documentation
|
||||||
|
│
|
||||||
|
└── test_agent_ocr.py # Script de test principal
|
||||||
|
```
|
||||||
|
|
||||||
|
## Circuit de Traitement OCR
|
||||||
|
|
||||||
|
1. **OCR Brut (Tesseract)**
|
||||||
|
- Sélection d'un profil de prétraitement (default, document, aggressive, clahe_high, invert_light)
|
||||||
|
- Prétraitement de l'image avec `ocr_preprocessor.py`
|
||||||
|
- Extraction du texte avec Tesseract via `ocr_utils.py`
|
||||||
|
- Sauvegarde des résultats dans `results/ocr_brut/`
|
||||||
|
|
||||||
|
2. **OCR Avancé (Llama Vision)**
|
||||||
|
- Préparation de l'image pour le modèle avec `image_preparer.py`
|
||||||
|
- Envoi au modèle par l'agent `AgentVisionOCR`
|
||||||
|
- Nettoyage du texte extrait avec `ocr_cleaner.py`
|
||||||
|
- Sauvegarde des résultats dans `results/ocr_avance/`
|
||||||
|
|
||||||
|
## Configuration Actuelle
|
||||||
|
|
||||||
|
- **OCR Brut** : Profil "document" avec PSM=11, OEM=3
|
||||||
|
- **OCR Avancé** : Modèle Llama Vision avec image redimensionnée à 672x672
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Le script `test_agent_ocr.py` permet de tester l'ensemble du circuit avec une image de test.
|
||||||
|
|
||||||
|
## Notes Importantes
|
||||||
|
|
||||||
|
1. Les fichiers dans `utils/` servent uniquement à la compatibilité avec les imports existants
|
||||||
|
2. Les résultats sont stockés dans des répertoires séparés pour plus de clarté
|
||||||
|
3. Le répertoire `ocr_brut_test/` a été conservé pour des tests ultérieurs"
|
||||||
54
docs/RESUME_OCR.md
Normal file
54
docs/RESUME_OCR.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Résumé des Modifications du Système OCR
|
||||||
|
|
||||||
|
## 1. Optimisation de l'OCR Brut (Tesseract)
|
||||||
|
|
||||||
|
- **Configuration optimale** :
|
||||||
|
- Profil de prétraitement "document" adapté aux documents administratifs
|
||||||
|
- PSM=11 (sparse text) pour une meilleure extraction
|
||||||
|
- OEM=3 (mode par défaut)
|
||||||
|
|
||||||
|
- **Simplification du code** :
|
||||||
|
- Suppression du redimensionnement redondant dans ocr_utils.py
|
||||||
|
- Uniformisation des chemins de sortie vers results/ocr_brut/
|
||||||
|
- Amélioration de la gestion des erreurs
|
||||||
|
|
||||||
|
## 2. Optimisation de l'OCR Avancé (Llama Vision)
|
||||||
|
|
||||||
|
- **Préparation des images** :
|
||||||
|
- Standardisation de toutes les images à 672x672 pixels
|
||||||
|
- Conservation des proportions avec padding
|
||||||
|
- Sortie unique vers results/ocr_avance/
|
||||||
|
|
||||||
|
- **Nettoyage du texte** :
|
||||||
|
- Dictionnaires de nettoyage séparés par profil
|
||||||
|
- Système modulaire pour activer différents niveaux de correction
|
||||||
|
|
||||||
|
## 3. Réorganisation de l'Architecture
|
||||||
|
|
||||||
|
- **Séparation claire des modules** :
|
||||||
|
- OCR brut (Tesseract) dans utils/ocr_brut/
|
||||||
|
- OCR avancé (Llama Vision) dans utils/ocr_avance/
|
||||||
|
- Résultats dans results/ocr_brut/ et results/ocr_avance/
|
||||||
|
|
||||||
|
- **Documentation complète** :
|
||||||
|
- README pour chaque module
|
||||||
|
- Documentation ARCHITECTURE_OCR.md pour la vue d'ensemble
|
||||||
|
- Avertissements dans les fichiers obsolètes
|
||||||
|
|
||||||
|
## 4. Tests et Compatibilité
|
||||||
|
|
||||||
|
- **Maintien de la compatibilité** :
|
||||||
|
- Module utils/__init__.py pour assurer la transition
|
||||||
|
- Conservation des fichiers originaux avec avertissements
|
||||||
|
- Duplication des fichiers critiques dans utils/ocrbrut/ pour archivage
|
||||||
|
|
||||||
|
- **Test agent_ocr.py** :
|
||||||
|
- Mise à jour pour utiliser les nouveaux chemins
|
||||||
|
- Création automatique des répertoires de résultats
|
||||||
|
- Affichage clair des chemins de sortie
|
||||||
|
|
||||||
|
## 5. Prochaines Étapes Possibles
|
||||||
|
|
||||||
|
- Suppression des fichiers obsolètes une fois la transition terminée
|
||||||
|
- Optimisation supplémentaire des profils de prétraitement
|
||||||
|
- Développement de nouveaux dictionnaires de correction
|
||||||
155
logs open_vpn
155
logs open_vpn
@ -1,155 +0,0 @@
|
|||||||
2025-05-07 08:46:02 OpenVPN 2.6.12 [git:v2.6.12/038a94bae57a446c] Windows [SSL (OpenSSL)] [LZO] [LZ4] [PKCS11] [AEAD] [DCO] built on Jul 18 2024
|
|
||||||
2025-05-07 08:46:02 Windows version 10.0 (Windows 10 or greater), amd64 executable
|
|
||||||
2025-05-07 08:46:02 library versions: OpenSSL 3.3.1 4 Jun 2024, LZO 2.10
|
|
||||||
2025-05-07 08:46:02 DCO version: 1.2.1
|
|
||||||
2025-05-07 08:46:02 TCP/UDP: Preserving recently used remote address: [AF_INET]37.71.248.18:1111
|
|
||||||
2025-05-07 08:46:02 UDPv4 link local: (not bound)
|
|
||||||
2025-05-07 08:46:02 UDPv4 link remote: [AF_INET]37.71.248.18:1111
|
|
||||||
2025-05-07 08:46:02 [vpn.cbao.fr] Peer Connection Initiated with [AF_INET]37.71.248.18:1111
|
|
||||||
2025-05-07 08:46:04 open_tun
|
|
||||||
2025-05-07 08:46:04 tap-windows6 device [Connexion au réseau local] opened
|
|
||||||
2025-05-07 08:46:04 Set TAP-Windows TUN subnet mode network/local/netmask = 10.8.1.0/10.8.1.12/255.255.255.0 [SUCCEEDED]
|
|
||||||
2025-05-07 08:46:04 Notified TAP-Windows driver to set a DHCP IP/netmask of 10.8.1.12/255.255.255.0 on interface {2CCBC607-261F-452C-8E9E-893870FF0EAE} [DHCP-serv: 10.8.1.0, lease-time: 31536000]
|
|
||||||
2025-05-07 08:46:04 Successful ARP Flush on interface [6] {2CCBC607-261F-452C-8E9E-893870FF0EAE}
|
|
||||||
2025-05-07 08:46:04 IPv4 MTU set to 1500 on interface 6 using service
|
|
||||||
2025-05-07 08:46:09 Initialization Sequence Completed
|
|
||||||
2025-05-07 13:46:02 [vpn.cbao.fr] Inactivity timeout (--ping-restart), restarting
|
|
||||||
2025-05-07 13:46:02 SIGUSR1[soft,ping-restart] received, process restarting
|
|
||||||
2025-05-07 13:46:03 TCP/UDP: Preserving recently used remote address: [AF_INET]37.71.248.18:1111
|
|
||||||
2025-05-07 13:46:03 UDPv4 link local: (not bound)
|
|
||||||
2025-05-07 13:46:03 UDPv4 link remote: [AF_INET]37.71.248.18:1111
|
|
||||||
2025-05-07 13:46:05 [vpn.cbao.fr] Peer Connection Initiated with [AF_INET]37.71.248.18:1111
|
|
||||||
2025-05-07 13:46:05 Preserving previous TUN/TAP instance: Connexion au réseau local
|
|
||||||
2025-05-07 13:46:05 Initialization Sequence Completed
|
|
||||||
|
|
||||||
|
|
||||||
dev tun
|
|
||||||
persist-tun
|
|
||||||
persist-key
|
|
||||||
data-ciphers AES-256-GCM:AES-256-CBC
|
|
||||||
data-ciphers-fallback AES-256-CBC
|
|
||||||
auth SHA256
|
|
||||||
tls-client
|
|
||||||
client
|
|
||||||
resolv-retry infinite
|
|
||||||
remote 37.71.248.18 1111 udp4
|
|
||||||
nobind
|
|
||||||
auth-user-pass
|
|
||||||
remote-cert-tls server
|
|
||||||
explicit-exit-notify
|
|
||||||
auth-nocache
|
|
||||||
<ca>
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIFBTCCA22gAwIBAgIIejdwM+00dLcwDQYJKoZIhvcNAQENBQAwWzEPMA0GA1UE
|
|
||||||
AxQGQ0FfVlBOMQswCQYDVQQGEwJGUjELMAkGA1UECBMCUE8xEjAQBgNVBAcTCVBl
|
|
||||||
cnBpZ25hbjENMAsGA1UEChMEQ0JBTzELMAkGA1UECxMCSVQwHhcNMjMwOTI5MDgx
|
|
||||||
MjM2WhcNMzMwOTI2MDgxMjM2WjBbMQ8wDQYDVQQDFAZDQV9WUE4xCzAJBgNVBAYT
|
|
||||||
AkZSMQswCQYDVQQIEwJQTzESMBAGA1UEBxMJUGVycGlnbmFuMQ0wCwYDVQQKEwRD
|
|
||||||
QkFPMQswCQYDVQQLEwJJVDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGB
|
|
||||||
AKEpm8PH2IOLzN3YeTEw17uIxipWNXDhtG7eqWgzXrus2r4UGeH692zb59I5Krrn
|
|
||||||
4JIWIEvAxylDkGucaRj1fAB2kHfDoiT/13ivbje0PjDNlCYNScaN0brz5/Q+CHzn
|
|
||||||
eFA6LyjXXT/IdpduRW5pL5BsEFWGHwgCT68YG0rfIqRMfEqYHCwd16yH2kywNgqd
|
|
||||||
xC61CEmp3plIlng+8DYaSZ6Si4UoJ2xtYWzFyH0EafH2R9Vhd6xgw9HqVD5LkTNS
|
|
||||||
qj7imL2oqIcjx1xbBKi1jgXrv2emCYJKmU2yE4DGxnHIR4tHwgrw2rsA6EobTg3c
|
|
||||||
GM/DwW6IchRO6AgxThvpTglDerSI3eZ7P+ezCLu1DVzDSpC4bUp5ZFLB7tR01EqK
|
|
||||||
8LxFXdOFF9ynJNc5v6GjMF5yi1P65bYUG9gFDFF4NDx0ZYUTyNlyzAJgtuJPivRD
|
|
||||||
milL+MQYEsrA4cdc1Em9ssSK1AGwX/987DxlGM/KRilNLGGUpRVr0Bn7S3YJTEkk
|
|
||||||
IwIDAQABo4HMMIHJMB0GA1UdDgQWBBRNjdxfpJmKOG2uv4aIxfQDOSH3HzCBjAYD
|
|
||||||
VR0jBIGEMIGBgBRNjdxfpJmKOG2uv4aIxfQDOSH3H6FfpF0wWzEPMA0GA1UEAxQG
|
|
||||||
Q0FfVlBOMQswCQYDVQQGEwJGUjELMAkGA1UECBMCUE8xEjAQBgNVBAcTCVBlcnBp
|
|
||||||
Z25hbjENMAsGA1UEChMEQ0JBTzELMAkGA1UECxMCSVSCCHo3cDPtNHS3MAwGA1Ud
|
|
||||||
EwQFMAMBAf8wCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBDQUAA4IBgQBqxHDMi2cn
|
|
||||||
UHc25JH1cEqOaiBfPKOyQuDXFeXQuc6lIuWOoiH4C/XGdMwxx9zP/WLpliVV4Wfq
|
|
||||||
PicjadSr6T77m5M55qPTFL6zG/oeKbHg+YHGIEdHMnMJPEon1nDx9lQsQFFoz9F/
|
|
||||||
cAKMTGjxuCQbTqRnOf4mCSsi0vtn0SgYwcoNuJhAOpP4OJHu9nbUaLlx8VJMONku
|
|
||||||
4P2EHWro/2UEqldrp1xkH2kXwx7u4LJr916z6IHdfTu4pMkr+yTcrM0EM1aVdC08
|
|
||||||
LqKj+WXcefcP6YZqajMgVbrAmq5JPLEmY4IiAl52b+kMEHp+mBfI+gvrJMMFZSz1
|
|
||||||
/n1U949EVAafklr/FqD9HBlgesZtbNsflybhrFF4+CE9/9Mp9YZ/nvBGkxiaXSBA
|
|
||||||
Xr4Ftq48GMk/abpA3MCuH4UWlMO3RZLSD727umoOko2BPbNqMmkvEL4hTvCTliAr
|
|
||||||
ThV23Aasyc9zy977HivaLeJpsKNCMC+C83LYATMab7hhQ9c2BwIj4Fs=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
</ca>
|
|
||||||
<cert>
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIE1jCCAz6gAwIBAgIBETANBgkqhkiG9w0BAQsFADBbMQ8wDQYDVQQDFAZDQV9W
|
|
||||||
UE4xCzAJBgNVBAYTAkZSMQswCQYDVQQIEwJQTzESMBAGA1UEBxMJUGVycGlnbmFu
|
|
||||||
MQ0wCwYDVQQKEwRDQkFPMQswCQYDVQQLEwJJVDAeFw0yNTAzMTMwODI5NTJaFw0z
|
|
||||||
NTAzMTEwODI5NTJaMFoxDjAMBgNVBAMTBWZncmFzMQswCQYDVQQGEwJGUjELMAkG
|
|
||||||
A1UECBMCUE8xEjAQBgNVBAcTCVBlcnBpZ25hbjENMAsGA1UEChMEQ0JBTzELMAkG
|
|
||||||
A1UECxMCSVQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChIgHQkTkw
|
|
||||||
QePtBYlMc0lFtL1AUQSX3k7BV41BjDVIBo/k3BF/TkNzFm+dpFRVFsgWP62XNRXO
|
|
||||||
pIIujFVRNfmckjby8r3dcFdFVJjb0uimjAUxFf2tf5PPLgBojZX/6QVpcsApJQp9
|
|
||||||
5D+oSVPudHqqCC2raBVW7ov9d9B+2GgBc9DwNd6gJplZNbUaxTgqwBrdC6sCO45/
|
|
||||||
nzKdXSKan7cdfWY5N8VbYR89rzwdkBnoI7qp8csKONymcXIgypHjj1MC7LdvOAYW
|
|
||||||
6/PV8DJuzFneQmClRBRQBrCIu0lyGvAys5drdzllBllZ6xjm/cr9l4ShHGfGWtr1
|
|
||||||
D7FaJ4umVyflAgMBAAGjggEkMIIBIDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAx
|
|
||||||
BglghkgBhvhCAQ0EJBYiT3BlblNTTCBHZW5lcmF0ZWQgVXNlciBDZXJ0aWZpY2F0
|
|
||||||
ZTAdBgNVHQ4EFgQUmb4rkgQoE6tQM2FxUpnPPcuc1A4wgYwGA1UdIwSBhDCBgYAU
|
|
||||||
TY3cX6SZijhtrr+GiMX0Azkh9x+hX6RdMFsxDzANBgNVBAMUBkNBX1ZQTjELMAkG
|
|
||||||
A1UEBhMCRlIxCzAJBgNVBAgTAlBPMRIwEAYDVQQHEwlQZXJwaWduYW4xDTALBgNV
|
|
||||||
BAoTBENCQU8xCzAJBgNVBAsTAklUggh6N3Az7TR0tzATBgNVHSUEDDAKBggrBgEF
|
|
||||||
BQcDAjAQBgNVHREECTAHggVmZ3JhczANBgkqhkiG9w0BAQsFAAOCAYEAPhSURAu3
|
|
||||||
XNV+gV5r6OGHXZMRmgUNjpXyJVo5MjSEgnBBqRwGfIcBd0VpNfZnrWqy1DMROGkI
|
|
||||||
g5aJ04Az5aD3CzUPfKcB8tAM4wT8+DteRZkGcMl7ZOqX++KoLsnA8AAejFinJ5FC
|
|
||||||
ZFnb16r/HpOw4tEZQfvGZ/FS8IyU8urLPk1IgOIKAqD0xZQNh73eeQnCIeS7RMpS
|
|
||||||
XVWDIGY/FlO+vBHqsusg3HlqRd4BQkxg22eKQFag01F9qCuu7VtRqiFH6G9RF0yU
|
|
||||||
UqkOCJU5HR+0CnGhKVM7SKIinGxPB1XskgrHdlpUckf4rlSDKxnX5OD+ooPz70Ex
|
|
||||||
L9hm0FmrHWVfCWjvZ0yDD8Sn2RslGT2XXZK57pRrh321SBFQDxIJgGlEmgBpjCaV
|
|
||||||
OqTw67AxG0ay9R2dQjVz1P/iTaiWLaeCQnMfNpFX0H9P+XPigw0xy6zepW6bxRDg
|
|
||||||
OYVgf+XV0yArTrnSJx9+/jW9xKRm+2DSRypxLWbZROJ5SErfpmGRX1NQ
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
</cert>
|
|
||||||
<key>
|
|
||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQChIgHQkTkwQePt
|
|
||||||
BYlMc0lFtL1AUQSX3k7BV41BjDVIBo/k3BF/TkNzFm+dpFRVFsgWP62XNRXOpIIu
|
|
||||||
jFVRNfmckjby8r3dcFdFVJjb0uimjAUxFf2tf5PPLgBojZX/6QVpcsApJQp95D+o
|
|
||||||
SVPudHqqCC2raBVW7ov9d9B+2GgBc9DwNd6gJplZNbUaxTgqwBrdC6sCO45/nzKd
|
|
||||||
XSKan7cdfWY5N8VbYR89rzwdkBnoI7qp8csKONymcXIgypHjj1MC7LdvOAYW6/PV
|
|
||||||
8DJuzFneQmClRBRQBrCIu0lyGvAys5drdzllBllZ6xjm/cr9l4ShHGfGWtr1D7Fa
|
|
||||||
J4umVyflAgMBAAECggEBAIMkZWu1tmDTT8lJ9zv0nI8SEfF1vxJHibuMIVhW38qW
|
|
||||||
JKj0f30oWnchrIgWBdkW6JRLEWJ+fxgnBhkSeCHXlydaTUSgUe0XEMBJoPtQha9/
|
|
||||||
SH5x0nxR2CAH5acyjQGySohPL5yNHCPoD/NMcvYhcPBQJbNay/trvR33VQbX5JZA
|
|
||||||
vMtZ822PcnklWUV+JUyk4McW8sAOw7UTCYaJMObwjAdkvi0cTpXOC6kp2Cn9leXW
|
|
||||||
Qvd6z26mXfk2gFgidkEKQkMNy5Np3/Nxssrth1+36WqQpMawZhWvrBtLnF21TUJW
|
|
||||||
AuwOtAmaaTver38X81doLVKNjr/oV4MTKmBC8iklLMECgYEA06Z/SlznvQaTolS2
|
|
||||||
hs9fu7En5jEgt+6b/chUUpRePPsCMG44T7CJNGtJ6rNnaJ3pC+zmvVh+xO9Sk6IB
|
|
||||||
OWgyNJ5I/R5tXrSyTwSTJXoUEwq394mjG/b7nfcw0PrQumHbuFj/q6o3NIvNiDui
|
|
||||||
KtfnzX4tVftaKCeOcEtJKuaznlECgYEAwuWciItvbmqaRHHAme5/yYYED4BsRbCY
|
|
||||||
Kk8WOZ4NSGSfyMhonPXSpSuwF66yZmk864olSbWsTjXzGs13KX9NOeXCjUkohAY5
|
|
||||||
tbps2CLoo/aDprjg4ZaWmXkFi6ceTzdoNIgSGf+Gro3P82fRPWLqcXfmWihPJh47
|
|
||||||
3tvEVrKxZ1UCgYArgRrDD0u3CAYKpP0Lws57xxNbdpeyFwLLbIUgoEyqnjG6AL3k
|
|
||||||
a3YYZ0E/U/cagvLnN5/KJcmQ81x26iL0SN2hATQhi0KR5/SK13bjii9cJqTf5dO4
|
|
||||||
KNFZi/jly9hhp0HBp9GN2KQWUfJCYXeY9N452Ai7lrnWbSMTI/Z7MgaTsQKBgQCA
|
|
||||||
GfOdPCjt5luniS0TAFQ13URl+/8ufzhE9t6g2GXao2jyy+cW4+yka+a+ajEQZzOH
|
|
||||||
jbGclTC/5232u/4K5IWZ/I631tIulPjxnatVFPzcaHd36iTFofkyvv0KIbomT0DK
|
|
||||||
5nUfaXjY2pVIY4CAXLfEBQ7/S2daopyviruuUJ2SUQKBgD1t4JloeG5yxXZmWLYY
|
|
||||||
QIXAJifNx3/U64mcXoRWZQukxMe3NB169f5Kbu2aAWS0Y+wa6WTFp+q6UwkHOqOm
|
|
||||||
dsFXc4IaYJICZQDpiuhqZi80c+TOJS5qUSHK5wKs4b1y2hxPeHNPoAWni+8292PB
|
|
||||||
ICZWzYno1a07gWGJeBhWSmsm
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
</key>
|
|
||||||
key-direction 1
|
|
||||||
<tls-auth>
|
|
||||||
#
|
|
||||||
# 2048 bit OpenVPN static key
|
|
||||||
#
|
|
||||||
-----BEGIN OpenVPN Static key V1-----
|
|
||||||
ad7131884e4148812622148d14af6d13
|
|
||||||
6ea1e84f92132eb8e5a18c56d908ddf2
|
|
||||||
97ae8b7b47d47e673b78b660dc91dace
|
|
||||||
7a97ce5934c20f49824bf8b7017b35ed
|
|
||||||
3a2fd7af967b2af243c1ca9482bb34d1
|
|
||||||
6e93478e695b9c86b29b5b79f472e67c
|
|
||||||
740a09a341be6c2c1b13d4468e705768
|
|
||||||
5dced700e2339a1e6f8b95165c869ec6
|
|
||||||
9e24c48b4c9127ec99a9a9e7c7c63ac5
|
|
||||||
aba05723e611ebbf76e343dcd1822b41
|
|
||||||
245413c9398ee4b5d96087f3b360cb7b
|
|
||||||
046576c1a45c3a804e9b958439c7f4cd
|
|
||||||
2cc93666db736b8d9d62b522b61c6b01
|
|
||||||
1d024d1b2c90fcee6c549a50e6e31062
|
|
||||||
1e096b1d41ee6b22e53488c2d071429d
|
|
||||||
e42476b191c7f9767e157aa9e45798b2
|
|
||||||
-----END OpenVPN Static key V1-----
|
|
||||||
</tls-auth>
|
|
||||||
31
results/README.md
Normal file
31
results/README.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Résultats des Traitements OCR
|
||||||
|
|
||||||
|
Ce répertoire contient les résultats des différents traitements OCR effectués sur les images.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
- `ocr_brut/` : Résultats de l'OCR basique (Tesseract)
|
||||||
|
- Images prétraitées par les différents profils
|
||||||
|
- Fichiers texte extraits des images
|
||||||
|
|
||||||
|
- `ocr_avance/` : Résultats de l'OCR avancé (Llama Vision)
|
||||||
|
- Images préparées pour le modèle Llama Vision
|
||||||
|
- Texte extrait par le modèle avec structure enrichie
|
||||||
|
|
||||||
|
## Organisation des Fichiers
|
||||||
|
|
||||||
|
### OCR Brut
|
||||||
|
- `preprocessed/[profil]/*.png` : Images prétraitées par profil
|
||||||
|
- `optimized_*.png` : Version finale prétraitée
|
||||||
|
- `ocr_*.txt` : Texte extrait par Tesseract
|
||||||
|
|
||||||
|
### OCR Avancé
|
||||||
|
- `vision_ready_*.png` : Images préparées pour Llama Vision (672x672)
|
||||||
|
- `ocr_*.txt` : Texte structuré extrait par le modèle
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
Ces résultats peuvent être utilisés pour :
|
||||||
|
- Comparer les performances des différentes méthodes d'OCR
|
||||||
|
- Vérifier les étapes de prétraitement des images
|
||||||
|
- Fournir des données d'entraînement pour améliorer les dictionnaires de correction"
|
||||||
BIN
results/ocr_avance/vision_ready_image_145435.png
Normal file
BIN
results/ocr_avance/vision_ready_image_145435.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
45
results/ocr_brut/ocr_image_145435.png.txt
Normal file
45
results/ocr_brut/ocr_image_145435.png.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
=
|
||||||
|
|
||||||
|
[e)
|
||||||
|
|
||||||
|
“
|
||||||
|
|
||||||
|
giraudibrg-lsb.com/BRG-LAB/PAGE programmetssai/zE4AAHEVNGOAA
|
||||||
|
|
||||||
|
BAGLAB C9 Béton C9 Fouméseu labo © Masse
|
||||||
|
|
||||||
|
FAT :1 Essai au bleu de méthylène (MB) - NF EN 933-9 (02-2022)
|
||||||
|
|
||||||
|
£E Victor
|
||||||
|
|
||||||
|
Echantilion _n°25-00075 réceptionné le 02/04/2028 par BOLLÉE Victor - prélevé le 02/04/2025 por BOLLEE Victor, n° prélbvement : 2500078
|
||||||
|
|
||||||
|
Matériau Sable 0/2 C - CARRIERE ADCEG
|
||||||
|
|
||||||
|
V HISTORIQUE
|
||||||
|
|
||||||
|
72
|
||||||
|
|
||||||
|
[VU Essai [ve marée ][M For Uo |[v osservanons
|
||||||
|
|
||||||
|
[
|
||||||
|
|
||||||
|
]
|
||||||
|
|
||||||
|
NREGISTRER
|
||||||
|
|
||||||
|
MPRMER
|
||||||
|
|
||||||
|
le l'essai
|
||||||
|
|
||||||
|
2025
|
||||||
|
|
||||||
|
(RE GIRAUD
|
||||||
|
|
||||||
|
les statistiques
|
||||||
|
|
||||||
|
lessai
|
||||||
|
|
||||||
|
A
|
||||||
|
|
||||||
|
impossible de trouver adresse IP du serveur de zk1.brg-lab.com.
|
||||||
BIN
results/ocr_brut/optimized_image_145435.png
Normal file
BIN
results/ocr_brut/optimized_image_145435.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 747 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 747 KiB |
@ -1,6 +1,11 @@
|
|||||||
from agents.llama_vision.agent_vision_ocr import AgentVisionOCR
|
from agents.llama_vision.agent_vision_ocr import AgentVisionOCR
|
||||||
from llm_classes.llama_vision import LlamaVision
|
from llm_classes.llama_vision import LlamaVision
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Créer les répertoires de résultats s'ils n'existent pas
|
||||||
|
os.makedirs("results/ocr_brut", exist_ok=True)
|
||||||
|
os.makedirs("results/ocr_avance", exist_ok=True)
|
||||||
|
|
||||||
# Instanciation du modèle
|
# Instanciation du modèle
|
||||||
model = LlamaVision()
|
model = LlamaVision()
|
||||||
@ -17,3 +22,7 @@ image_path = "output/ticket_T11143/T11143_20250422_084617/attachments/image_1454
|
|||||||
res = agent.executer(image_path)
|
res = agent.executer(image_path)
|
||||||
print(f"\n🔵 Résultat pour l'image {image_path}:")
|
print(f"\n🔵 Résultat pour l'image {image_path}:")
|
||||||
print(f"Texte extrait:\n{res['extracted_text']}\n")
|
print(f"Texte extrait:\n{res['extracted_text']}\n")
|
||||||
|
|
||||||
|
# Affichage des chemins de sortie
|
||||||
|
print(f"✅ Résultats OCR brut sauvegardés dans: results/ocr_brut/")
|
||||||
|
print(f"✅ Résultats OCR avancé sauvegardés dans: results/ocr_avance/")
|
||||||
|
|||||||
@ -5,5 +5,21 @@ Package utils contenant des utilitaires pour le traitement d'images et autres fo
|
|||||||
# Pas besoin de préfixer avec 'utils.' quand on est déjà dans le package
|
# Pas besoin de préfixer avec 'utils.' quand on est déjà dans le package
|
||||||
from .image_dedup import filtrer_images_uniques
|
from .image_dedup import filtrer_images_uniques
|
||||||
|
|
||||||
|
# Compatibilité avec les anciens imports après la réorganisation des fichiers OCR
|
||||||
|
from utils.ocr_brut import extraire_texte, extraire_texte_fr, preprocess_image, preprocess_image_with_profile, PREPROCESSING_PROFILES
|
||||||
|
from utils.ocr_avance import prepare_image_for_llama_vision, clean_text_with_profiles
|
||||||
|
|
||||||
# Exposer les fonctions principales
|
# Exposer les fonctions principales
|
||||||
__all__ = ['filtrer_images_uniques']
|
__all__ = [
|
||||||
|
# OCR Brut (Tesseract)
|
||||||
|
'extraire_texte',
|
||||||
|
'extraire_texte_fr',
|
||||||
|
'preprocess_image',
|
||||||
|
'preprocess_image_with_profile',
|
||||||
|
'PREPROCESSING_PROFILES',
|
||||||
|
|
||||||
|
# OCR Avancé (Llama Vision)
|
||||||
|
'prepare_image_for_llama_vision',
|
||||||
|
'clean_text_with_profiles',
|
||||||
|
'filtrer_images_uniques'
|
||||||
|
]
|
||||||
@ -1,5 +1,12 @@
|
|||||||
|
"""
|
||||||
|
!!! FICHIER OBSOLÈTE !!!
|
||||||
|
Ce fichier est maintenu uniquement pour la compatibilité.
|
||||||
|
Veuillez utiliser les modules dans utils/ocr_avance/ à la place.
|
||||||
|
"""
|
||||||
|
|
||||||
from PIL import Image, ImageOps
|
from PIL import Image, ImageOps
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
BICUBIC = Image.Resampling.BICUBIC # Nouvelle façon d'accéder à BICUBIC
|
BICUBIC = Image.Resampling.BICUBIC # Nouvelle façon d'accéder à BICUBIC
|
||||||
|
|
||||||
|
|||||||
32
utils/ocr_avance/README.md
Normal file
32
utils/ocr_avance/README.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Module OCR Avancé (Llama Vision)
|
||||||
|
|
||||||
|
Ce module contient les outils pour l'extraction de texte avancée utilisant le modèle Llama Vision.
|
||||||
|
|
||||||
|
## Fichiers principaux
|
||||||
|
|
||||||
|
- `image_preparer.py` : Prépare les images pour être utilisées avec le modèle Llama Vision
|
||||||
|
- `ocr_cleaner.py` : Nettoie et améliore le texte extrait par l'OCR
|
||||||
|
- Dictionnaires de nettoyage :
|
||||||
|
- `ocr_clean_dict.json` : Corrections de base pour l'OCR
|
||||||
|
- `hallucination_filter.json` : Filtres pour les hallucinations du modèle
|
||||||
|
- `translation_clean_dict.json` : Corrections pour les erreurs de traduction
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
```python
|
||||||
|
from utils.ocr_avance import prepare_image_for_llama_vision, clean_text_with_profiles
|
||||||
|
|
||||||
|
# Préparation d'une image pour Llama Vision
|
||||||
|
image_pretraitee = prepare_image_for_llama_vision("chemin/vers/image.jpg")
|
||||||
|
|
||||||
|
# Nettoyage du texte extrait
|
||||||
|
texte_propre = clean_text_with_profiles(texte_brut, active_profiles=("ocr", "hallucination"))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Résultats
|
||||||
|
|
||||||
|
Les images prétraitées et les résultats de l'OCR sont sauvegardés dans le répertoire `results/ocr_avance/`.
|
||||||
|
|
||||||
|
## Intégration avec l'agent
|
||||||
|
|
||||||
|
Ce module est utilisé par l'agent `AgentVisionOCR` situé dans `agents/llama_vision/agent_vision_ocr.py`.
|
||||||
8
utils/ocr_avance/__init__.py
Normal file
8
utils/ocr_avance/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from utils.ocr_avance.image_preparer import prepare_image_for_llama_vision
|
||||||
|
from utils.ocr_avance.ocr_cleaner import clean_text_with_profiles
|
||||||
|
|
||||||
|
# Compatibilité rétroactive
|
||||||
|
__all__ = [
|
||||||
|
'prepare_image_for_llama_vision',
|
||||||
|
'clean_text_with_profiles'
|
||||||
|
]
|
||||||
10
utils/ocr_avance/hallucination_filter.json
Normal file
10
utils/ocr_avance/hallucination_filter.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"The following information is fictional": "",
|
||||||
|
"This content is autogenerated and may not reflect reality": "",
|
||||||
|
"Lorem ipsum": "",
|
||||||
|
"As an AI language model": "",
|
||||||
|
"Note: The above is a sample output": "",
|
||||||
|
"BRG-LAB is a fictional laboratory": "BRG-LAB",
|
||||||
|
"This is a placeholder text": ""
|
||||||
|
}
|
||||||
|
|
||||||
32
utils/ocr_avance/image_preparer.py
Normal file
32
utils/ocr_avance/image_preparer.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
from PIL import Image, ImageOps
|
||||||
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
BICUBIC = Image.Resampling.BICUBIC # Nouvelle façon d'accéder à BICUBIC
|
||||||
|
|
||||||
|
def prepare_image_for_llama_vision(input_path: str, output_path: Optional[str] = None, size=(672, 672)) -> str:
|
||||||
|
"""Prépare une image pour être utilisée avec le modèle Llama Vision en la redimensionnant et en ajoutant du padding."""
|
||||||
|
from PIL import ImageOps, Image
|
||||||
|
|
||||||
|
# Si aucun chemin de sortie n'est spécifié, utiliser le répertoire par défaut
|
||||||
|
if output_path is None:
|
||||||
|
os.makedirs("results/ocr_avance", exist_ok=True)
|
||||||
|
image_name = Path(input_path).stem
|
||||||
|
output_path = f"results/ocr_avance/vision_ready_{image_name}.png"
|
||||||
|
|
||||||
|
img = Image.open(input_path)
|
||||||
|
if img.mode != "RGB":
|
||||||
|
img = img.convert("RGB")
|
||||||
|
|
||||||
|
# Redimensionne en conservant le ratio
|
||||||
|
img.thumbnail(size, Image.Resampling.BICUBIC)
|
||||||
|
|
||||||
|
# Ajoute du padding pour obtenir exactement 672x672
|
||||||
|
padded_img = Image.new("RGB", size, (255, 255, 255)) # fond blanc
|
||||||
|
offset = ((size[0] - img.width) // 2, (size[1] - img.height) // 2)
|
||||||
|
padded_img.paste(img, offset)
|
||||||
|
|
||||||
|
padded_img.save(output_path, format="PNG", optimize=True)
|
||||||
|
return output_path
|
||||||
|
|
||||||
8
utils/ocr_avance/ocr_clean_dict.json
Normal file
8
utils/ocr_avance/ocr_clean_dict.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"zkt1.brg-lab.com": "zk1.brg-lab.com",
|
||||||
|
"ADEO": "ADCEG",
|
||||||
|
"ADEIG": "ADCEG",
|
||||||
|
"RA.Z.": "RAZ",
|
||||||
|
"NF EN 9933-9": "NF EN 933-9"
|
||||||
|
}
|
||||||
|
|
||||||
59
utils/ocr_avance/ocr_cleaner.py
Normal file
59
utils/ocr_avance/ocr_cleaner.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# 🧩 Dictionnaires disponibles (clés = profils activables)
|
||||||
|
CLEAN_DICT_FILES = {
|
||||||
|
"ocr": "ocr_clean_dict.json",
|
||||||
|
"translation": "translation_clean_dict.json",
|
||||||
|
"hallucination": "hallucination_filter.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 📁 Chemin racine de tous les dictionnaires
|
||||||
|
BASE_PATH = Path(__file__).parent
|
||||||
|
|
||||||
|
def load_cleaning_dict(path):
|
||||||
|
"""Charge un dictionnaire de nettoyage JSON."""
|
||||||
|
if not path.exists():
|
||||||
|
return {}
|
||||||
|
with open(path, "r", encoding="utf-8") as f:
|
||||||
|
return json.load(f)
|
||||||
|
|
||||||
|
def load_multiple_dicts(active_keys):
|
||||||
|
"""Charge et fusionne plusieurs dictionnaires selon les profils sélectionnés."""
|
||||||
|
merged_dict = {}
|
||||||
|
for key in active_keys:
|
||||||
|
filename = CLEAN_DICT_FILES.get(key)
|
||||||
|
if filename:
|
||||||
|
path = BASE_PATH / filename
|
||||||
|
data = load_cleaning_dict(path)
|
||||||
|
merged_dict.update(data)
|
||||||
|
return merged_dict
|
||||||
|
|
||||||
|
def clean_ocr_text(text, cleaning_dict=None):
|
||||||
|
"""Applique les corrections d’un dictionnaire sur un texte."""
|
||||||
|
if cleaning_dict is None:
|
||||||
|
return text
|
||||||
|
for wrong, correct in cleaning_dict.items():
|
||||||
|
text = text.replace(wrong, correct)
|
||||||
|
return text
|
||||||
|
|
||||||
|
def clean_text_with_profiles(text, active_profiles=("ocr",)):
|
||||||
|
"""
|
||||||
|
Nettoie un texte avec un ou plusieurs profils activés.
|
||||||
|
Profils possibles : "ocr", "translation", "hallucination"
|
||||||
|
"""
|
||||||
|
cleaning_dict = load_multiple_dicts(active_profiles)
|
||||||
|
return clean_ocr_text(text, cleaning_dict)
|
||||||
|
|
||||||
|
def add_to_cleaning_dict(wrong, correct, profile="ocr"):
|
||||||
|
"""
|
||||||
|
Ajoute une paire (erreur, correction) à un dictionnaire spécifique.
|
||||||
|
"""
|
||||||
|
filename = CLEAN_DICT_FILES.get(profile)
|
||||||
|
if not filename:
|
||||||
|
raise ValueError(f"Profil inconnu : {profile}")
|
||||||
|
path = BASE_PATH / filename
|
||||||
|
data = load_cleaning_dict(path)
|
||||||
|
data[wrong] = correct
|
||||||
|
with open(path, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||||
12
utils/ocr_avance/translation_clean_dict.json
Normal file
12
utils/ocr_avance/translation_clean_dict.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"bearing capacity": "capacité portante",
|
||||||
|
"liquid limit": "limite de liquidité",
|
||||||
|
"air voids": "vides d'air",
|
||||||
|
"CEMENT": "ciment",
|
||||||
|
"AGGREGATE": "granulat",
|
||||||
|
"IT IS NOT RELEVANT": "NON APPLICABLE",
|
||||||
|
"SPECIMEN": "ÉCHANTILLON",
|
||||||
|
"trial mixture": "mélange d'essai",
|
||||||
|
"test": "essai"
|
||||||
|
}
|
||||||
|
|
||||||
30
utils/ocr_brut/README.md
Normal file
30
utils/ocr_brut/README.md
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Module OCR Brut (Tesseract)
|
||||||
|
|
||||||
|
Ce module contient les outils pour l'extraction de texte basique à partir d'images en utilisant Tesseract OCR.
|
||||||
|
|
||||||
|
## Fichiers principaux
|
||||||
|
|
||||||
|
- `ocr_utils.py` : Fonctions principales d'extraction de texte avec Tesseract
|
||||||
|
- `ocr_preprocessor.py` : Prétraitement d'images pour améliorer la qualité de l'OCR
|
||||||
|
|
||||||
|
## Configuration par défaut
|
||||||
|
|
||||||
|
- Profil de prétraitement : "document"
|
||||||
|
- PSM (Page Segmentation Mode) : 11 (Texte sparse)
|
||||||
|
- OEM (OCR Engine Mode) : 3 (par défaut)
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
```python
|
||||||
|
from utils.ocr_brut import extraire_texte, extraire_texte_fr
|
||||||
|
|
||||||
|
# OCR multilingue avec détection automatique
|
||||||
|
texte, image_optimisee = extraire_texte("chemin/vers/image.jpg")
|
||||||
|
|
||||||
|
# OCR français optimisé
|
||||||
|
texte_fr = extraire_texte_fr("chemin/vers/image.jpg")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Résultats
|
||||||
|
|
||||||
|
Les résultats du prétraitement et de l'OCR sont sauvegardés dans le répertoire `results/ocr_brut/`.
|
||||||
11
utils/ocr_brut/__init__.py
Normal file
11
utils/ocr_brut/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from utils.ocr_brut.ocr_utils import extraire_texte, extraire_texte_fr
|
||||||
|
from utils.ocr_brut.ocr_preprocessor import preprocess_image, preprocess_image_with_profile, PREPROCESSING_PROFILES
|
||||||
|
|
||||||
|
# Compatibilité rétroactive
|
||||||
|
__all__ = [
|
||||||
|
'extraire_texte',
|
||||||
|
'extraire_texte_fr',
|
||||||
|
'preprocess_image',
|
||||||
|
'preprocess_image_with_profile',
|
||||||
|
'PREPROCESSING_PROFILES'
|
||||||
|
]
|
||||||
159
utils/ocr_brut/ocr_preprocessor.py
Normal file
159
utils/ocr_brut/ocr_preprocessor.py
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
# ocr_preprocessor.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
from PIL import Image, ImageEnhance
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import time
|
||||||
|
|
||||||
|
# === 🎛️ PROFILS DE TRAITEMENT D'IMAGE OCR ===
|
||||||
|
PREPROCESSING_PROFILES = {
|
||||||
|
"default": {
|
||||||
|
"resize_min_dim": 1000, # 📏 Si largeur/hauteur < 1000px, image agrandie proportionnellement
|
||||||
|
"enhance_contrast": True, # 🔆 Active l'amélioration du contraste
|
||||||
|
"contrast_factor": 1.2, # >1 = plus contrasté, typique : 1.2 à 1.8
|
||||||
|
"enhance_sharpness": False, # 💥 Active la netteté
|
||||||
|
"sharpness_factor": 1.0, # >1 = plus net, typique : 1.2 à 2.0
|
||||||
|
"apply_denoising": False, # 🚿 Réduction de bruit
|
||||||
|
"denoise_strength": {
|
||||||
|
"h": 0, # 0 à 15 : intensité du lissage luminance
|
||||||
|
"hColor": 0, # 0 à 15 : lissage chroma
|
||||||
|
"templateWindowSize": 7, # Taille du patch à comparer (typiquement 7)
|
||||||
|
"searchWindowSize": 21 # Zone autour du patch pour recherche (typiquement 21)
|
||||||
|
},
|
||||||
|
"invert_colors": False, # ↕️ Inversion si texte clair sur fond sombre
|
||||||
|
"apply_clahe": False, # 📈 Égalisation du contraste local (utile en cas de zones très sombres/claires)
|
||||||
|
"save_debug_output": True,
|
||||||
|
"debug_output_dir": "results/ocr_brut/preprocessed"
|
||||||
|
},
|
||||||
|
"aggressive": {
|
||||||
|
"resize_min_dim": 1400,
|
||||||
|
"enhance_contrast": True,
|
||||||
|
"contrast_factor": 1.8,
|
||||||
|
"enhance_sharpness": True,
|
||||||
|
"sharpness_factor": 1.5,
|
||||||
|
"apply_denoising": True,
|
||||||
|
"denoise_strength": {
|
||||||
|
"h": 10,
|
||||||
|
"hColor": 10,
|
||||||
|
"templateWindowSize": 7,
|
||||||
|
"searchWindowSize": 21
|
||||||
|
},
|
||||||
|
"invert_colors": False,
|
||||||
|
"apply_clahe": False,
|
||||||
|
"save_debug_output": True,
|
||||||
|
"debug_output_dir": "results/ocr_brut/preprocessed"
|
||||||
|
},
|
||||||
|
"document": {
|
||||||
|
"resize_min_dim": 1100,
|
||||||
|
"enhance_contrast": True,
|
||||||
|
"contrast_factor": 1.2,
|
||||||
|
"enhance_sharpness": False,
|
||||||
|
"sharpness_factor": 1.0,
|
||||||
|
"apply_denoising": False,
|
||||||
|
"denoise_strength": {"h": 0, "hColor": 0, "templateWindowSize": 7, "searchWindowSize": 21},
|
||||||
|
"invert_colors": False,
|
||||||
|
"apply_clahe": False,
|
||||||
|
"save_debug_output": True,
|
||||||
|
"debug_output_dir": "results/ocr_brut/preprocessed"
|
||||||
|
},
|
||||||
|
"clahe_high": {
|
||||||
|
"resize_min_dim": 1200,
|
||||||
|
"enhance_contrast": True,
|
||||||
|
"contrast_factor": 1.4,
|
||||||
|
"enhance_sharpness": True,
|
||||||
|
"sharpness_factor": 1.3,
|
||||||
|
"apply_denoising": True,
|
||||||
|
"denoise_strength": {
|
||||||
|
"h": 7,
|
||||||
|
"hColor": 7,
|
||||||
|
"templateWindowSize": 7, # Taille du patch local utilisé
|
||||||
|
"searchWindowSize": 21 # Zone de recherche du filtre
|
||||||
|
},
|
||||||
|
"invert_colors": False,
|
||||||
|
"apply_clahe": True,
|
||||||
|
"save_debug_output": True,
|
||||||
|
"debug_output_dir": "results/ocr_brut/preprocessed"
|
||||||
|
},
|
||||||
|
"invert_light": {
|
||||||
|
"resize_min_dim": 1200,
|
||||||
|
"enhance_contrast": True,
|
||||||
|
"contrast_factor": 1.3,
|
||||||
|
"enhance_sharpness": True,
|
||||||
|
"sharpness_factor": 1.4,
|
||||||
|
"apply_denoising": False,
|
||||||
|
"invert_colors": True,
|
||||||
|
"apply_clahe": False,
|
||||||
|
"save_debug_output": True,
|
||||||
|
"debug_output_dir": "results/ocr_brut/preprocessed"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def preprocess_image(image_path: str, **settings) -> Image.Image:
|
||||||
|
img = Image.open(image_path).convert("RGB")
|
||||||
|
base_name = os.path.basename(image_path)
|
||||||
|
|
||||||
|
# Gestion des dossiers de debug
|
||||||
|
debug_dir = settings.get("debug_output_dir", "results/ocr_brut/preprocessed")
|
||||||
|
profile_name = settings.get("profile_name", "default") # Ajout du nom du profil
|
||||||
|
debug_profile_dir = os.path.join(debug_dir, profile_name)
|
||||||
|
os.makedirs(debug_profile_dir, exist_ok=True)
|
||||||
|
|
||||||
|
# Redimensionnement
|
||||||
|
if settings.get("resize_min_dim", 0) > 0:
|
||||||
|
width, height = img.size
|
||||||
|
min_dim = min(width, height)
|
||||||
|
if min_dim < settings["resize_min_dim"]:
|
||||||
|
scale = settings["resize_min_dim"] / min_dim
|
||||||
|
new_size = (int(width * scale), int(height * scale))
|
||||||
|
img = img.resize(new_size, Image.Resampling.BICUBIC)
|
||||||
|
|
||||||
|
# Contraste
|
||||||
|
if settings.get("enhance_contrast", False):
|
||||||
|
enhancer = ImageEnhance.Contrast(img)
|
||||||
|
img = enhancer.enhance(settings.get("contrast_factor", 1.5))
|
||||||
|
|
||||||
|
# Netteté
|
||||||
|
if settings.get("enhance_sharpness", False):
|
||||||
|
enhancer = ImageEnhance.Sharpness(img)
|
||||||
|
img = enhancer.enhance(settings.get("sharpness_factor", 1.5))
|
||||||
|
|
||||||
|
# Convert to OpenCV image
|
||||||
|
img_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
|
||||||
|
|
||||||
|
# Débruitage
|
||||||
|
if settings.get("apply_denoising", False):
|
||||||
|
strength = settings.get("denoise_strength", {})
|
||||||
|
img_cv = cv2.fastNlMeansDenoisingColored(
|
||||||
|
img_cv,
|
||||||
|
None,
|
||||||
|
h=strength.get("h", 10),
|
||||||
|
hColor=strength.get("hColor", 10),
|
||||||
|
templateWindowSize=strength.get("templateWindowSize", 7),
|
||||||
|
searchWindowSize=strength.get("searchWindowSize", 21)
|
||||||
|
)
|
||||||
|
|
||||||
|
# CLAHE
|
||||||
|
if settings.get("apply_clahe", False):
|
||||||
|
lab = cv2.cvtColor(img_cv, cv2.COLOR_BGR2LAB)
|
||||||
|
l, a, b = cv2.split(lab)
|
||||||
|
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
|
||||||
|
cl = clahe.apply(l)
|
||||||
|
img_cv = cv2.merge((cl, a, b))
|
||||||
|
img_cv = cv2.cvtColor(img_cv, cv2.COLOR_LAB2BGR)
|
||||||
|
|
||||||
|
# Inversion
|
||||||
|
if settings.get("invert_colors", False):
|
||||||
|
img_cv = cv2.bitwise_not(img_cv)
|
||||||
|
|
||||||
|
# Sauvegarde image prétraitée (debug)
|
||||||
|
if settings.get("save_debug_output", False):
|
||||||
|
debug_path = os.path.join(debug_profile_dir, f"optimized_{base_name}")
|
||||||
|
cv2.imwrite(debug_path, img_cv)
|
||||||
|
|
||||||
|
return Image.fromarray(cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB))
|
||||||
|
|
||||||
|
def preprocess_image_with_profile(image_path: str, profile_name="default") -> Image.Image:
|
||||||
|
settings = PREPROCESSING_PROFILES[profile_name].copy() # On fait une copie pour ne pas modifier l'original
|
||||||
|
settings["profile_name"] = profile_name # On ajoute le nom du profil aux paramètres
|
||||||
|
return preprocess_image(image_path, **settings)
|
||||||
103
utils/ocr_brut/ocr_utils.py
Normal file
103
utils/ocr_brut/ocr_utils.py
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
import pytesseract
|
||||||
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image
|
||||||
|
from langdetect import detect
|
||||||
|
import re
|
||||||
|
from utils.ocr_brut.ocr_preprocessor import preprocess_image_with_profile
|
||||||
|
|
||||||
|
# ⬇️ PARAMÈTRES CENTRAUX D'ACTIVATION ⬇️
|
||||||
|
USE_PREPROCESSING = True # Active le prétraitement de l'image via ocr_preprocessor.py
|
||||||
|
USE_TEXT_CORRECTION = True # Corrige les mots tronqués après OCR
|
||||||
|
SAVE_DEBUG_OUTPUT = True # Sauvegarde image + texte dans debug_ocr/
|
||||||
|
AUTO_DETECT_LANGUAGE = True # Détecte automatiquement la langue
|
||||||
|
|
||||||
|
# Paramètres Tesseract optimaux selon tests
|
||||||
|
OCR_DEFAULT_PSM = 11 # Page segmentation mode 11 (sparse text)
|
||||||
|
OCR_DEFAULT_OEM = 3 # OCR Engine mode 3 (default, based on what is available)
|
||||||
|
OCR_DEFAULT_PROFILE = "document" # Profil de prétraitement optimal selon tests
|
||||||
|
|
||||||
|
# Complétion de mots tronqués (rudimentaire mais utile)
|
||||||
|
def completer_mots_tronques(texte):
|
||||||
|
lignes = texte.splitlines()
|
||||||
|
lignes_corrigees = []
|
||||||
|
for ligne in lignes:
|
||||||
|
if ligne.strip().endswith("-"):
|
||||||
|
ligne = ligne.strip()[:-1]
|
||||||
|
lignes_corrigees.append(ligne)
|
||||||
|
return "\n".join(lignes_corrigees)
|
||||||
|
|
||||||
|
# Détection de langue automatique (si activée)
|
||||||
|
def detect_language_tesseract(image_cv):
|
||||||
|
try:
|
||||||
|
text_sample = pytesseract.image_to_string(image_cv, config="--psm 6")
|
||||||
|
lang = detect(text_sample)
|
||||||
|
return {
|
||||||
|
"fr": "fra",
|
||||||
|
"en": "eng"
|
||||||
|
}.get(lang, "fra+eng")
|
||||||
|
except:
|
||||||
|
return "fra+eng"
|
||||||
|
|
||||||
|
# OCR principal
|
||||||
|
def extraire_texte(image_path, lang="auto"):
|
||||||
|
# Vérification de l'existence de l'image
|
||||||
|
if not os.path.exists(image_path):
|
||||||
|
print(f"[OCR] Image non trouvée: {image_path}")
|
||||||
|
return "", None
|
||||||
|
|
||||||
|
# Prétraitement de l'image avec le profil optimal
|
||||||
|
if USE_PREPROCESSING:
|
||||||
|
img_optimized = preprocess_image_with_profile(image_path, profile_name=OCR_DEFAULT_PROFILE)
|
||||||
|
else:
|
||||||
|
img_optimized = Image.open(image_path)
|
||||||
|
|
||||||
|
# Détection de langue
|
||||||
|
ocr_lang = lang
|
||||||
|
if lang == "auto" and AUTO_DETECT_LANGUAGE:
|
||||||
|
ocr_lang = detect_language_tesseract(img_optimized)
|
||||||
|
if ocr_lang == "auto":
|
||||||
|
ocr_lang = "fra+eng"
|
||||||
|
|
||||||
|
# OCR avec paramètres optimaux
|
||||||
|
config = f"--psm {OCR_DEFAULT_PSM} --oem {OCR_DEFAULT_OEM} -l {ocr_lang}"
|
||||||
|
texte = pytesseract.image_to_string(img_optimized, config=config)
|
||||||
|
|
||||||
|
# Correction des mots tronqués
|
||||||
|
if USE_TEXT_CORRECTION:
|
||||||
|
texte_corrige = completer_mots_tronques(texte)
|
||||||
|
if len(texte_corrige) >= len(texte) * 0.9:
|
||||||
|
texte = texte_corrige
|
||||||
|
|
||||||
|
# Sauvegarde debug (si activée)
|
||||||
|
if SAVE_DEBUG_OUTPUT and texte:
|
||||||
|
try:
|
||||||
|
debug_dir = "results/ocr_brut"
|
||||||
|
os.makedirs(debug_dir, exist_ok=True)
|
||||||
|
image_name = Path(image_path).stem
|
||||||
|
|
||||||
|
# Conversion si image PIL
|
||||||
|
if isinstance(img_optimized, Image.Image):
|
||||||
|
img_optimized = np.array(img_optimized)
|
||||||
|
if img_optimized.ndim == 3 and img_optimized.shape[2] == 3:
|
||||||
|
img_optimized = cv2.cvtColor(img_optimized, cv2.COLOR_RGB2BGR)
|
||||||
|
elif img_optimized.ndim == 3 and img_optimized.shape[2] == 4:
|
||||||
|
img_optimized = cv2.cvtColor(img_optimized, cv2.COLOR_RGBA2BGR)
|
||||||
|
|
||||||
|
if isinstance(img_optimized, np.ndarray):
|
||||||
|
cv2.imwrite(f"{debug_dir}/optimized_{image_name}.png", img_optimized)
|
||||||
|
|
||||||
|
with open(f"{debug_dir}/ocr_{image_name}.png.txt", "w", encoding="utf-8") as f:
|
||||||
|
f.write(texte)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[OCR DEBUG] Erreur de sauvegarde debug: {e}")
|
||||||
|
|
||||||
|
return texte, img_optimized
|
||||||
|
|
||||||
|
# Raccourci rapide pour juste récupérer le texte en français
|
||||||
|
def extraire_texte_fr(image_path):
|
||||||
|
texte, _ = extraire_texte(image_path, lang="fra")
|
||||||
|
return texte
|
||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
!!! FICHIER OBSOLÈTE !!!
|
||||||
|
Ce fichier est maintenu uniquement pour la compatibilité.
|
||||||
|
Veuillez utiliser les modules dans utils/ocr_avance/ à la place.
|
||||||
|
"""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@ -30,7 +36,7 @@ def load_multiple_dicts(active_keys):
|
|||||||
return merged_dict
|
return merged_dict
|
||||||
|
|
||||||
def clean_ocr_text(text, cleaning_dict=None):
|
def clean_ocr_text(text, cleaning_dict=None):
|
||||||
"""Applique les corrections d’un dictionnaire sur un texte."""
|
"""Applique les corrections d'un dictionnaire sur un texte."""
|
||||||
if cleaning_dict is None:
|
if cleaning_dict is None:
|
||||||
return text
|
return text
|
||||||
for wrong, correct in cleaning_dict.items():
|
for wrong, correct in cleaning_dict.items():
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
!!! FICHIER OBSOLÈTE !!!
|
||||||
|
Ce fichier est maintenu uniquement pour la compatibilité.
|
||||||
|
Veuillez utiliser les modules dans utils/ocr_brut/ à la place.
|
||||||
|
"""
|
||||||
|
|
||||||
# ocr_preprocessor.py
|
# ocr_preprocessor.py
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
!!! FICHIER OBSOLÈTE !!!
|
||||||
|
Ce fichier est maintenu uniquement pour la compatibilité.
|
||||||
|
Veuillez utiliser les modules dans utils/ocr_brut/ à la place.
|
||||||
|
"""
|
||||||
|
|
||||||
import pytesseract
|
import pytesseract
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -6,7 +12,7 @@ from pathlib import Path
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from langdetect import detect
|
from langdetect import detect
|
||||||
import re
|
import re
|
||||||
from utils.ocr_preprocessor import preprocess_image_with_profile
|
from utils.ocr_brut.ocr_preprocessor import preprocess_image_with_profile
|
||||||
|
|
||||||
# ⬇️ PARAMÈTRES CENTRAUX D'ACTIVATION ⬇️
|
# ⬇️ PARAMÈTRES CENTRAUX D'ACTIVATION ⬇️
|
||||||
USE_PREPROCESSING = True # Active le prétraitement de l'image via ocr_preprocessor.py
|
USE_PREPROCESSING = True # Active le prétraitement de l'image via ocr_preprocessor.py
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user