genetic-images/report/report.org
2019-03-24 22:57:04 +01:00

8.2 KiB
Raw Blame History

Création dimages par algorithme génétique avec référence

Sujet

Le sujet de ce projet est la création dun 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. Lalgorithme commence par créer une image vide aux dimensions identiques à limage de référence, puis applique une de ces formes aléatoires. Si la ressemblance de limage ainsi générée augmente par rapport à sa version précédente par rapport à limage 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 limage. Sauf indication contraire, jai utilisé dans limplémentation de chaque méthode des carrés comme forme déléments appliqués aléatoirement à limage.

Pour évaluer la ressemblance entre deux image, jévalue une distance euclidienne entre le vecteur de leurs pixels qui peut se résumer à ceci :

V étant le vecteur de pixels de limage de référence, W étant le vecteur de pixels de limage 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 dun 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 doptimisation -O3 et -flto.

Voici également ci-dessous la liste des options et arguments possibles concernant lexé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 dexé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 dexé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

Jai tout dabord implémenté la méthode naïve afin davoir 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 mattendais, cette méthode de génération dimages est très lente, principalement dû au fait que lalgorithme en létat essaiera dappliquer des couleurs nexistant pas dans limage de référence, voire complètement à lopposées de la palette de couleurs de limage de référence.

Voici les moyennes de temps dexécution selon le nombre ditérations réussies sur le nombre dexécutions indiqué.

/ < < <
Nombre ditérations Temps dexécution Variation Nombre dexé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 dexécution"
  set size ratio square
  set key box linestyle -1
  set key top left

  set xlabel "Nombre dité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/media/commit/e1a7b127af362a01df86b7f0ac1e9a8234912bf8/report/temps1.png

Naturellement, la variation en temps dexécution croît en même temps que le nombre daméliorations nécessaires à apporter à limage à améliorer, dû à la nature aléatoire de lalgorithme. Cependant, on constate également une croissance importante du temps dexécution suivant également ce nombre ditérations réussies.

Réduction du panel des couleurs

Constatant que la majorité des échecs dajout de formes de couleur par la première méthode échouent dû à une couleur incorrecte, voire nappartenant pas à limage de référence, jai décidé de restreindre les possibilités de couleurs parmis lesquelles le hasard peut choisir à la liste des couleurs présentes dans limage de référence uniquement. Ce choix se fait donc via limplémentation dun set de valeurs uniques représentant les couleurs trouvées dans limage de référence, leur détection étant réalisée avec des threads parallèles pour plus de rapidité à lexécution. Cette méthode est celle implémentée dans la fonction method2() dans src/methods.cc.

Voici les moyennes de temps dexécution selon le nombre ditérations réussies sur le nombre dexécutions indiqué.

/ < < <
Nombre ditérations Temps dexécution Variation Nombre dexécutions
10 0.051697 0.000413 200
50 0.28958 0.00713 100
100 0.9058 0.0266 50
200 3.2047 0.0921 20
500 21.70 1.57 10
1000 78.58 5.06 5
  reset
  set title "Temps dexécution"
  set size ratio square
  set key box linestyle -1
  set key top left

  set xlabel "Nombre dité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é dexécution du logiciel. Étant donné que cette modification ne sera à priori pas en conflit avec dautres 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