feat(privacy): trefwoorden met woordgrenzen, en een gezicht op een dia telt ook #363
No reviewers
Labels
No labels
accepted
bug
declined
docs
duplicate
enhancement
good first issue
in-progress
needs-info
privacy
release-blocker
security
triage
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
LibreKAT/Ocideck!363
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/privacy-quality-badges"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Vervolg op #357. Vijf commits,
make checkgroen op de huidige main.Wat er misging in de tekstcontrole
De trefwoordmatcher was een kale
indexOfzonder woordgrenzen. Gemeten op de echte scanner:De vogels vliegen over het weilandmedicatie-expertiseMarieke de Vries wordt verdacht van diefstalDie laatste is de vervelendste: de lijst bevatte de verbogen vorm
verdachte, waardoor de gebruikelijkste formulering van precies het geval waar artikel 10 over gaat volledig gemist werd. De matcher kent nu twee modi — korte termen (hiv,ggz,vog) alleen als héél woord, langere op woordbegin met een vrij achtervoegsel, want de Nederlandse morfologie is suffigerend.En redactie werkte op trefwoordniveau:
Jan had een diagnose bij de huisartswerdJan had een ████████ bij de huisarts. Er wordt niets verborgen, "Jan" blijft staan, en de ontvanger concludeert uit het blok dat daar iets stond.PrivacyTermRolescheidt nu de aanwijzing van het gegeven — een onderscheid dat de Autoriteit Persoonsgegevens zelf hanteert: "Gegevens die hooguit een indicatie geven … zijn niet voldoende".De beeldcontrole
Een afbeelding waarop iemand herkenbaar staat is een persoonsgegeven, ook zonder naam. De tekstscanner kan dat per definitie niet vinden — die leest
mem:11162735-….YuNet (OpenCV Zoo, MIT, 232 KB) via
opencv_core, volledig lokaal. Kosten: 27 MBDartCvMacOS.framework, gemeten. Web verliest de functie en zegt dat viaisSupported.Aanwezigheid, nooit identiteit. Het model levert per gezicht een kader, vijf landmarks en een score; alleen het aantal blijft over. Geen sjabloon, niets opgeslagen, niets vergeleken. Dat is wat dit buiten artikel 9-biometrie houdt (EDPB 3/2019 §74-76), en er staat een expliciete grensmarkering op de regel waar dat mis zou gaan.
Drie fouten die de meting op echte foto's blootlegde
HEIC meldde nul. OpenCV leest het niet,
imdecodegaf een lege matrix, en dat werd gerapporteerd als "geen gezichten" — terwijl iPhone-foto's standaard HEIC zijn.facesenreadablezijn nu gescheiden.Eén vaste breedte verloor gezichten. Per foto verschilt de beste schaal; drie schalen met het maximum eroverheen lost het op.
En de scoredrempel stond bijna op een klif:
Op 0,95 vindt de detector letterlijk niets. 0,80 ligt in het midden van het plateau, dus zo ver mogelijk van beide kliffen. Effect: groepsfoto van 3 naar 8 van 8, totaal van 8 naar 14, valse positieven onveranderd nul, en sneller (497 ms tegen 731 ms).
Ook gemeten en daarom niet gebouwd: extra tussenschalen en CLAHE-contrastnormalisatie leverden geen enkel extra gezicht op.
Documentatie
OCIWACHT.md§13 bevat het lexiconmodel, de meertaligheidsstrategie in drie lagen, de pijplijnvolgorde en de fasering 9-14. Inclusief twee expliciete "bewust niet gedaan"-secties (geen NER — er is geen Nederlandse parser die offline in Dart draait; geen gehashte woordenlijst — de privacy van een bloomfilter ís de min-entropie van de invoer).PRIVACY.mdvertelt nu dát er een neuraal netwerk over je afbeeldingen gaat en waarom dat geen biometrie is.Voorbehoud
Zeven foto's en elf negatieven is een kleine steekproef; het plateau is geruststellend maar dit is geen benchmark. En de CI zet
DARTCV_LIB_PATHnog niet — zonder die variabele staan de twee detectietests permanent op skipped.🤖 Generated with Claude Code
vogis geen vogel 951f68e62eTwee fouten die samenhangen, allebei gemeten op de echte scanner. De matcher was een kale `indexOf`. Daardoor meldde "De vogels vliegen over het weiland" een strafrechtelijk gegeven, en "medicatie-expertise" een gezondheidsgegeven. Er zit nu een woordgrens omheen, met twee modi: korte termen (`hiv`, `ggz`, `vog`) matchen alleen als héél woord, langere op woordbegin met een vrij achtervoegsel. Dat laatste is geen luxe maar noodzaak — Nederlandse morfologie is vrijwel volledig suffigerend, en de lijst bevatte de verbogen vorm `verdachte`. Daardoor werd "wordt verdacht van diefstal", de gebruikelijkste formulering van precies het geval waar artikel 10 over gaat, volledig gemist. De stam staat er nu, en dekt `verdachte`, `verdachten` en `verdachtmaking` mee. En redactie werkte op trefwoordniveau: Jan had een diagnose bij de huisarts Jan had een ████████ bij de huisarts Er wordt niets verborgen, "Jan" blijft staan, en de ontvanger concludeert uit het blok dat daar iets gevoeligs stond. Dat is misleidender dan overbodig. `PrivacyTermRole` scheidt daarom de aanwijzing van het gegeven: "diagnose" wijst ergens naar, `F32.1` en een parketnummer zíjn het. Een aanwijzing gaat alleen mee als de escalator haar bereik heeft verbreed tot de hele mededeling — want dán is het gegeven niet het woord maar de uitspraak, en haalt redactie werkelijk iets weg. Dat onderscheid is niet zelfbedacht. De Autoriteit Persoonsgegevens hanteert het in haar eigen handhaving: "Gegevens die hooguit een indicatie geven dat het om een gevoelig kenmerk zou kunnen gaan, zijn niet voldoende" om van een rechtstreeks verband te spreken. Wat dit niet oplost: homoniemen. `arrest` blijft een treffer op een uitspraak van de Hoge Raad. Daar is geen woordgrens tegen bestand; dat vraagt de persoonskoppelingspoort. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>Getest op veertien echte foto's — geen mensen, slecht zichtbare mensen, groepen — en er kwamen twee fouten uit die allebei precies het gedrag vertoonden waar deze controle tegen ontworpen is. ── HEIC meldde nul in plaats van "niet gekeken" ── Alle zeven HEIC-bestanden gaven nul gezichten, in 4 tot 14 milliseconden. Te snel voor een decode: OpenCV kent HEIC niet, `imdecode` geeft een lege matrix, en de code rapporteerde dat als "geen gezichten". iPhone-foto's zijn standaard HEIC, dus een deck vol portretten meldde niets. `ImageFaceScanResult` scheidt daarom `faces` van `readable`, en een onleesbare afbeelding levert een eigen informatieve melding op: "Dat betekent niet dat er niemand op staat — er is niet gekeken." ── Eén vaste breedte verloor de meeste gezichten ── Van zeven leesbare foto's vond de detector er twee. De sweep laat zien waarom: per foto verschilt de béste breedte en geen enkele is overal goed. foto orig 1920 1280 640 startbaan 0 0 1 0 twee personen 3 3 1 0 portret staand 0 - - 1 Drie schalen met het maximum eroverheen vindt er zes van zeven. De zevende is een strandfoto waarop iemand omlaag kijkt met een zonnebril op — die hóórt een gezichtsdetector te missen, en dat is precies waarom de melding "herkenbaar gezicht" zegt en niet "persoon". Kosten: ~40 tot 190 ms per afbeelding, 599 ms voor veertien. Voor een achtergrondcontrole ruim binnen de marge. ── En het getal is nu eerlijk ── Op een groepsfoto van acht mensen bij tegenlicht vindt de detector er drie. Geen valse positieven — een óndertelling. Voor de waarschuwing maakt dat niets uit, want één gezicht is al een persoonsgegeven, maar "toont 3 herkenbare gezichten" zou liegen. Er staat nu "minstens". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>De vraag was of de nauwkeurigheid nog beter kon. Vier knoppen gemeten — scoredrempel, aantal schalen, contrastnormalisatie voor tegenlicht, en opschalen. Eén ervan deed vrijwel alles. drempel gezichten valse-positieven 0,95 0 0 0,92 8 0 0,90 11 0 0,85 14 0 0,80 14 0 0,70 14 0 0,60 15 0 0,50 15 2 Gemeten op zeven echte foto's plus elf mensloze app-assets. Er stond 0,92, door mij gekozen met het argument "liever een gezicht missen dan de gebruiker leren dat de melding onzin is". Dat argument was niet fout, de plaatsing wel: op 0,95 vindt de detector letterlijk niets meer. Ik zat drie honderdsten van een kapotte functie, en ik had het niet gemeten. Tussen 0,85 en 0,70 ligt een vlak gebied waar het aantal niet verandert en er geen enkele valse positief bijkomt. 0,80 ligt daar in het midden en dus zo ver mogelijk van beide kliffen — de recall-klif boven, de precisie-klif bij 0,50. Effect: de groepsfoto van acht mensen bij tegenlicht gaat van drie naar **acht van acht**, en de strandfoto waarvan ik eerder schreef dat een gezichtsdetector hem hoort te missen — hoofd omlaag, zonnebril — wordt nu wél gevonden. Totaal over zeven foto's: van 8 naar 14. Valse positieven: nul, ongewijzigd. En het is sneller: 497 ms tegen 731 ms. Ook gemeten en daarom *niet* gebouwd: extra tussenschalen (960, 480) en CLAHE-contrastnormalisatie leverden geen enkel extra gezicht op. Die complexiteit blijft eruit. De "minstens N"-formulering blijft staan, maar met een betere reden: niet omdat een specifieke groepsfoto ondertelde, maar omdat een gezichtsdetector structureel ondertelt en nooit overtelt — iemand van achteren of met het hoofd buiten de uitsnede ontbreekt per definitie. Voorbehoud dat in de code én in OCIWACHT.md staat: zeven foto's en elf negatieven is een kleine steekproef. Het plateau is geruststellend, maar dit is geen benchmark. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>