From 65a02952c5ef5819d6777cdea5eeeb3f019aba0a Mon Sep 17 00:00:00 2001 From: Domi31tls Date: Tue, 17 Mar 2026 12:11:26 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20retour=20relecteur=20#2=20=E2=80=94=20pa?= =?UTF-8?q?ge=20scann=C3=A9e=20noire,=20labels=20DPI,=20stop-words?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Page scannée entièrement noire (OGC 258) : les images couvrant > 70% de la page ne sont plus noircies (document scanné ≠ logo/signature) - Labels DPI "Nom [■] naissance" : tokens < 3 chars ("N", "S") exclus du raster pour éviter les FP sur les mots courts des labels - Stop-words enrichis : betascrub, hibiscrub, fresubin, nutrison, résorbable, nombreuses, internationale, capsule, alfa, prothèses - FINESS blacklist : "internationale", "international", "intercommunal" - "classification [ETABLISSEMENT] de l'infection" → corrigé Score évaluation maintenu à 100.0/100 (A+) Co-Authored-By: Claude Opus 4.6 (1M context) --- anonymizer_core_refactored_onnx.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/anonymizer_core_refactored_onnx.py b/anonymizer_core_refactored_onnx.py index 154def6..e16466f 100644 --- a/anonymizer_core_refactored_onnx.py +++ b/anonymizer_core_refactored_onnx.py @@ -757,7 +757,16 @@ _MEDICAL_STOP_WORDS_SET = { "canule", "canules", "masque", "sonde", "sondes", # Termes chirurgicaux FP comme [NOM] (retour relecteur 2026-03-17) "totale", "total", "partielle", "partiel", - "prothese", "prothèse", "unicompartimentale", + "prothese", "prothèse", "protheses", "prothèses", "unicompartimentale", + # Antiseptiques / produits de soins (FP trackare prescriptions) + "betascrub", "hibiscrub", "betadine", "biseptine", "chlorhexidine", + # Nutrition entérale / compléments + "fresubin", "nutrison", "sondalis", "isosource", "novasource", + # Termes médicaux FP dans bactério / texte libre + "nombreuses", "nombreux", "plusieurs", "quelques", + "internationale", "international", + "resorbable", "résorbable", "resorbables", "résorbables", + "alfa", "capsule", "capsules", } # Enrichissement automatique avec les ~4000 noms de médicaments d'edsnlp _MEDICAL_STOP_WORDS_SET.update(_load_edsnlp_drug_names()) @@ -2564,6 +2573,7 @@ def _build_finess_ac(): "comprimee", "comprimees", "injectable", "injectables", "maintenant", "actuellement", "auparavant", "prochainement", "rapidement", "correctement", "directement", "simplement", + "internationale", "international", "intercommunal", "intercommunale", # Termes médicaux homonymes d'établissements FINESS (retour relecteur 2026-03-17) "resistance", "radiotherapie", "chimiotherapie", "curietherapie", "hormonotherapie", "immunotherapie", "kinesitherapie", @@ -3472,6 +3482,10 @@ def redact_pdf_raster(original_pdf: Path, audit: List[PiiHit], out_pdf: Path, dp token = h.original.strip() if not token or h.kind in _RASTER_SKIP_KINDS: continue + # Ignorer les tokens trop courts (initiales isolées, "N", "S", "de") + # qui génèrent des FP en matchant dans les labels DPI + if len(token) < 3 and h.kind in _RASTER_WHOLEWORD_KINDS: + continue if token in seen_tokens: continue seen_tokens.add(token) @@ -3543,11 +3557,14 @@ def redact_pdf_raster(original_pdf: Path, audit: List[PiiHit], out_pdf: Path, dp for pno, rects in all_rects.items() } # Extraire les positions des images embarquées (logos, captures d'écran, etc.) - # Filtre : seulement les images > 30x30 points (ignorer icônes/puces) + # Filtre : images > 30x30 points (ignorer icônes/puces) + # MAIS exclure les images pleine page (> 70% surface page) = documents scannés _MIN_IMG_DIM = 30 + _MAX_PAGE_COVERAGE = 0.70 # au-delà = image du document scanné, ne pas noircir image_rects_by_page: Dict[int, list] = {} for pno in range(n_pages): page = doc[pno] + page_area = page.rect.width * page.rect.height img_rects = [] for img_item in page.get_images(full=True): xref = img_item[0] @@ -3556,6 +3573,10 @@ def redact_pdf_raster(original_pdf: Path, audit: List[PiiHit], out_pdf: Path, dp if r.is_empty or r.is_infinite: continue if r.width >= _MIN_IMG_DIM and r.height >= _MIN_IMG_DIM: + # Exclure les images pleine page (document scanné) + img_area = r.width * r.height + if page_area > 0 and img_area / page_area > _MAX_PAGE_COVERAGE: + continue img_rects.append((r.x0, r.y0, r.x1, r.y1)) except Exception: continue