fix: retour relecteur #2 — page scannée noire, labels DPI, stop-words

- 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) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 12:11:26 +01:00
parent ad7f1ffa8a
commit 65a02952c5

View File

@@ -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