Transfert de style : et si Van Gogh peignait Tux ?

Magazine
Marque
GNU/Linux Magazine
Numéro
202
Mois de parution
mars 2017
Domaines


Résumé
Qu'est-ce que le style transfer ? Comment cela fonctionne-t-il ? Comment en faire chez soi ? Cet article est là pour répondre à toutes ces questions, et pour vous guider pas à pas sur un exemple.

Body

Le neural style, ou style transfer, a récemment fait son apparition, avec la publication d’un article en septembre 2015 [1]. Il émerge d’un contexte de fort développement des réseaux de neurones pour diverses applications, et notamment pour l’art. Quelques mois auparavant apparaissait le deep dream, programme faisant ressortir des patterns inexistants dans des images, créant ce qui pourrait être considéré comme un style artistique à part entière.

Le neural-style permet de récupérer le « style » d’une image et de l’appliquer sur une autre. Cela permet, avec quasiment aucun effort, de copier le style d’un grand maître pour l’appliquer sur la photo de son chat. Perspective fort intéressante !

Cet article couvrira un peu de théorie, puis décrira pas à pas l’installation puis le transfert d’un style vers notre Tux chéri (figure 1).

premier_exemple

Fig. 1 : Tux modifié en utilisant comme style une image glanée sur une banque d’images libre de droits [2].

1. Un peu de théorie

Commençons par un peu de théorie : réseaux de neurones, deep learning, transfert de style et lien avec le deep dreaming.

1.1 Réseaux de neurones

Les réseaux de neurones sont une structure algorithmique copiant très schématiquement le fonctionnement de neurones dans le cerveau. Chaque neurone réalise une opération mathématique donnée, produisant ou non une sortie en fonction d’une valeur seuil qui lui est propre. Les réseaux peuvent avoir une immensité de topologies différentes, et les liens entre leurs neurones peuvent avoir des poids différents (appelés « poids synaptiques »).

Étant donnée la quantité de variables en jeu, la principale difficulté dans l’utilisation d’un réseau de neurones consiste en le choix de la valeur de ces variables. Différentes méthodes ont été testées pour apprendre automatiquement ces valeurs depuis l’apparition des réseaux de neurones dans les années 50. C’est l’efficacité des réseaux multi-couches (deep learning ou apprentissage profond) qui font le succès des réseaux de neurones depuis 2010.

1.2 Deep learning

L’idée du deep learning (apprentissage profond) est de structurer les tâches en couches reliées les uns aux autres, réalisant des opérations de niveaux d’abstraction différents. Par exemple, un réseau de reconnaissances d’images pourra être constitué d’une couche travaillant sur les pixels, reliée à une couche reconnaissant des bordures simples, elle-même reliée à une couche reconnaissant des motifs, puis des parties d’objets, puis des objets, etc.

Si le deep learning est aussi populaire en ce moment, c’est pour une raison simple : alors que l’on pensait jusqu’alors que l’avenir de l’intelligence artificielle passerait par l’enseignement d’heuristiques aux systèmes d’intelligence artificielle, on s’est rendu compte qu’avec une structure appropriée et une puissance de calcul suffisante, de telles structures étaient capables de découvrir les heuristiques par elles-mêmes. Mieux, elles pouvaient le faire parfois mieux que les humains ! On a ainsi vu un tel système battre un des plus grands maîtres du jeu de go, alors qu’une telle perspective semblait éloignée d’encore au moins quelques dizaines d’années.

En tant que système multi-couches, le deep learning est particulièrement sujet à la diversité des topologies possibles. Pour le transfert de style, le principal réseau utilisé se nomme VGG (Visual Geometry Group). Il s’agit d’un réseau de 16 couches de neurones (ou 19, selon la version), connu pour obtenir de bons résultats en reconnaissance d’image.

1.3 Transfert de style

Dans un article publié en septembre 2015, des chercheurs de Tübingen et de Houston ont introduit un algorithme utilisant du deep learning pour créer des « images artistiques de haute qualité perceptuelle ». Leur article introduit l’idée que la représentation du style et du contenu peuvent être séparés dans un certain type de réseau de neurones. Cela a lancé la voie du transfert de style, rapidement étendu et amélioré par d’autres articles : gain de vitesse, application au son ou à la vidéo, etc.

