204 lines
11 KiB
Org Mode
204 lines
11 KiB
Org Mode
#+TITLE: Création d’images par algorithme génétique avec référence
|
||
#+SUBTITLE: Rapport de projet
|
||
#+AUTHOR: Lucien Cartier-Tilet
|
||
#+EMAIL: phundrak@phundrak.fr
|
||
#+CREATOR: Lucien Cartier-Tilet
|
||
#+LANGUAGE: fr
|
||
#+LATEX_CLASS: article
|
||
#+LaTeX_CLASS_OPTIONS: [a4paper,twoside]
|
||
#+LATEX_HEADER: \usepackage{xltxtra,fontspec,xunicode}\usepackage[total={6.5in,9.5in}]{geometry}\setromanfont[Numbers=Lowercase]{Charis SIL}
|
||
#+LATEX_HEADER: \usepackage{xcolor} \usepackage{hyperref}
|
||
#+LATEX_HEADER: \hypersetup{colorlinks=true,linkbordercolor=red,linkcolor=blue,pdfborderstyle={/S/U/W 1}}
|
||
#+STARTUP: latexpreview
|
||
#+OPTIONS: toc:nil
|
||
|
||
* Sujet
|
||
|
||
Le sujet de ce projet est la création d’un logiciel pouvant recréer une image
|
||
fournie grâce à des générations aléatoires et successives de formes aux,
|
||
positions, couleurs et taille aléatoires. L’algorithme commence par créer une
|
||
image vide aux dimensions identiques à l’image de référence, puis applique une
|
||
de ces formes aléatoires. Si la ressemblance de l’image ainsi générée augmente
|
||
par rapport à sa version précédente par rapport à l’image de référence, alors
|
||
cette modification est conservée, sinon elle est annulée. Répéter jusqu’à
|
||
satisfaction.
|
||
|
||
* Les méthodes utilisées
|
||
|
||
Plusieurs approches au problème sont possibles, allant de la simple
|
||
implémentation naïve du problème à des moyen pouvant au moins décupler la
|
||
vitesse de génération de l’image. Sauf indication contraire, j’ai utilisé dans
|
||
l’implémentation de chaque méthode des carrés comme forme d’éléments appliqués
|
||
aléatoirement à l’image.
|
||
|
||
Pour évaluer la ressemblance entre deux image, j’évalue une distance euclidienne
|
||
entre le vecteur de leurs pixels qui peut se résumer à ceci :
|
||
#+begin_export latex
|
||
$$\sqrt{\sum_{i=0}^{n} V_{i}^{2}+W_{i}^{2}}$$
|
||
#+end_export
|
||
~V~ étant le vecteur de pixels de l’image de référence, ~W~ étant le vecteur de
|
||
pixels de l’image générée, et ~n~ la taille de ces deux vecteurs.
|
||
|
||
Les tests de temps sont réalisés sur un Thinkpad x220, disposant d’un processeur
|
||
Intel® Core™ i5-2540M à 2.6GHz, composé de deux cœurs supportant chacun deux
|
||
threads, et de 4Go de RAM. Le programme est compilé avec les options
|
||
d’optimisation ~-O3~ et ~-flto~.
|
||
|
||
Voici également ci-dessous la liste des options et arguments possibles
|
||
concernant l’exécution du logiciel.
|
||
#+begin_src text
|
||
$ ./bin/genetic-image -h
|
||
Allowed options:
|
||
-h [ --help ] Display this help message
|
||
-i [ --input ] arg Input image
|
||
-o [ --output ] arg Image output path (default: input path + "_output")
|
||
-m [ --method ] arg Method number to be used (default: 1)
|
||
-n [ --iterations ] arg Number of iterations (default: 5000)
|
||
-v [ --verbose ] Enables verbosity
|
||
#+end_src
|
||
|
||
Voici la ligne de commande utilisée depuis le répertoire ~build~ afin de pouvoir
|
||
obtenir un temps d’exécution :
|
||
#+begin_src shell
|
||
perf stat -r {nombreExécutions} -B ./bin/genetic-image \
|
||
-i ../img/mahakala-monochrome.jpg -o output.png \
|
||
-n {nombreIterations} -m 1
|
||
#+end_src
|
||
|
||
Les deux éléments entre accolades sont à remplacer par leur valeur, par exemple
|
||
afin d’exécuter dix fois le programme avec vingt améliorations, il faudrait
|
||
exécuter ceci :
|
||
#+begin_src shell
|
||
perf stat -r 1 -B ./bin/genetic-image \
|
||
-i ../img/mahakala-monochrome.jpg -o output.png -n 20 -m 1
|
||
#+end_src
|
||
|
||
** Méthode naïve
|
||
|
||
J’ai tout d’abord implémenté la méthode naïve afin d’avoir une référence en
|
||
matière de temps. Cette dernière est implémentée dans ~src/methods.cc~ avec la
|
||
fonction ~method1()~. Comme ce à quoi je m’attendais, cette méthode de
|
||
génération d’images est très lente, principalement dû au fait que l’algorithme
|
||
en l’état essaiera d’appliquer des couleurs n’existant pas dans l’image de
|
||
référence, voire complètement à l’opposées de la palette de couleurs de l’image
|
||
de référence.
|
||
|
||
Voici les moyennes de temps d’exécution selon le nombre d’itérations réussies
|
||
sur le nombre d’exécutions indiqué.
|
||
|
||
| / | < | < | < |
|
||
| Nb d’améliorations | Temps d’exécution (s) | Variation (s) | Nb d’exécutions |
|
||
|--------------------+-----------------------+---------------+-----------------|
|
||
| 10 | 0.060847 | 0.000498 | 200 |
|
||
| 50 | 0.29823 | 0.00453 | 100 |
|
||
| 100 | 0.7093 | 0.0135 | 50 |
|
||
| 200 | 1.9584 | 0.0559 | 20 |
|
||
| 500 | 8.739 | 0.291 | 10 |
|
||
| 1000 | 27.930 | 0.582 | 5 |
|
||
|
||
Naturellement, la variation en temps d’exécution croît en même temps que le
|
||
nombre d’améliorations nécessaires à apporter à l’image à améliorer, dû à la
|
||
nature aléatoire de l’algorithme. Cependant, on constate également une
|
||
croissance importante du temps d’exécution suivant également ce nombre
|
||
d’itérations réussies.
|
||
|
||
Vous trouverez en Annexes (§[[*M%C3%A9thode 1]]) un exemple d’image générée à partir de
|
||
~img/mahakala-monochrome.png~ avec 2000 améliorations via cette méthode.
|
||
|
||
** Réduction du panel des couleurs
|
||
|
||
Constatant que la majorité des échecs d’ajout de formes de couleur par la
|
||
première méthode échouent dû à une couleur incorrecte, voire n’appartenant pas à
|
||
l’image de référence, j’ai décidé de restreindre les possibilités de couleurs
|
||
parmis lesquelles le hasard peut choisir à la liste des couleurs présentes dans
|
||
l’image de référence uniquement. Ce choix se fait donc via l’implémentation d’un
|
||
set de valeurs uniques représentant les couleurs trouvées dans l’image de
|
||
référence, leur détection étant réalisée avec des threads parallèles pour plus
|
||
de rapidité à l’exécution. Cette méthode est celle implémentée dans la fonction
|
||
~method2()~ dans ~src/methods.cc~.
|
||
|
||
Voici les moyennes de temps d’exécution selon le nombre d’itérations réussies
|
||
sur le nombre d’exécutions indiqué.
|
||
|
||
| / | < | < | < |
|
||
| Nb d’améliorations | Temps d’exécution (s) | Variation (s) | Nb d’exécutions |
|
||
|--------------------+-----------------------+---------------+-----------------|
|
||
| 10 | 0.074951 | 0.000533 | 200 |
|
||
| 50 | 0.26385 | 0.00401 | 100 |
|
||
| 100 | 0.6385 | 0.0148 | 50 |
|
||
| 200 | 1.6145 | 0.0348 | 20 |
|
||
| 500 | 6.747 | 0.235 | 10 |
|
||
| 1000 | 19.608 | 0.327 | 5 |
|
||
|
||
On peut remarquer une amélioration dans la rapidité d’exécution du logiciel.
|
||
Cependant, le résultat n’est pas aussi important qu’escompté. Je suppose que
|
||
cela est dû au fait que l’algorithme précédent peut considérer un rapprochement
|
||
d’une zone déjà colorée vers la couleur d’origine comme une amélioration, avec
|
||
une possibilité plus large sur ce plan-là que pour le second algorithme qui se
|
||
doit d’être plus précis concernant les couleurs. Une nette amélioration du
|
||
résultat est toutefois visibles, voir Annexes (§[[*M%C3%A9thode 2]]) pour une image
|
||
générée à partir de ~img/mahakala-monochrome.png~ via la méthode 2 et avec 2000
|
||
améliorations.
|
||
|
||
Étant donné que cette modification ne sera à priori pas en conflit avec d’autres
|
||
méthodes, cette amélioration sera conservée pour toutes les autres avancées
|
||
suivantes.
|
||
|
||
** Une taille des formes aléatoire mais contrôlée
|
||
|
||
Une autre méthode peut être de contrôler la taille des éléments en spécifiant
|
||
une taille minimale et maximale selon le nombre d’éléments posés et le nombre
|
||
total d’éléments à poser. Ainsi, on pourrait privilégier tout d’abord de grandes
|
||
formes en début de génération pour encourager petit à petit les formes à réduire
|
||
en taille. Cela permettrait d’obtenir rapidement une représentation grossière de
|
||
l’image pour ensuite pouvoir progressivement afiner les détails. La taille de la
|
||
forme à appliquer est définie comme suit :
|
||
|
||
#+begin_export latex
|
||
$$coef=\frac{nbIterRestantes}{totalIter}$$
|
||
$$tailleMinimale=coef \frac{min(Width,Height)}{2}$$
|
||
$$tailleMaximale=tailleMinimale*2+1$$
|
||
$$taille=Rand([\![tailleMinimale;tailleMaximale[\![)$$
|
||
#+end_export
|
||
|
||
Voici les moyennes de temps d’exécution selon le nombre d’itérations réussies
|
||
sur le nombre d’exécutions indiqué.
|
||
|
||
| / | < | < | < |
|
||
| Nb d’améliorations | Temps d’exécution (s) | Variation (s) | Nb d’exécutions |
|
||
|--------------------+-----------------------+---------------+-----------------|
|
||
| 10 | | | 200 |
|
||
| 50 | | | 100 |
|
||
| 100 | | | 50 |
|
||
| 200 | | | 20 |
|
||
| 500 | | | 10 |
|
||
| 1000 | | | 5 |
|
||
|
||
Cette version du logiciel est nettement plus lente que ses versions précédentes
|
||
du fait de la contrainte de taille pour les formes pouvant potentiellement
|
||
améliorer l’image, cependant la qualité des images générées est plus haute que
|
||
celle des version précédentes, voir en Annexes (§[[*M%C3%A9thode 3]]).
|
||
|
||
Cette méthode ne me semble que moyennement concluante, certes la vitesse
|
||
d’exécution du logiciel est beaucoup plus faible, mais il est également vrai que
|
||
la qualité des images générées est supérieure aux deux autres méthodes. Ainsi,
|
||
il sera possible d’utiliser les modifications apportées par cette méthode en
|
||
utilisant une option ~-s [ --size ]~ avec les méthodes suivantes pour activer
|
||
cette modification de l’algorithme.
|
||
|
||
** Concurrence entre threads
|
||
|
||
Une utilisation na
|
||
|
||
* Annexes
|
||
** Images
|
||
*** Méthode 1
|
||
#+CAPTION: Image générée à partir de ~img/mahakala-monochrome.png~ avec 2000 améliorations avec la première méthode
|
||
[[./output1.png]]
|
||
*** Méthode 2
|
||
#+CAPTION: Image générée à partir de ~img/mahakala-monochrome.png~ avec 2000 améliorations avec la seconde méthode
|
||
[[./output2.png]]
|
||
*** Méthode 3
|
||
#+CAPTION: Image générée à partir de ~img/mahakala-monochrome.png~ avec 2000 améliorations avec la troisième méthode
|
||
[[./output3.png]]
|