API de floutage: au dessous du capot

Le floutage des images prises dans l’espace public est un passage obligé avant leur publication.

C’est un sujet important pour le projet Panoramax, délicat aussi pour trouver un équilibre entre respect de la vie privée et utilisation des images.

Voici résumé les différentes étapes qui ont permis de mettre en place l’API de floutage utilisée au démarrage du projet.

Détecter les zones à flouter

Lors des premiers essais de floutage, ce sont des algorithmes de segmentation qui ont été utilisés. Ils déterminent pour chaque pixel composant une image à quelle classe d’objet celui-ci est le plus probable d’appartenir.

Exemple de masque issu de segmentation:
blur_mask

Floutage par segmentation sémantique:

Bien sûr les classes d’objets dépendent des données qui ont été utilisées pour entraîner le modèle de segmentation. Chaque image d’entraînement a donc été annotées et délimitant les zones correspondantes aux personnes, véhicules, arbres, bâtiments, etc.
Annoter ce type d’images prends beaucoup de temps, on utilise donc souvent des modèles déjà entraînés ou des données déjà annotées.
Pour notre cas (les vues de rues), des modèles existent mais ont été entraînés sur des images pas forcément ressemblantes au contexte français et qui ont le plus souvent été prises en milieu urbain.

Un autre défaut de la segmentation, c’est la façon d’appliquer le floutage dans l’image d’origine, qui nécessite le plus souvent un traitement global et donc une décompression/recompression de l’image complète avec les pertes associées car les zones à flouter peuvent avoir des formes complexes (polygones).

De la segmentation à la détection d’objets

L’autre technique est la détection d’objets. Pour chaque objet détecté, une zone rectangulaire englobante est retournée avec la classe de l’objet détecté et le taux de confiance.

On peut ici appliquer ensuite un “floutage différentiel” décrit ci-dessous en minimisant les pertes de qualité.

L’annotation est aussi beaucoup plus facile, il suffit de sélectionner un rectangle englobant l’objet dans l’image d’entraînement et d’indiquer de quelle classe il s’agit ce qui se fait relativement vite.

Annoter collaborativement

L’entraînement d’un modèle d’IA repose sur les recettes habituelles en matière de pédagogie: répétition et exemples.

Il faut donc annoter un nombre suffisant d’images pour entraîner correctement le modèle. Dans notre cas c’est un millier de photos qui ont été utilisées, une partie est conservée pour vérifier l’entraînement (la validation). Sur chaque photos ont été repéré à l’aide d’un rectangle les visages, plaques d’immatriculation et panneaux de signalisation (on verra pourquoi cette troisième catégorie).

Travail répétitif, ingrat, un peu long, mais si on le partage c’est nettement plus confortable. C’est ce que l’on a fait en utilisant le logiciel “Label Studio” qui permet de faire une annotation collaborative, donc à plusieurs. En quelques jours c’était fait !

Faux négatifs et faux positifs

Les algorithmes de détection ne sont pas parfaits et on a donc une zone grise où l’on n’est pas sûr de la détection.

Pour chaque détection, les algorithmes donnent un taux de confiance et si l’on ne prend en compte qu’ un taux élevé de confiance, on risque de passer à côté de certaines détections (les faux négatifs).

A l’inverse, si l’on baisse trop le taux de confiance, on va bien diminuer les faux négatifs, mais on va augmenter les faux positifs. On a pris pour un visage ou une plaque d’immatriculation quelque chose d’autre.

Si l’on floute définitivement ces zones dans l’image d’origine qu’on ne conserve pas, on perd définitivement la zone floutée

Le floutage différentiel

L’idée d’un “floutage différentiel” est née pour compenser ces imperfections, voici l’idée générale :

Dans cet exemple, on a détecté deux zones dans l’image originale:

  • on va extraire ces deux zones, et uniquement elles du reste de l’image
  • on applique un floutage dessus
  • on réintègre ces zones floutées à l’originale que l’on ne conserve pas

Si l’on veut pouvoir “déflouter” un faux positif, on peut conserver la zone en question, sans le reste de l’image et sans le contexte (metadonnées).