Pour parvenir à cette prouesse, les auteurs de l’article construisent un réseau capturant les informations de texture d’une image, mais pas l’organisation des éléments de celle-ci. Une fois ces informations de texture mémorisées dans un réseau, il est possible de les appliquer sur une image différente.

Le transfert de style est un problème d’optimisation : on cherche à appliquer un modèle précalculé (le style) sur une image. Pour cela, on définit une fonction objectif (loss function) qu’on cherche à minimiser. Il s’agit d’une somme pondérée de l’erreur (loss) entre l’image originale et l’image produite et de l’erreur entre le style original et celui appliqué. En jouant sur les paramètres de la pondération, on peut donc donner plus d’importance à l’image originale ou au style utilisé (cf. section 5).

1.4 Différences avec le deep dream

Le deep dream a été présenté dans un article de juillet 2015 par des chercheurs de Google. Antérieur à l'article précédent, il introduit l’idée de la génération d’images à but artistique par des réseaux de neurones profonds.

L’idée est ici plus simple : il s’agit de lancer « à l’envers » un réseau de neurones entraîné à reconnaître des images spécifiques. Le but est de produire en sortie l’image originale modifiée de telle sorte que l’on voie les endroits où le réseau « pense » reconnaître lesdites images. Cela produit des sortes d’hallucinations visuelles comparables à celles obtenues par un cerveau humain sous drogue psychédélique. On obtient ainsi une image étrange, où des formes inexistantes se dessinent sur les structures de l’image originale.

En faisant tourner l’algorithme plusieurs fois à partir de bruit, on obtient une représentation stylisée et combinée des objets que le réseau a été entraîné à reconnaître.

Le réseau de neurones utilisé pour l’article susnommé ayant été entraîné sur des images de chiens, de fractales colorées et de pagodes, on retrouve souvent des images hallucinantes contenant des chiens et des pagodes de façon colorée. Il est évidemment possible d’entraîner des réseaux sur de nouvelles images pour halluciner des choses différentes (pourquoi pas des tux ?).

La figure 2 montre le résultat d’un tux passé au filtre du Deep Dreaming.

tux_deepdream

Fig. 2 : Tux modifié avec le Deep Dream.

Nous n'étudierons pas plus en détail le deep dream dans cet article, car il y a tellement de choses à faire avec (notamment en jouant avec les différentes couches) que cela pourrait constituer un article à part entière !

Notez que le transfert de style est parfois aussi appelé deep dreaming.

2. Options d’utilisation

Plusieurs méthodes, plus ou moins simples et rapides, permettent de générer des images avec transfert de style. Passons-les en revue.

2.1 Demande à Claude

Passons rapidement sur la méthode la plus simple : utiliser le cloud (aussi appelé « l’ordinateur de quelqu’un d’autre »). Il existe de nombreuses pages web et applications pour smartphone permettant de générer des images en neural-style. L’avantage évident de tels systèmes est qu’on évite toute la partie installation (et éventuel achat de matériel nécessaire). L’inconvénient, c’est qu’on ne contrôle pas les paramètres, et que l'on n’apprend rien ! Dans cet article, nous allons donc nous attacher à tout installer nous-mêmes, mais sachez que des solutions directes existent.

Après quelques tests, je constate que leur qualité est très limitée : certains ne fonctionnent pas, beaucoup demandent une inscription, d’autres ne permettent pas de choisir le fichier de style, d’autres encore se veulent être des réseaux sociaux à part entière. À vrai dire, ceux qui fonctionnent correctement [3] sont basés sur la version rapide de l’algorithme (dont je discute les limites plus bas) et ne permettent pas de choisir le style.

2.2 Chez soi c’est quand même mieux

