l’arrivée des modèles de génération d’image en text2image de plus en plus performant, DALLE Midjourney ou encore stable diffusion, on produit une critique et une résistance sur internet. En effet, les artistes publiant leur projets sur internet se sont mis à spammer cette image (ci-dessous) sur des plateformes comme art station pour montrer leur mécontentement face à l’usage de leurs publications pour nourrir leur modèle sans aucune contrepartie et aussi à la publication d’image produit par ces algorithme sur les plateformes de partage d’image.
Puis ces modèles de génération d’images, se basant sur les contenus disponibles sur ces plateforme, se sont mis à intégrer ce symbole dans leur production, par exemple dans cette génération.
Comment reproduire ce genre de dynamique dans des modèles plus simples ?
J’ai donc voulu réintégrer des interférences dans le modèle de Nvidia de StyleGan2 entrainé sur FFHQ (Flickr Faces High Quality). Il s’agit du modèle utilisé pour le projet thispersondoesnotexist. Le modèle est entrainé sur la base de donnée de visages FFHQ, issues de photos postées sur Flickr. J’ai « enrichi » le modèle en intégrant des images de visage (issues aussi de FFHQ) anonymisées. En effet, votre visage peut être dans cette base de donnée et vous ne le savez pas, en ré entrainant le modèle avec quelques images aux visages anonymisées l’algorithme ne pourra plus générer des visages aussi net et précis.
L’automatisation de l’anonymisation des visages de la base de données a été réalisé avec du machine learning. Initialement je voulais utiliser un HAAR Cascade classifier (avec openCV) mais cette approche produisant trop d’imprécisions j’ai plutôt utilisé face_recognition dont le modèle de reconnaissance est basé sur DLIB, en fin d’article vous pouvez avoir accès à ce petit script qui pour un répertoire d’images va produire une version avec un rectangle « d’anonymisation ».
J’ai donc sur-entrainé le modèle en lui donnant en plus environ 1000 images de visages anonymisées, le modèle décline ainsi ce nouveau rectangle noir pour chaque génération.
Après 30kimg (en 1h50) d’entrainement sur le modèle pré entrainé sur une NVIDIA RTX2070 à 8gb de VRAM on obtient ceci :
Le résultat fonctionne « trop bien » : on retrouve très peu d’erreur et d’aléatoire par rapport au génération plus étrange produite par l’apprentissage avec le symbole « no IA ». Peut être faudrait-il intégrer plus de complexité dans l’élément récursif (une forme plus complexe que le carré noir ?) ou peut-être mélanger dans le dataset avec des images non-anonymisées ?
Ci-joint le programme python pour automatisation de l’anonymisation des visages
from PIL import Image, ImageDraw
import face_recognition
from pathlib import Path
from tqdm import tqdm
# le chemin vers les images. ie : /69000/69001.png
p = Path('69000')
# itération dans tout le repertoire avec un suivi de chargement avec TQDM
for path in tqdm(list(p.glob("*.png"))):
# Charge l'image
image = face_recognition.load_image_file(str(path))
# Trouve les coordonées des points biométriques. On utilise de modèles "small" qui n'affiche que les yeux et le nez
face_landmarks_list = face_recognition.face_landmarks(image, model="small")
pil_image = Image.fromarray(image)
for face_landmarks in face_landmarks_list:
d = ImageDraw.Draw(pil_image, 'RGBA')
# On crée les deux points de coordonnées pour dessiner le rectangle
# border_height et border_width sont deux marges ajoutées pour avoir un rectangle plus grand
borders_height = 50
borders_width = 25
p1 = (face_landmarks['right_eye'][0][0] + borders_width, face_landmarks['right_eye'][0][1] - borders_height)
p2 = (face_landmarks['left_eye'][0][0] - borders_width, face_landmarks['left_eye'][0][1] + borders_height)
# On dessine un rectangle noir
d.rectangle([p1, p2], fill = (0, 0, 0, 255))
# enregistrement de l'image
pil_image.save("image_transformed/" + path.name)