Le nom du fichier conservé peut être généré par une formule de hachage cryptographique, qui ne permettra pas de remonter à l’image d’origine. On conserve ainsi, un visage ou une plaque mais sans aucun contexte, ce qui est une forme d’anonymisation.

Limiter les pertes de qualité d’image

Ces traitements modifiant une image à la base compressée en format JPEG génèrent des petites pertes de qualité car elles nécessitent une décompression et une recompression qui à chaque fois introduisent une perte de qualité.

C’est là où il faut descendre à un niveau un peu plus bas et comprendre comment les images JPEG sont compressées, car nous ne voulons modifier que de petites parties de l’image (les zones à flouter) et pas l’image entière.

Il se trouve que l’algorithme de compression JPEG n’agit pas sur l’image dans sa globalité mais découpe les images en petits blocs tels que ceci :

mcu_orig_4x_grid

Chaque bloc (appelé “MCU”) est compressé de façon indépendante des autres. L’image JPEG est de plus séparées en plusieurs couches, une de luminance (Y) et deux de chrominance (Cr et Cb) et pour améliorer la compression les couches de chrominance sont “sous-échantillonnées”, c’est à dire qu’on prend les valeur moyennes d’un pixel sur deux, voir un pixel sur 4.

Les MCU de luminance font 8x8 pixels, ceux de chrominances peuvent aller de 8x8 à 16x16 pixels (voir explication).

Il est donc possible de modifier des portions d’images JPEG en remplaçant juste les MCU (blocs de 8x8 à 16x16 pixels) couvrant les zones à flouter et donc sans toucher au reste de l’image. La perte de qualité se limite aux zones à flouter et leur environ proche.

Le outil proposé autour de la librairie JPEG (son petit nom est jpegtran) permettent de faire assez facilement ces manipulations, comme extraire une portion d’image (crop) ou remplacer une portion d’un image par une autre (drop) ou la remplacer par un aplat gris.

Quel niveau de floutage ?

Lors du partage des premiers essais de floutage, plusieurs personnes ont fait remarquer que le floutage ne semblait pas suffisant.

Il faut en effet adapter le niveau de floutage à la taille de la zone concernée. Un visage au loin sera définit par un bien plus petit nombre de pixels qu’un visage plus proche. Il faut donc que le niveau de flou soit proportionnel au nombre de pixels à flouter.

Le plus simple est de pixelliser la zone à flouter, c’est à dire la réduire à un nombre limité de pixels, puis à l’étendre à nouveau à la taille d’origine.

Après quelques recherches en ligne, les algorithmes de reconnaissance faciales semblent actuellement capables de fonctionner avec des visages définis par seulement 24 pixels de côté, ou 12 pixels entre les yeux.

C’est donc une pixellisation complète de la zone (visage complet) à 12 pixels de côté qui a été faite, avec ensuite un flou appliqué pour limiter l’effet visuel et une meilleure intégration dans l’image.

à suivre avec l’implémentation en python…

1 « J'aime »

C’est vrai que la question de la détection du floutage est quelque chose de difficile.

J’ai par exemple uploadé cette photo-sphère où de nombreuses personnes sont présentes :

Même si globalement, le boulot de floutage est fait, il y a des ratés, surement lié aux biais — bien documentés — des modèles d’apprentissages :

  • piqué de l’image (qu’est-ce qui permet d’identifier une personne, en terme de définition…?)
  • vues de profil
  • enfants
  • couleurs de peau

Il y a aussi les problèmes liés à la projection sur les photos-sphères. Je ne sais pas si le modèle prend en compte ces déformations dans le haut et bas de l’image ?

Pour les images 360, le modèle n’est pas bien entraîné et laisse passer pas mal de faux négatifs comme indiqué ici:

On va refaire une annotation d’images 360 pour compléter l’entraînement justement à cause des déformations causées par la projection sphérique.

Pour l’instant, il vaut mieux ne pas verser d’images 360 tant que le modèle n’est pas ré-entraîné.

