18 novembre 2022

la suite de Font Gan

En DNSEP à la HEAR, j’avais réalisé un gan typographique. Un modèle génératif en deep learning, pour une valeur ascii donnée va générer un caractère typographique après avoir « appris » à générer depuis un corpus de typographie qui l’a « nourrit ». Le modèle produit n’utilise que les caractères latins sans accent (a-z,A-Z).

Le modèle permet par déplacement dans l’espace latent de produire des « transitions » entre ces générations.

Les modèles de GAN fonctionnent principalement sur des images bitmaps ou des données converties en matrices car cette méthode utilise des traitements de convolution. J’avais donc pour ambition de convertir ces générations d’image en forme vectorielle après la génération pour avoir de meilleur tracé. Ces transitions peuvent ensuite être produite « vectoriellement » par des interpolations.

Le système est consultable à l’adresse : https://post.felixjely.fr/projets/fontgan/ ; avec cette interface vous pouvez choisir le caractère et modifier l’affichage des couleurs

J’ai ainsi produit un processus en python qui va utiliser Potrace pour convertir les images matricielles en images vectorielles. Voici le processus :

Voici le script pour le processus ci-dessus

# Import
from pathlib import Path
from subprocess import run
import cv2
from svgpathtools import svg2paths
import json

# Liste des toutes les vidéos prégénerées par le GAN typographique
path_videos = list(Path('./out_1024/').glob('*.mp4'))


for video in path_videos:
    # On ouvre la vidéo avec opencv
    cap = cv2.VideoCapture(str(video))
    if (cap.isOpened()== False): 
        print("Error opening video stream or file")
    
    # "file content" contiendra tout les chemins des typos
    file_content = []
    # le count va permettre de sauter des images clefs.
    count = 0
    # La boucle lit toute la vidéo
    while(cap.isOpened()):
      
      ret, frame = cap.read()

      if ret == True:
        # On enregistre l'image de la frame en BMP car potrace utilise ce format
        cv2.imwrite("cache.bmp", frame)
        # On lance une commande potrace pour convertir en svg
        run(f"potrace --svg cache.bmp -o cache.svg", shell=True)
        # Avec svgpathtools, on lit le fichier svg généré par potrace pour recupérer les chemins
        paths, attributes = svg2paths('cache.svg')
        
        paths_in_frame = []

        count += 60 # On avance d'une seconde (on saute 60 frames dans la vidéo)
        cap.set(cv2.CAP_PROP_POS_FRAMES, count)

        for k, v in enumerate(attributes):
          paths_in_frame.append(v)
      # On colle le chemin dans le file content
        file_content.append(paths_in_frame)
        

     
      # si (not ret) alors on sort de la boucle (la vidéo est fini ou il y a eu une erreur de lecture de frame)
      else: 
        break
    # On release la cam
    cap.release()
    # Enregistrement de file content en json
    with open(f"{video.stem}.json", "w") as outfile:
      json.dump(file_content, outfile)