You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

8.2 KiB

Création d’images par algorithme génétique avec référence

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 :

$$\sqrt{\sum_{i=0}^{n} V_{i}^{2}+W_{i}^{2}}$$

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.

  $ ./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

Voici la ligne de commande utilisée depuis le répertoire build afin de pouvoir obtenir un temps d’exécution :

  perf stat -r {nombreExécutions} -B ./bin/genetic-image \
       -i ../img/mahakala-monochrome.jpg -o output.png   \
       -n {nombreIterations} -m 1

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 :

  perf stat -r 1 -B ./bin/genetic-image \
       -i ../img/mahakala-monochrome.jpg -o output.png -n 20 -m 1

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é.

/ < < <
Nombre d’itérations Temps d’exécution Variation Nombre d’exécutions
10 0.08371 0.00249 200
50 1.0966 0.0320 100
100 3.835 0.118 50
200 13.274 0.547 20
500 73.47 2.49 10
1000 293.11 10.96 5
  reset
  set title "Temps d’exécution"
  set size ratio square
  set key box linestyle -1
  set key top left

  set xlabel "Nombre d’itérations"
  set xrange[0 : 7]
  set xtics nomirror rotate by -45

  set yrange [0 : *]
  set ylabel "Temps (s)"
  set ytics nomirror
  set log y 2;

  set y2range [* : *]
  set y2label "Variation (s)"
  set log y2 2
  set y2tics 0,0.5,3.5

  set style data points
  plot data u 2:xticlabels(1) axis x1y1 lw 3 title 'Temps', \
       data u 3:xticlabels(1) axis x1y2 lw 3 title 'Variation'

/phundrak/genetic-images/src/commit/d9f2a2267c70cda51b7ba8778c0b5bc9b301ba22/report/temps1.png

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.

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é.

/ < < <
Nombre d’itérations Temps d’exécution Variation Nombre d’exécutions
10 0.051697 0.000413 200
50 100
100 50
200 20
500 10
1000 5
  reset
  set title "Temps d’exécution"
  set size ratio square
  set key box linestyle -1
  set key top left

  set xlabel "Nombre d’itérations"
  set xrange[0 : 7]
  set xtics nomirror rotate by -45

  set yrange [0 : *]
  set ylabel "Temps (s)"
  set ytics nomirror
  set log y 2;

  set y2range [* : *]
  set y2label "Variation (s)"
  set log y2 2
  set y2tics 0,0.5,3.5

  set style data points
  plot data u 2:xticlabels(1) axis x1y1 lw 3 title 'Temps', \
       data u 3:xticlabels(1) axis x1y2 lw 3 title 'Variation'

On peut remarquer une très nette amélioration de la rapidité d’exécution du logiciel. É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 limiter

Concurrence entre threads

Une utilisation na