Dans les annotations qui ont été faites sur les photos non 360, il y avait une bonne diversité sur la qualité des images, les conditions de prise de vue, les résolutions et on a annoté les visages autant de face que partiels ou de profil.
Pour les enfants et la diversité de couleurs de peau, il y a peut être quelques manques (surtout les enfants).

2 « J'aime »

Super boulot de vulgarisation des processus techniques et scientifiques !

Est-ce qu’il ne faudrait psa générer autant d’images distinctes qu’il n’y a de composantes connexes (ou objets) détectées, pour qu’il n’y ai pas de rapprochement possible « telle véhicule a été vu à côté de telle personne » ?

Je ne l’ai pas précisé mais c’est déjà le cas.

L’ajout suivant est encore plus radical… les extraits conservés seront bientôt chiffrés avec une clé renvoyée au client de l’API mais qui ne sera pas conservée par le serveur.

Cela rendra inutilisables les extraits conservés sauf par le client qui a demandé le floutage (et bien conservé la clé).

Au bout d’un temps à définir, on pourra aussi supprimer ces données définitivement.

1 « J'aime »

Bonjour,

Je suis très intéressé par le floutage des 360 et dans l’attente de la validation de l’API pour pousser nos 900 km de voies.
Comment participer à la phase d’annotation des images 360 ?

Merci pour tout le travail effectuer jusqu’à présent.

Pour le floutage imparfait des 360, je pense avoir bien amélioré ça hier, sans ré-entraînement de modèle car le problème ne venait pas forcément du modèle en lui même.

Explication:

  • YOLO propose un paramètre (pas assez documenté) “imgsz” qui par défaut se met à 2048, c’est à dire 2048 pixels de côté maximum.
  • Une image 360 est souvent très large (5760 pour les GoPro Max) et se retrouve donc compressée en 2048x1024.
  • Les objets à détecter deviennent trop petits pour que le modèle les repère…

Ceci pose moins problème sur les images planes car un objet distinguable restera plus grand (plus de pixels utiles, même une fois l’image réduite) et aura donc plus de chance d’être détecté.

J’ai donc modifié le code appelant le modèle de détection pour ne pas réduire les images très larges.

Voici une petite séquence qui bénéficie de cette correction où il n’y a plus de faux négatifs : https://panoramax.openstreetmap.fr/#focus=pic&map=18.42/47.864602/3.392719&pic=435ab996-2ea1-42ac-8528-abe608d04bac&xyz=89.92/-0.71/0

2 « J'aime »

Hello,

Je viens de tomber là-dessous: GitHub - XPixelGroup/DiffBIR
Logiciel open-source écrit en python et basé sur des modèles d’IA permettant de récupérer des détails de façon spectaculaire. Peut-il aller jusqu’au défloutage ou est-ce que ce cas a été prévu ?

Ce type de modèle génératif crée une version haute def en s’inspirant de la version dégradée.

C’est une création… impossible de ressortir par exemple le visage d’origine si il n’a jamais été vu pas le modèle lors de l’entraînement.
Il est même souvent possible de générer plusieurs versions, car des éléments aléatoires sont intégrés lors de la génération.

C’est comme ChatGPT, les réponses ont juste l’air vraies…

Les exemples de visages ont aussi des résolutions bien plus importantes (plus de 256 pixels) que ce qui sort de notre API de floutage (12 pixels).

On n’a pas encore des outils de Deckard (Harrison Ford) dans Blade Runner :wink:

Merci @cquest. Au moins c’est clair. je préfère qu’on se pose la question à tort que trop tard. Surtout avec les progrès technologiques quotidiens, la veille est hyper importante.

J’ai pris 12 pixels pour le visage compte car après recherche il semble que certains annoncent faire de la reconnaissance faciale avec 12 pixels entre les yeux (donc environ le double pour le visage complet).

Le hic, c’est que la techno évolue… et que ce qu’on ne peut pas exploiter aujourd’hui pourrait l’être dans quelques années. C’est le même sujet avec la cryptographie, ce qui est sûr aujourd’hui ne le sera plus à un moment donné à l’avenir. Un mot de passe de 8 caractère était considéré comme sûr il y a quelques années, ce n’est plus du tout le cas.