Voyons donc comment installer un des outils permettant de faire du style transfer : neural-style. Les explications qui suivent (ainsi que toutes les installations de l'article) sont prévues pour Debian Stretch.

Il faut commencer par installer torch, un framework en lua utilisé entre autres pour manipuler des réseaux de neurones. Il faut télécharger la version prévue pour l’installation (et non pas la version de développement) :

$ git clone https://github.com/torch/distro.git --recursive

$ ./install-deps # Utilise apt-get, vous pouvez aussi lire le script et installer les paquets

                 # nécessaires a la main

$ ./install.sh

$ mkdir build && cd build

$ cmake ..

$ make

$ sudo make install

Le script d’installation vous demandera si vous souhaitez qu’il ajoute un script à votre .bashrc. Acceptez, il sert à exporter des variables d’environnement pour que torch puisse s’exécuter correctement.

Pour vérifier que l’installation de torch est correcte, il suffit d’utiliser la commande th et de voir si cela ouvre un shell interactif.

Maintenant que torch est activé, on peut installer le reste des dépendances de neural-style :

$ sudo aptitude install libprotobuf-dev protobuf-compiler

$ luarocks install loadcaffe

Pour la dernière commande, un bug vis-à-vis des versions de protobuf peut être contourné en l’exécutant en root.

Ensuite, on clone le dépôt et on télécharge le modèle VGG, c’est-à-dire le schéma des réseaux de neurones. Celui-ci a le format des réseaux Caffe, un autre framework de deep learning.

$ git clone https://github.com/jcjohnson/neural-style.git

$ sh models/download_models.sh

Il ne manque qu’une chose : les images à utiliser ! Pour notre exemple, j’ai pris les images [4] et [5]. Voilà, normalement tout est bon pour lancer un calcul :

$ th neural_style.lua -style_image PB_20140912201212155.jpg -content_image tux.png -output_image tux_robots.jpg -print_iter 1 -gpu -1

Les options utilisées parlent d’elles-mêmes :

- -style_image : le chemin vers l’image dont on veut copier le style ;

- -content_image : le chemin vers l’image sur laquelle appliquer le style ;

- -output_image : le nom du fichier de sortie. Notez que l’extension que vous indiquez sera utilisée pour produire l’image dans le format correspondant ;

- -print_iter : pour afficher une sortie à chaque itération (il y en a 1000 par défaut) ;

- -gpu -1 : pour ne pas utiliser de GPU (nous allons voir cela dans les sections suivantes).

Au cours du calcul, le script enregistre les images intermédiaires toutes les 100 itérations, ce qui permet de se rendre compte du fonctionnement du système (figure 3). On peut aussi les utiliser pour créer un GIF animé !

etapes

Fig. 3 : Les étapes (toutes les 100 itérations) de la génération de l’image finale.

3. Accélération

Bon voilà, c’est bien joli tout cela, mais notre calcul précédent prend plus ou moins... 10 heures ! Il va falloir étudier les moyens disponibles pour l’accélérer.

3.1 GPU

Les GPU sont très utiles pour accélérer des calculs de réseaux de neurones, ceux-ci bénéficiant particulièrement du calcul massivement parallèle.

3.1.1 Choix de la carte

Pour le choix de la carte, notez que si les cartes Nvidia ont un meilleur rapport qualité/prix, les pilotes libres ne permettent pas d’utiliser CUDA (mais d'autres technologies équivalentes moins performantes). Privilégiez une carte particulièrement performante pour les calculs de basse précision, ceux-ci étant massivement utilisés dans les réseaux de neurones.

Il faut de plus installer un backend permettant le calcul parallèle : CUDA ou OpenCL. Le backend CUDA étant plus utilisé par la communauté, il est plus abouti et plus efficace en terme de calcul. Le backend OpenCL, quant à lui, a l’avantage d’être en licence libre (et donc plus facile à installer). Pour les cartes gérant CUDA (Nvidia), l’utilisation additionnelle du backend cuDNN permet un léger gain de performance, et surtout une meilleure gestion de la mémoire (ce qui permet de générer des images plus grandes).

Une carte graphique milieu de gamme (environ 300€) est adaptée pour générer des images de taille 512x512, mais sera quelque peu limitée pour aller au-delà (jusqu’à 800-900 pour une carte avec 6 Gio de mémoire, en fonction des images). Le facteur limitant est ici la mémoire de la carte, sachant que le swap n’est généralement pas possible en cas d’utilisation totale de cette mémoire (peu de cartes le gèrent). La consommation mémoire de l’outil est assez importante : 3.5 Gio avec les paramètres par défaut, 1 Gio en utilisant un backend moins consommateur de mémoire. La carte graphique utilisée doit en posséder au moins autant, puisqu’une insuffisance en mémoire rendra l’exécution impossible.

3.1.2 Installation

Pour faire du calcul sur GPU, quelques installations supplémentaires sont nécessaires, et dépendent de la carte choisie et du backend désiré.

Pour OpenCL, l’installation est a priori simple, mais je ne l’ai pas testée. Il faut d’abord installer les drivers correspondant à la carte graphique (qui dépendent du constructeur, cf. [6]), puis installer cltorch et clnn :

$ git clone --recursive https://github.com/hughperkins/distro -b distro-cl ~/torch-cl

$ cd ~/torch-cl

$ ./install-deps

$ ./install.sh

Dans le cas d’une carte Nvidia, installer CUDA et cuDNN est plus compliqué. Le module du noyau nécessite que les headers du noyau utilisé soient installés. On commence donc par les installer, avant de faire de même pour tous les paquets nécessaires. Les paquets lua cutorch et cunn ne compilent qu’avec des versions de gcc inférieures à 5. Il faut donc passer des flags pour que les bonnes versions soient utilisées (vérifiez vos versions de gcc et g++ avant cela). En résumé :

$ sudo aptitude install linux-headers-\$(uname -r)

$ sudo aptitude install nvidia-driver nvidia-kernel-dkms nvidia-cuda-toolkit nvidia-cuda-dev

$ CC=gcc-4.8 CXX=g++-4.8 luarocks install cutorch

$ CC=gcc-4.8 CXX=g++-4.8 luarocks install cunn

Toujours dans le cas d’une carte Nvidia, on peut optionnellement rajouter cuDNN, qui permet un léger gain de performances, et surtout une meilleure utilisation mémoire. cuDNN n’est pas packagé sur Debian, il faut le télécharger sur le site de Nvidia [7], après enregistrement. On l’installe ensuite comme un paquet normal, puis on installe la bibliothèque lua associée :

$ sudo dpkg -i 'libcudnn5_5.1.5-1+cuda8.0_amd64.deb'

$ CC=gcc-4.8 CXX=g++-4.8 luarocks install cudnn

Si tout est bon après un redémarrage, on peut désormais lancer neural-style avec l’option gpu (0 signifie d’utiliser le GPU numéro 0, pas de la désactiver), avec cuDNN si on l’a installé :

$ th neural_style.lua -style_image PB_20140912201212155.jpg -content_image tux.png -output_image \ tux_robots.jpg -print_iter 1 -gpu 0 -backend cudnn

Ou en utilisant OpenCL :

$ th neural_style.lua -style_image PB_20140912201212155.jpg -content_image tux.png -output_image \ tux_robots.jpg -print_iter 1 -gpu 0 -backend clnn

Et voilà, le calcul ne prend plus que quelques minutes !

3.2 TPU

Les réseaux de neurones utilisés dans le style transfer ont la particularité de nécessiter uniquement du calcul sur petits entiers (8 bits). Si les GPU possèdent de nombreux cœurs, ceux-ci sont inutilement puissants pour une telle application. Pour cette raison, Google a développé des puces spécialement dédiées à ce genre de calcul, appelées TPU (Tensor Processing Unit), et les utilise depuis un an dans ses datacenters. Ces puces permettraient un énorme gain de vitesse et de performance par watt.

Et là vous vous dites : « Mais c’est super ! Ça se trouve où ? ». Malheureusement, ces puces ne sont pas disponibles dans le commerce, et Google n’a pas annoncé vouloir les commercialiser.

Pour être exhaustif, notons qu’il existe d’autres processeurs destinés à accélérer les outils de machine learning en se spécialisant dans les opérations mathématiques de basse précision : FPGA, d’autres types d’ASIC… [8]

3.3 Fast neural network

Il existe une implémentation plus récente du style transfer permettant un calcul bien plus rapide. Celle-ci est basée sur un article d’octobre 2016 [9]. L’idée est de remplacer l’erreur (loss) « par pixel » par l’erreur « perceptuelle ». En d’autres termes, le système ne cherche plus à faire coller chaque pixel à l’image originale, mais calcule la perte à un niveau plus élevé, ce qui permet de mesurer plus finement la similitude « perçue » entre deux images. De plus, l’implémentation utilise une modification dans l’architecture du réseau qui permet également un gain de performance. Celle-ci se base sur un précalcul du modèle, qui peut alors être utilisé à faible coût pour être appliqué sur de nouvelles images.

Au niveau pratique, les modèles doivent donc être précalculés afin de pouvoir être utilisés. Une fois le projet précédent installé, il n’y a rien de nouveau à installer pour créer de nouvelles images en utilisant les modèles préinstallés (en fait, il y a même moins de dépendances). Il n’y a donc qu’à cloner le dépôt :

$ git clone https://github.com/jcjohnson/fast-neural-style

Vous pouvez à présent créer de nouvelles images avec les modèles existants :

 th fast_neural_style.lua -model models/eccv16/starry_night.t7 -input_image tux.png -output_image tux-starry_night.png

Notez qu’avec cette implémentation, la création d’images utilisant des modèles existants ne prend plus qu’une minute sur CPU (et quelques secondes sur GPU !). L’entraînement de nouveaux modèles reste cependant extrêmement coûteux : 4 à 6 heures sur une carte graphique haut de gamme (on passe de 6 à 4,5h avec cuDNN). Il n’est donc pas vraiment envisageable d’entraîner de nouveaux modèles sur CPU...

Justement, voyons maintenant l’entraînement de nouveaux modèles. Pour cela, il y a encore 2-3 choses à installer : torch-hdf5 et python-h5py.

$ git clone https://github.com/deepmind/torch-hdf5

$ cd torch-hdf5

$ luarocks install hdf5-0-0.rockspec

$ sudo aptitude install python-h5py

Pour entraîner un réseau, il faut de plus le faire sur une banque d’images. Il faut donc un tel jeu d’images, et le préparer pour créer un fichier .hdf5, qui contient des informations sur le contenu des images. On va utiliser le jeu de données COCO, une grosse base de données d’images variées. Celui-ci est composé d’un jeu d’entraînement de 13 Gio ainsi que d’un jeu de vérification de 6 Gio. Ce dernier sert à effectuer des passes de vérification du bon fonctionnement de l’entraînement du réseau sur des images différentes de celles du jeu d’entraînement.

$ wget http://msvocds.blob.core.windows.net/coco2014/train2014.zip

$ wget http://msvocds.blob.core.windows.net/coco2014/val2014.zip

$ unzip train2014

$ unzip val2014

$ python scripts/make_style_dataset.py --train_dir train2014 --val_dir val2014 --output_file file.h5

Notez que l’exécution du script prend quelques heures. Il est a priori possible d’obtenir des résultats très similaires avec un sous-ensemble très réduit du jeu de données, mais cette étape n’est à exécuter qu’une seule fois de toute manière, et l’étape d’entraînement n’est pas accélérée par l’utilisation d’un jeu d’images plus petit.

Comme pour neural-style, on a besoin du réseau VGG pour entraîner notre modèle :

$ ./models/download_vgg16.sh

Si tout est bon, on peut commencer à entraîner notre nouveau modèle :

$ th train.lua -h5_file normal.hdf5 -style_image PB_20140912201212155.jpg -gpu 0 -use_cudnn 1

Si, comme c’est le cas à l’heure où j’écris ces lignes, vous obtenez cette erreur :


Error: unable to locate HDF5 header file at hdf5.h

Voici une manière de la corriger :

- installez le paquet libhdf5-serial-dev ;

- modifiez le fichier hdf5-0-0.rockspec pour ajouter le dossier de localisation de hdf5.h à la commande cmake. Concrètement, remplacez la ligne :

cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=''$(LUA_BINDIR)/.." -DCMAKE_INSTALL_PREFIX="$(PREFIX)'';

par :

cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=''$(LUA_BINDIR)/.." -DCMAKE_INSTALL_PREFIX="$(PREFIX)'' -DHDF5_INCLUDE_DIR=''/usr/include/hdf5/serial/'';

Puis relancez la commande d'installation :

$ luarock install hdf5-0-0.rockspec

On obtient le résultat visible en figure 4 :

tux_fast

Fig. 4 : Résultat obtenu avec fast-neural-style.

Comme je le disais plus haut, le résultat est bien moins intéressant qu’avec la version lente de l’algorithme. Cependant, l’image Tux est très « lisse » et « simple » . On obtient des résultats bien plus intéressants pour d’autres images : cf. figure 5 par exemple. Ce dernier est tout de même à mon goût moins intéressant que son équivalent neural-style (figure 6).

stallman_robot_fast

Fig. 5 : Une autre image avec fast-neural-style.

stallman_robot

Fig. 6 : L’équivalent de l’image de la figure 5 avec le neural-style original.

4. Quelques conseils artistiques

Après quelques utilisations sur diverses images, voici les conseils que je peux donner pour obtenir des résultats intéressants :

- Parfois, les fichiers d’étapes (cf. figure 3) sont plus intéressants que le résultat final (notamment les 200 premières itérations). Pensez aussi à essayer d’augmenter le nombre d’itérations si l’image finale n’est pas « terminée » (c’est-à-dire si les images d’étapes changent encore beaucoup dans les dernières centaines d’itérations).

- Pour les styles, choisir des images de styles avec de nombreux détails, ou un style bien défini. Prendre un simple logo donne des résultats inintéressants (utiliser Tux ou le logo Debian comme image de style ne donne rien de bien).

- Par défaut, les images sont générées avec une taille de 512 pixels pour son côté le plus grand. Cela donne des images assez petites, et surtout pixelisées. Agrandir l’image de résultat (avec l’option -image_size) augmente le niveau de détails en même temps que la netteté (pensez à l’option style_scale pour remédier à cela). Comme indiqué plus haut, il est cependant difficile d’augmenter beaucoup les tailles des images générées, puisque l’utilisation mémoire augmente de façon quadratique. La mémoire de la carte graphique est donc rapidement pleine, à moins d’en avoir plusieurs... Quant à l’option du calcul sur CPU (pour bénéficier d’une mémoire plus grande et de la possibilité de swaper), il est extrêmement lent : il m’a fallu 46h de calcul pour générer une image de 1024x682 pixels !

- Notez qu’il est possible d’utiliser plusieurs styles à la fois avec neural-style, ce qui peut donner des résultats intéressants. Avec fast-neural-style, ce n’est pas possible.

- L’outil fast-neural-style, s’il est plus rapide, donne des résultats moins intéressants. Comme le notent les auteurs de l’article, cette solution a tendance à produire des motifs répétitifs. À mon sens, le résultat est vraiment moins pertinent.

Il est possible de jouer avec les paramètres des outils. Étudions-en quelques-uns :

- L’option style_scale permet d’appliquer le style avec une échelle plus ou moins grande. Varier ce paramètre peut donner une meilleure intégration du style dans le résultat final (voir figure 7).

vary_style_scale

Fig. 7 : Résultats obtenus en faisant varier l’option style_scale avec les valeurs suivantes : 0.1, 0.2, 0.5, 0.8, 1.5, 2.0 (valeur par défaut : 1.0). Les valeurs supérieures demandent trop de mémoire pour ma carte graphique de 6 Gio.

- Les options content_weight et style_weight permettent de donner plus ou moins de poids au style ou à l’image originale dans la construction de l’image finale. Leurs valeurs par défaut sont respectivement 5 et 100. Les figures 8 et 9 montrent les résultats obtenus en faisant varier ces paramètres.

vary_content_weight

Fig. 8 : Résultats obtenus en faisant varier l’option content_weight avec les valeurs suivantes : 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 (valeur par défaut : 5).

vary_style_weight

Fig. 9 : Résultats obtenus en faisant varier l’option style_weight avec les valeurs suivantes : 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000 (valeur par défaut : 100).

- Ne pas hésiter à jouer avec tous les autres paramètres ! Les outils présentés en possèdent de nombreux, qu’il serait long de passer en détail. Par exemple, l’option -init image permet de démarrer le calcul à partir de l’image d’origine, plutôt que d’un bruit aléatoire. Cela donne un résultat moins déconstruit, plus proche de l’image originale (cf. figure 10).

init_image

Fig. 10 : Résultats obtenus en faisant varier l’option -init image (à gauche) au lieu de -init random (à droite).

5. Pour aller plus loin : la vidéo

Les images c’est bien. Quand elles bougent, c’est mieux ! Il existe plusieurs techniques différentes pour passer de l’image à la vidéo. Voyons-en une rapide, et une autre orientée vers un meilleur résultat.

5.1 En temps réel

L’outil précédent (fast-neural-style) est tellement rapide qu’il permet une exécution en temps réel sur une entrée vidéo. Et justement, il comprend un script permettant de faire cela. Pour l’utiliser, il faut installer quelques dépendances supplémentaires :

$ sudo aptitude install libopencv_highgui

$ luarocks install camera

$ luarocks install qtlua

Pour lancer le script, il faut utiliser qlua et non plus th :

$ qlua webcam_demo.lua -gpu 0 -models models/model.t7

Le script s’occupe de chercher une entrée vidéo (webcam) et d’y appliquer le transfert de style en temps réel. Et voilà !

5.2 Stabilisée

Vous remarquerez cependant rapidement un défaut avec le script précédent : le style n’est pas appliqué identiquement à chaque image, ce qui donne une sorte de clignotement assez désagréable. Cela est dû au fait qu’étant initialisée avec des valeurs aléatoires, chaque image va converger vers un maximum local différent. Un article d'octobre 2016 [10] par des chercheurs de l'université de Freiburg a étudié la question pour corriger ce problème. Pour simplifier, ses auteurs proposent d'initialiser chaque image avec les valeurs de l’image précédente afin de conserver une certaine uniformité, et calculent en plus le flux optique, c'est-à-dire le mouvement apparent des objets prenant en compte le mouvement relatif de la caméra. Cela donne un résultat stable, bien qu’encore imparfait (on trouve entre autres des artefacts étranges dans le résultat et il reste des soucis de cohérence). Notez que cet algorithme utilise neural-style et non fast-neural-style, et est donc lent : j’ai mis environ 7 heures pour générer une vidéo de 10 secondes en 320x200.

Si vous avez déjà installé les dépendances des outils précédents (torch7, loadcaffe et CUDA), il n’y a plus qu’à cloner le dépôt et à télécharger deux outils, disponibles directement sous la forme de binaires. Ceux-ci servent à calculer le flux optique entre deux images.

$ git clone https://github.com/manuelruder/artistic-videos

$ cd artistic-videos

$ wget lear.inrialpes.fr/src/deepmatching/code/deepmatching_1.2.2.zip

$ unzip deepmatching_1.2.2.zip

$ mv deepmatching_1.2.2_c++/deepmatching-static .

$ wget pascal.inrialpes.fr/data2/deepmatching/files/DeepFlow_release2.0.tar.gz

$ tar xzf DeepFlow_release2.0.tar.gz

$ mv DeepFlow_release2.0/deepflow2-static .

Un script existe pour lancer l’outil avec les options par défaut :

$ ./stylizeVideo.sh <video> <image_style>

Si on veut utiliser d’autres options pour le transfert de style, il faut décomposer le script : celui-ci découpe une vidéo en images, calcule le flux optique, lance le transfert de style sur chaque image, puis reconstruit la vidéo à partir des images générées. En bref :

$ mkdir tmp

$ ffmpeg -i <video> tmp/frame_%04d.ppm

$ makeOptFlow.sh ./tmp/frame_%04d.ppm ./tmp/flow_$resolution

$ th artistic_video.lua -content_pattern tmp/%03d.ppm -flow_pattern \ tmp/flow_default/backward_[%d]_{%d}.flo -flowWeight_pattern \ tmp/flow_default/reliable_[%d]_{%d}.pgm -output_folder tmp -style_image <style> -gpu 0 \ -backend cudnn -number_format %03d

$ ffmpeg -i tmp/out-%04d.png video-stylized.mp4

Attention : comme auparavant, on se retrouve rapidement à court de mémoire si on utilise des images trop grandes. Il sera certainement nécessaire de réduire la taille des images lors de la conversion de la vidéo en images avec l'option -vf scale=<résolution> de ffmpeg.

6. File au zoo, fi !

Le développement du machine learning à des fins artistiques pose de nouveaux questionnements philosophiques. S’il y a quelques années, il était encore courant de penser que l’art resterait pour longtemps du domaine de l’humain, inaccessible par la machine, la publication du deep dream par des chercheurs de Google a balayé cette supposition d’un revers de main : une intelligence artificielle aurait créé un nouveau style d’art ! Évidemment, cette affirmation est à relativiser largement puisque c’est avant tout les chercheurs et non la machine qui ont créé cet art. Le style transfer va encore plus loin : une machine est désormais capable de copier le style d’un humain sur une nouvelle image. Incroyable !

La barrière est donc repoussée. On peut se réconforter en se disant que l’art consiste avant tout à créer quelque chose de nouveau en fonction du contexte, qui sache perturber, questionner et émerveiller le spectateur. Et ça, la machine en est toujours incapable, puisqu’elle doit nécessairement être guidée par un être humain. Pour l’instant. Mais pour combien de temps ? Le défi est lancé !

L’image de la fin

En note finale, remarquons que si le transfert de style fonctionne pour les images, rien ne l’empêche d’être possible pour d’autres arts, notamment la musique [11] et la danse [12]. À vos claviers !

Et pour finir, voici quelques images de tux modifié en utilisant quelques images et photos glanées sur divers sites proposant des images libres de droits. Imaginez ce qu’il est possible de faire en ne se limitant pas pour des questions de droit !

exemples

Fig. 11 : D’autres résultats avec des images de style différentes.

Références

[1] GATYS L., ECKER A. et BETHGE M., « A neural algorithm of Artistic style », 2015 : https://arxiv.org/pdf/1508.06576v2.pdf

[2] Photo de Jeffrey Betts : http://finda.photo/image/11418

[3] Application Aristo : https://artisto.my.com/

[4] Photo de Jeffrey Betts : http://finda.photo/image/11418

[5] Image de Tux : https://commons.wikimedia.org/wiki/File:Tux.png

[6] Installation des drivers des cartes graphiques sous Debian : https://wiki.debian.org/fr/GraphicsCard

[7] cuDNN : https://developer.nvidia.com/rdp/cudnn-download

[8] Accélération des outils de machine learning : https://en.wikipedia.org/wiki/AI_accelerator

[9] JOHNSON J., ALAHI A. et LI F.-F., « Perceptual losses for real-time style transfer and super-resolution », ECCV 2016 : http://cs.stanford.edu/people/jcjohns/eccv16/

[10] RUDER M., DOSOVITSKIY A. et BROX T., « Artistic style transfer for videos », 2016 : https://arxiv.org/pdf/1604.08610.pdf

[11] Algorithmic Music Generation with Recurrent Neural Networks : https://www.youtube.com/watch?v=0VTI1BBLydE

[12] Generative Choreography using Deep Learning : http://peltarion.com/creative-ai




Articles qui pourraient vous intéresser...

Conservez l’historique de vos commandes pour chaque projet, le retour

Magazine
Marque
GNU/Linux Magazine
Numéro
241
Mois de parution
octobre 2020
Domaines
Résumé

Pouvoir conserver un historique dédié pour chaque projet, voici l’idée géniale énoncée par Tristan Colombo dans un précédent article de GLMF [1]. Cet article reprend ce concept génial (je l’ai déjà dit?) et l’étoffe en simplifiant son installation et en ajoutant quelques fonctionnalités (comme l’autodétection de projets versionnés pour proposer à l’utilisateur d’activer un historique dédié, si ce n’est pas le cas).