Création d'une image en Python

Cette activité a pour but d'apprendre à créer des images numériques de toutes sortes en Python, en donnant des programmes modifiables afin de personnaliser les images (motifs et couleurs).

Commençons par dessiner une image "surfacique", c'est-à-dire une image où chaque pixel possède une couleur donnée par une équation en fonction des coordonnées x et y du pixel.

Voici un premier exemple dans lequel l'équation de la couleur est n=x*cos(x)+y*sin(y) :

# ##########################################################################
# Dessine une image surfacique pixel par pixel dans une fenêtre Matplotlib #
# Programme réalisé le 01 novembre 2022 par Jean-Christophe MICHEL         #
# www.gecif.net                                                            #
# ##########################################################################


import matplotlib.pyplot as plt
from math import *

x_min=-40
x_max=40
y_min=-40
y_max=40

# résolution de l'image :
res_x=500
res_y=500

tab = []

for py in range(1,res_y+1):
        ligne=[]
        for px in range(1,res_x+1):
                x=x_min+px*(x_max-x_min)/res_x
                y=y_max-py*(y_max-y_min)/res_y

                # pour modifier l'image il suffit de changer l'équation de n en fonction de x et de y :
                n=x*cos(x)+y*sin(y)

                ligne.append(n)

        tab.append(ligne)

# crée une figure dans la fenêtre :
fig=plt.figure(1, figsize=(8, 8))

# crée un axe dans la figure :
ax=fig.add_subplot(1,1,1)

# n'affiche pas les graduations sur les axes :
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)

# agrandit le repère à toute la surface de la figure :
plt.gcf().subplots_adjust(left = 0, bottom = 0, right = 1, top = 1, wspace = 0, hspace = 0)

# affiche l'image :
ax.imshow(tab)
plt.show()

Télécharger ce programme surfacique_base.pyw

Et voici l'image surfacique obtenue :

En modifiant l'équation de n en fonction de x et de y on change le motif de l'image surfacique. Voici quelques exemples à tester :

n=x*cos(y)+y*sin(x)
n=(x+y)*cos(y)*sin(x)
n=x*y*cos(y)*sin(x)
n=x*y*cos(y)**2*sin(x)**2
n=x*cos(x)**2+y*sin(y)**2
n=x*cos(y)**2+y*sin(x)**2
n=(int(x)%7)*cos(x)+(int(y)%11)*sin(y)
n=(int(x)%7)*cos(y)+(int(y)%7)*sin(x)
n=x**2*cos(y)+y**2*sin(x)
n=(x/10)**2+(y/10)**2
n=sin((x/8)**2+(y/8)**2)
n=cos((x/8+y/8)**2)
etc. à vous d'inventer la suite ...

La palette de couleur utilisée par défaut est une palette "arc-en-ciel" allant du bleu au rouge. Pour l'afficher dans une barre verticale, modifions les 2 dernières lignes du programme de base en les remplaçant par :

# affiche l'image :
im=ax.imshow(tab)
# affiche la palette de couleur utilisée dans une barre vertivale :
fig.colorbar(im, ax=ax, extend='min', orientation='vertical')
# met à jour la fenêtre pyplot :
plt.show()

Et voici le résultat avec cette fois l'équation n=x*y*cos(y)**2*sin(x)**2 pour la couleur des pixels :



Télécharger le programme surfacique_2.pyw

Il est tout à fait possible d'utiliser une autre palette de couleur que la palette arc-en-ciel par défaut : il faut alors préciser la palette à utiliser lors de l'appel de la fonction imshow. Voici quelques noms de palette à tester :

Blues
RdBu
OrRd
Reds
CMRmap
Dark2

Affichons par exemple l'image précédente en utilisant la palette de couleur RdBu (allant du Rouge au Bleu). Pour cela on appelle la fonction imshow avec un nouveau paramère cmap précisant le nom de la palette à utiliser :

# affiche l'image :
im=ax.imshow(tab, cmap='RdBu')
# affiche la palette de couleur utilisée dans une barre vertivale :
fig.colorbar(im, ax=ax, extend='min', orientation='vertical')
# met à jour la fenêtre pyplot :
plt.show()

Et voici le résultat :

Remarque : les palettes de couleurs prédéfinies sont des propriétés de l'objet plt.cm. Pour en obtenir la liste on pourra taper dir(plt.cm) dans la console de Pyton.

En voici une liste reconstituée :

liste_palette=['Accent',
'Accent_r',
'Blues',
'Blues_r',
'BrBG',
'BrBG_r',
'BuGn',
'BuGn_r',
'BuPu',
'BuPu_r',
'CMRmap',
'CMRmap_r',
'Dark2',
'Dark2_r',
'GnBu',
'GnBu_r',
'Greens',
'Greens_r',
'Greys',
'Greys_r',
'OrRd',
'OrRd_r',
'Oranges',
'Oranges_r',
'PRGn',
'PRGn_r',
'Paired',
'Paired_r',
'Pastel1',
'Pastel1_r',
'Pastel2',
'Pastel2_r',
'PiYG',
'PiYG_r',
'PuBu',
'PuBuGn',
'PuBuGn_r',
'PuBu_r',
'PuOr',
'PuOr_r',
'PuRd',
'PuRd_r',
'Purples',
'Purples_r',
'RdBu',
'RdBu_r',
'RdGy',
'RdGy_r',
'RdPu',
'RdPu_r',
'RdYlBu',
'RdYlBu_r',
'RdYlGn',
'RdYlGn_r',
'Reds',
'Reds_r',
'Set1',
'Set1_r',
'Set2',
'Set2_r',
'Set3',
'Set3_r',
'Spectral',
'Spectral_r',
'YlGn',
'YlGnBu',
'YlGnBu_r',
'YlGn_r',
'YlOrBr',
'YlOrBr_r',
'YlOrRd',
'YlOrRd_r']

Le programme surfacique_3.pyw tire au hasard une palette parmi les 72 palettes de la liste liste_palette puis affiche l'image surfacique utilisant l'équation n=sin((x/8)**2+(y/8)**2) en précisant le nom de la palette utilisée. Voici quelques résultats :

Télécharger le programme surfacique_3.pyw

Et voici un autre exemple d'image surfacique. Toutes les images suivantes sont en résolution 800x600 pixels et utilisent la palette de couleur CMRmap (sans l'afficher sur l'image).

Cette fois l'équation de n donne une valeur entière (grâce à la fonction int de Python) , mais surtout contient l'opérateur modulo (% en Python) qui permet de régler "le nombre de couleurs" qui sera utilisé dans l'image (donc indirectement le contraste de l'image).

Exemple d'équation : n=int(x*cos(x)+y*sin(y)) % 100

Et voici les résultats pour différentes valeurs du diviseur (% 100, % 50 et % 200) :


n=int(x*cos(x)+y*sin(y)) % 100


n=int(x*cos(x)+y*sin(y)) % 50


n=int(x*cos(x)+y*sin(y)) % 200

On peut aussi modifier l'équation de n. Par exemple tout simplement le produit x*y. Voici 3 exemples avec 3 modulos différents :


n=int(x*y) % 50


n=int(x*y) % 100


n=int(x*y) % 200

Enfin on peut également modifier la taille du zoom. Pour cela on va utiliser un coefficient coeff_zoom afin de multiplier par 2, 4, 5, 10 20, etc. les 4 variables x_min, x_max, y_min et y_max :

coeff_zoom=4
x_min=-4.44350838253174E+0001*coeff_zoom
x_max=4.31538338253302E+0001*coeff_zoom
y_min=-3.29278753690077E+0001*coeff_zoom
y_max=3.27638128689780E+0001*coeff_zoom

Voici quelques exemples :


coeff_zoom=4 et n=int(x*y) % 50


coeff_zoom=10 et n=int(x*y) % 100


coeff_zoom=2 et n=int(x*cos(x)+y*sin(y)) % 100


coeff_zoom=2 et n=int(x*cos(y)+y*sin(x)) % 100

Télécharger le programme surfacique_4.pyw

Voici d'autres palettes de couleurs illustrées (à tester), certaines donnent de très beaux résultats (hsv, prism, ou gist_rainbow par exemple) :

Liste de ces palettes de couleurs : ['Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', 'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', 'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn']

Liste de ces palettes de couleurs : ['twilight', 'twilight_shifted', 'hsv']

Liste de ces palettes de couleurs : ['PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', 'RdYlBu', 'RdYlGn', 'Spectral', 'coolwarm', 'bwr', 'seismic']

Liste de ces palettes de couleurs : ['Pastel1', 'Pastel2', 'Paired', 'Accent', 'Dark2', 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c']

Liste de ces palettes de couleurs : ['binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink', 'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia', 'hot', 'afmhot', 'gist_heat', 'copper']

Liste de ces palettes de couleurs : ['flag', 'prism', 'ocean', 'gist_earth', 'terrain', 'gist_stern', 'gnuplot', 'gnuplot2', 'CMRmap', 'cubehelix', 'brg', 'gist_rainbow', 'rainbow', 'jet', 'turbo', 'nipy_spectral', 'gist_ncar']

Pour illustrer ces nouvelles palettes de couleurs, nous repartons du programme surfacique_4.pyw mais dans lequel on va décaler les valeurs de base du zoom :

coeff_zoom=2
decalage_x=20
decalage_y=20

x_min=-4.44350838253174E+0001*coeff_zoom+decalage_x
x_max=4.31538338253302E+0001*coeff_zoom+decalage_x
y_min=-3.29278753690077E+0001*coeff_zoom+decalage_y
y_max=3.27638128689780E+0001*coeff_zoom+decalage_y

Voici quelques exemples d'images obtenues :

Éléments principaux du programme : Image surfacique obtenue :

coeff_zoom=2
decalage_x=20
decalage_y=20

n=int(x*cos(y)+y*sin(x)) % 100

ax.imshow(tab, cmap='gist_rainbow')

coeff_zoom=0.5
decalage_x=80
decalage_y=80

n=int(x*cos(x)+y*sin(y)) % 100


ax.imshow(tab, cmap='rainbow')

coeff_zoom=0.5
decalage_x=80
decalage_y=80

n=int(x*cos(x)**2+y*sin(y)**2) % 100

ax.imshow(tab, cmap='hsv')

coeff_zoom=1/4
decalage_x=0
decalage_y=0

n=int((x*cos(x)+y*sin(y))**2) % 100

ax.imshow(tab, cmap='prism')

coeff_zoom=1/8
decalage_x=10
decalage_y=10

n=int((x*cos(y)+y*sin(x))**2) % 50

ax.imshow(tab, cmap='jet')

coeff_zoom=1/4
decalage_x=10
decalage_y=10

n=int(x**2*cos(y)+y**2**sin(x)) % 50

ax.imshow(tab, cmap='brg', interpolation='none')

 

Voici d'autres équations donnant une valeur à n en fonction des coordonnées x et y de chaque pixel, à tester pour générer de nouvelles images surfaciques :

n=(255*(cos($y)*sin(x)+1)) % 255
n=(255*(cos(y)+sin(x)+1)) % 255
n=(255*x*(cos(y)*sin(x)+1)) % 255
n=(255*y*(cos(y)*sin(x)+1)) % 255
n=(255*(y*(cos(x*x)+1)+x*(sin(y*y)+1))) % 255
n=(255*(y*(cos(x*y)+1)+x*(sin(x*y)+1))) % 255
n=(255*(cos(y)*sin(y)*sin(x)*cos(x)+1)) % 255
n=(255*(cos(y)*sin(y)+sin(x)*cos(x)+1)) % 255
n=(255*(cos(y)*cos(x)+sin(x)*sin(y)+1)) % 255
n=(x*cos(y)) % 255
n=(y*cos(x)) % 255
n=(x**3 + y**3) % 255
n=x*y
n=(y*(x_max-x)*cos(x*y)+x*(y_max-y)*sin(x*y)) % 255
n=(x*cos(y) +y*sin(x) ) % 255
n=(255*(cos(y*sin(x*y)+x*sin(y*x))+1)) % 255
n=(x*x*cos(y) +y*y*sin(x) ) % 255
n=(x*y*cos(y) +y*x*sin(x) ) % 255
n=(x*x*cos(x) + y*y*sin(y) ) % 255
n=(x*x*y*cos(y) +y*y*sin(x) ) % 255
n=(x*y*cos(y) +y*x*x*sin(x) ) % 255
n=(x*x*x*cos(x) + y*y*y*sin(y) ) % 255
n=(255*(cos(x*y)+1)) % 255
n=(255*(cos(y*sin(x)+x*sin(y))+1)) % 255
n=(255*(sin(x)+1)) % 255
n=(255*(sin(y)+1)) % 255
n=(255*(cos(y)*sin(x)+1)) % 255
n=(255*(cos(y)+sin(x)+1)) % 255
n=(255*(cos(y*x)*sin(x*y)+1)) % 255
n=(255*(cos(y)*sin(x)+1)*(cos(y)+sin(x)+1)) % 255
n=(255*(y*cos(y)+x*sin(x)+1)) % 255
n=(255*(y*cos(x)+x*sin(y)+1)) % 255
n=(255*((cos(x)+1)-(sin(y)+1))) % 255
n=(255*((cos(x)+1)+(sin(y)+1))) % 255
n=(255*(cos(y+x)*sin(x*y)+1)) % 255
n=(255*(y*(cos(x*y)+x*sin(x*y)))) % 255
n=127*sin((px/res_x)*6.2831853*echelle)+128
n=127*cos((px/res_x)*6.2831853*echelle)+128
n=127*cos((py/res_y)*6.2831853)+128
n=127*sin((py/res_y)*6.2831853)+128
n=(py/res_y)*255
n=(px/res_x)*255
n=(px/res_x)*128+(py/res_y)*127
n=127*sin((px/res_x)*3.14159265)+128
n=127*cos((px/res_x)*3.14159265)+128
n=127*cos((py/res_y)*3.14159265)+128
n=255*cos(x*y+x*y)
n=255*cos(x*x+y*y)
n=255*sin(x*x+y*y)
n=255*sin(x*y+y*x)
n=127*sin((px/res_x)*6.2831853*echelle)+128
n=127*cos((px/res_x)*6.2831853*echelle)+128
n=127*cos((py/res_y)*6.2831853*echelle)+128
n=127*sin((py/res_y)*6.2831853*echelle)+128
n=(py/res_y)*255
n=(px/res_x)*255
n=(px/res_x)*128+(py/res_y)*127
n=127*sin((px/res_x)*6.2831853*echelle)+128*sin((py/res_y)*6.2831853*echelle)
n=(255*(cos(x*y)+1)) % 255
n=(255*(cos(y)*sin(x)+1)) % 255


Remarques concernant ces 60 nouvelles équations de n :

  • les coefficients 255 et 127 permettent de limiter le nombre de couleurs utilisées dans l'image et peuvent être remplacer par d'autres valeurs (à tester)
  • la variable echelle est un entier entre 1 et 30 (à tester également)
  • évidemment ces équations ne donneront de belles images surfaciques seulement si le zoom est correctement configurer : valeurs des 4 variables x_min, x_max, y_min et y_max à rechercher ...

Les valeurs de base peuvent être un des 3 cas suivants :

x_min=-50
x_max=50
y_min=-50
y_max=50

x_min=-25
x_max=25
y_min=-25
y_max=25

x_min=-12.5
x_max=12.5
y_min=-12.5
y_max=12.5

Pour visiter une galerie de plus de 10 000 images surfaciques utilisant certaines de ces 60 équations, cliquez-ici.

Libre à vous maintenant de tester différentes palettes de couleurs et surtout de complexifier l'équation de la couleur des pixels en donnant à la variable n une valeur en fonction des coordonnées x et de y de chaque pixel. La seule limite sera alors votre imagination !

Les ensembles de Julia

Voici le programme en Python qui calcule un ensemble de Julia :

# ########################################################################
# Trace un ensemble de Julia pixel par pixel dans une fenêtre Matplotlib #
# Programme réalisé le 02 novembre 2022 par Jean-Christophe MICHEL       #
# www.gecif.net                                                          #
# ########################################################################


import matplotlib.pyplot as plt
import math

# ensemble de Julia complet :
x_min=-1.55974934894274
x_max=1.73429361977433
y_min=-1.23556315104494
y_max=1.23496907549286

# résolution de l'image :
res_x=640
res_y=480

# calcul du nombre d'itérations en fonction du grossissement :
grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*10000+200)

tab = []
pour_cent=0
print("Grossissement : %g" % grossissement)
print("Nombre d'itérations :",iter_max)
print("Progression du calcul de l'image :")

for py in range(1,res_y+1):
        ligne=[]
        if py % (res_y//10)==0:
                pour_cent+=10
                print("%d %% calculé ..." % pour_cent)
        for px in range(1,res_x+1):
                n=0
                x=x_min+px*(x_max-x_min)/res_x
                y=y_max-py*(y_max-y_min)/res_y
                z=complex(x,y)

                # ####################################################################
                # L'ensemble de Julia dépend de la valeur du nombre complexe z2 :
                # ####################################################################

                #z2=complex(-0.0986,-0.65186)
                #z2=complex(0.32,0.043)

                z2=complex(-0.772691322542185,0.124281466072787)
                #z2=complex(-4.05253601070165E-0001,-6.44628651946028E-0001)
                #z2=complex(-8.60671234122251E-0001,2.66206614158146E-0001)
                #z2=complex(3.77390034989716E-0001,1.04280344628515E-0001)
                #z2=complex(1.98028564451152E-0002,6.71022287982223E-0001)
                #z2=complex(-3.07991027828944E-0002,6.98009999570495E-0001)
                #z2=complex(2.99800364173435E-0001,2.33172098636993E-0002)
                #z2=complex(2.93053436276367E-0001,-2.97037776038500E-0004)
                # ####################################################################


                while(abs(z)<2):
                        z=z*z+z2
                        n+=1
                        if n>=iter_max:
                                break
                ligne.append(n)

        tab.append(ligne)

# crée une figure dans la fenêtre et un axe dans la figure :
fig=plt.figure(1, figsize=(6.4, 4.8))
ax=fig.add_subplot(1,1,1)

# n'affiche pas les graduations sur les axes :
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)

# agrandi le repère à toute la surface de la figure :
plt.gcf().subplots_adjust(left = 0, bottom = 0, right = 1, top = 1, wspace = 0, hspace = 0)

# affiche l'image :
ax.imshow(tab, cmap='RdBu', interpolation='none')
plt.show()

Télécharger le programme julia.pyw

Pour obtenir différentes images fractales d'un ensemble de Julia on pourra modifier soit la valeur de z2, soit la palette de couleur, soit les deux (sur les lignes en rouge dans le programme ci-dessus).

Et voici quelques exemples d'ensembles de Julia, utilisant chacun une valeur précise pour le nombre complexe z2 et une palette de couleur particulière :

z2=complex(-0.772691322542185,0.124281466072787) avec la palette RdBu :

 

z2=complex(-0.7927,0.1609) avec la palette Greys :

 

z2=complex(-1.1380,0.2403) avec la palette BuPu :


z2=complex(-0.1225,0.7449) avec la palette Reds_r :

 

z2=complex(-0.3380,-0.6230) avec la palette YlOrBr :

 

z2=complex(0.32,0.043) avec la palette PuBuGn :

 

z2=complex(-0.0986,-0.65186) avec la palette RdYlGn_r et iter_max=1000 :

 

z2=complex(-4.05253601070165E-0001,-6.44628651946028E-0001) avec la palette PuOr_r :

 

z2=complex(-8.60671234122251E-0001,2.66206614158146E-0001) avec la palette Reds :

 

z2=complex(3.77390034989716E-0001,1.04280344628515E-0001) avec la palette Paired_r :

 

z2=complex(1.98028564451152E-0002,6.71022287982223E-0001) avec la palette RdGy_r :

 

z2=complex(-3.07991027828944E-0002,6.98009999570495E-0001) avec la palette PiYG_r :

 

z2=complex(2.99800364173435E-0001,2.33172098636993E-0002) avec la palette Spectral :
z2=complex(2.93053436276367E-0001,-2.97037776038500E-0004) avec la palette CMRmap_r :

 

Pour voir des ensembles de julia en mouvement, cliquez ici.

 

L'ensemble de Mandelbrot

Voici le programme de base qui calcule et affiche l'ensemble de Mandelbrot :

# ############################################################################
# Trace l'ensemble de Mandelbrot pixel par pixel dans une fenêtre Matplotlib #
# Programme réalisé le 03 novembre 2022 par Jean-Christophe MICHEL           #
# www.gecif.net                                                              #
# ############################################################################


import matplotlib.pyplot as plt
import math

# Ensemble de Mandelbrot complet :
x_min=-2.61458333330719
x_max=1.33333333332000
y_min=-1.56250000000000
y_max=1.39843749997039


# résolution de l'image :
res_x=640
res_y=480

# calcul automatique du nombre d'itérations en fonction du zoom :
grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*10000+200)

tab = []
pour_cent=0
print("Grossissement : %g" % grossissement)
print("Nombre d'itérations :",iter_max)
print("Progression du calcul de l'image :")

for py in range(1,res_y+1):
        ligne=[]
        if py % (res_y//10)==0:
                pour_cent+=10
                print("%d %% calculé ..." % pour_cent)
        for px in range(1,res_x+1):
                n=0
                x=x_min+px*(x_max-x_min)/res_x
                y=y_max-py*(y_max-y_min)/res_y
                z=complex(x,y)
                z2=z
                while(abs(z)<2):
                        z=z*z+z2
                        n+=1
                        if n>=iter_max:
                                break
                ligne.append(n)

        tab.append(ligne)

# crée une figure dans la fenêtre et un axe dans la figure :
fig=plt.figure(1, figsize=(6.4, 4.8))
ax=fig.add_subplot(1,1,1)

# n'affiche pas les graduations sur les axes :
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)

# agrandi le repère à toute la surface de la figure :
plt.gcf().subplots_adjust(left = 0, bottom = 0, right = 1, top = 1, wspace = 0, hspace = 0)

# affiche l'image :
ax.imshow(tab, cmap='PuBuGn', interpolation='none')
plt.show()

Télécharger le programme mandelbrot.pyw

Voici le résultat de ce programme : on obtient l'ensemble de Mandelbrot complet :


Ensemble de Mandelbrot complet (200 itérations)


Ensemble de Mandelbrot complet (avec 40 itérations seulement et la palette RdBu)

Pour obtenir un très grand nombre d'images fractales toutes différentes, il faut effectuer des zooms sur les frontières de l'ensemble de Mandelbrot. Pour cela il faut modifier les valeurs des 4 variables x_min, x_max, y_min et y_max en rouge dans le programme ci-dessus.

On pourra également modifier la palette de couleur utilisée lors de l'appel de la méthode imshow qui affiche l'image, ou encore forcer le nombre d'itérations avec la variable iter_max.

Et voici quelques exemples d'images fractales correspondant à un zoom dans l'ensemble de Mandelbrot. Les dimensions du zoom (valeur des 4 variables x_min, x_max, y_min et y_max), le nombre d'itérations (variable iter_max) ainsi que la palette de couleur utilisée sont précisé pour chaque image :

# Zoom dans l'ensemble de Mandelbrot :
x_min=-7.93387099211429E-0001
x_max=-7.93347007821297E-0001
y_min= 1.61323683223294E-0001
y_max= 1.61353751765894E-0001

iter_max=400

Palette de couleur RdBu

 

# Zoom dans l'ensemble de Mandelbrot :
x_min=-7.89042630970518E-0001
x_max=-7.88953625996330E-0001
y_min= 1.61733969013150E-0001
y_max= 1.61800722743791E-0001

iter_max=400

Palette de couleur PiYG

# image 93A4759A :
x_min=-0.751105944308082529
x_max=-0.751045703880430127
y_min=0.026130437835065461
y_max=0.026175618155804756

Palette de couleur CMRmap_r

# image A36B94 :
x_min=0.273101806637893407
x_max=0.274065653480331684
y_min=-0.006128311172790656
y_max=-0.005405426040961947

iter_max=400

Palette de couleur Greys

# image 62D59 :
x_min=-0.066172281900380714
x_max=-0.062316894530627595
y_min=-0.666122436532401552
y_max=-0.663230896005086668

iter_max=400

Palette de couleur BuPu

# image 9717547B :
x_min=-0.774659951520167978
x_max=-0.774599711092515575
y_min=0.118479013426182972
y_max=0.118524193746922260

iter_max=400

Palette de couleur PuOr_r

# image A36F949 :
x_min=0.273342768348502962
x_max=0.273583730059112518
y_min=0.005799293502383034
y_max=0.005980014785340211

iter_max=800

Palette de couleur Greys

# image 5F9A :
x_min=-0.794840494783719431
x_max=-0.779418945304707012
y_min=-0.151428222670361046
y_max=-0.139862060561101703

iter_max=400

Palette de couleur OrRd

# image 5F9A7 :
x_min=-0.783274332674460116
x_max=-0.779418945304707012
y_min=-0.148536682143046217
y_max=-0.145645141615731388

iter_max=300

Palette de couleur PiYG_r

# image 5F9A792 :
x_min=-0.781828562410802674
x_max=-0.781587600700193064
y_min=-0.147090911879388803
y_max=-0.146910190596431622

iter_max=400

Palette de couleur CMRmap_r

# image E1321 :
x_min=-0.174123128253467957
x_max=-0.170267740883714852
y_min=0.658203124977792431
y_max=0.661094665505107315

iter_max=400

Palette de couleur PRGn

# image 67A4F5 :
x_min=0.235511779782800551
x_max=0.236475626625238827
y_min=-0.523714065562145947
y_max=-0.522991180430317226

iter_max=800

Palette de couleur YlGnBu_r

# image 62CB99 :
x_min=-0.096051534015967360
x_max=-0.095087687173529084
y_min=-0.653110504159484795
y_max=-0.652387619027656074

iter_max=800

Palette de couleur YlGnBu

# image 972594 :
x_min=-0.744720458976929067
x_max=-0.743756612134490735
y_min=0.121099472029062044
y_max=0.121822357160890751

iter_max=800

Palette de couleur Spectral_r

# image 97699555 :
x_min=-0.743455409996228722
x_max=-0.743395169568576319
y_min=0.179156184179055183
y_max=0.179201364499794485

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image AEDCC5555 :
x_min=-0.084169109661532959
x_max=-0.084154049554619859
y_min=0.656271666266187714
y_max=0.656282961346372540

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image A374DA1 :
x_min=0.290692011512391990
x_max=0.290932973223001545
y_min=-0.014080047622906450
y_max=-0.013899326339949274

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image 62D53D :
x_min=-0.057497660318436214
x_max=-0.056533813475997938
y_min=-0.669736862191545046
y_max=-0.669013977059716325

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image A36B709 :
x_min=0.281053543088009228
x_max=0.281294504798618783
y_min=-0.009381294266019845
y_max=-0.009200572983062668

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image A36B705 :
x_min=0.281053543088009228
x_max=0.281294504798618783
y_min=-0.009562015548977022
y_max=-0.009381294266019845

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image 5F9A6C :
x_min=-0.787129720044213221
x_max=-0.786165873201774890
y_min=-0.146368026747560082
y_max=-0.145645141615731361

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

# image 976D0B :
x_min=-0.745684305819367288
x_max=-0.744720458976928956
y_min=0.185436248761817080
y_max=0.186159133893645801

grossissement=4/(x_max-x_min)
iter_max=int((math.log10(grossissement)/12)*1000+100)

Palette de couleur RdBu

Pour explorer l'ensemble de Mandelbrot, cliquez-ici. Dans l'explorateur de l'ensemble de Mandelbrot, chaque image porte un numéro précis permettant de l'identifier.

Le programme suivant calcule la taille du zoom (valeur des 4 variables x_min, x_max, y_min et y_max) en fonction du numéro de l'image :

# ############################################################################
# Ce programme zoom.pyw calcule les coordonnées d'une image correspondant à  #
# un zoom dans l'ensemble de Mandelbrot en fonction du numéro de l'image     #
# donné par l'explorateur de l'ensemble de Mandelbrot sur Gecif.net          #
#                                                                            #
# Programme réalisé le 31 octobre 2022 par Jean-Christophe MICHEL            #
# www.gecif.net                                                              #
# ############################################################################


def colonne(i):
        # cette fonction renvoie la colonne (entre 0 et 3) de la portion i (0<=i<=15)
        return i % 4

#****************************************************************************

def ligne(i):
        # cette fonction renvoie la ligne (entre 0 et 3) de la portion i (0<=i<=15)
        if i in [0,1,2,3]:
                return 0
        if i in [4,5,6,7]:
                return 1
        if i in [8,9,10,11]:
                return 2
        if i in [12,13,14,15]:
                return 3

#****************************************************************************

# Ensemble de Mandelbrot complet :
x_min=-2.61458333330719
x_max=1.33333333332000
y_min=-1.56250000000000
y_max=1.39843749997039

image="5FD76"
niveau=len(image)-1
largeur_x=(x_max-x_min)/4
largeur_y=(y_max-y_min)/4
origine_x=x_min
origine_y=y_min

for i in range(niveau):
        c=image[i]
        origine_x=origine_x+largeur_x*colonne(int(c,16))
        origine_y=origine_y+largeur_y*ligne(int(c,16))
        largeur_x=largeur_x/4
        largeur_y=largeur_y/4

c=image[-1]
x_min=origine_x+colonne(int(c,16))*largeur_x
y_min=origine_y+ligne(int(c,16))*largeur_y
x_max=x_min+largeur_x
y_max=y_min+largeur_y

print("# image %s :" % image)
print("x_min=%.18f" % x_min)
print("x_max=%.18f" % x_max)
print("y_min=%.18f" % y_min)
print("y_max=%.18f" % y_max)

Télécharger le programme zoom.pyw

Par exemple pour l'image n°5FD76 le programme affiche les lignes suivantes, directement utilisables dans le programme mandelbrot.pyw :

# image 5FD76 :
x_min=-0.771708170565200802
x_max=-0.767852783195447697
y_min=-0.113838195815268217
y_max=-0.110946655287953388

En modifiant la valeur de la variable image dans le programme zoom.pyw (en rouge dans le code source ci-dessus) vous obtenez instantanément la valeur du zoom (valeur des 4 variables x_min, x_max, y_min et y_max) à utiliser dans le programme mandelbrot.pyw afin d'obtenir l'image correspondante.

Et pour finir voici l'image n°61FA7A en haute résolution (1280x1024 pixels) :

Voici les lignes à modifier dans le programme mandelbrot.pyw pour obtenir une telle image :

# image 61FA7A :
x_min=-0.164484659829085167
x_max=-0.163520812986646891
y_min=-0.656002044686799568
y_max=-0.655279159554970847

 

# résolution de l'image :
res_x=1280
res_y=1024

 

# nombre d'itérations fixe :
iter_max=800

 

# crée une figure dans la fenêtre et un axe dans la figure :
fig=plt.figure(1, figsize=(12.8, 10.24))

 

# affiche l'image :
ax.imshow(tab, cmap='PuBuGn', interpolation='none')

 

Pour visiter une galerie de plus de 100 000 images fractales, cliquez-ici.

Pour voir des vidéos représentant des zooms dans l'ensemble de Mandelbrot, cliquez-ici.

 

Générateur automatique d'images fractales issues de l'ensemble de Mandelbrot

Le programme gene_mandelbrot.pyw permet de générer automatiquement un ensemble d'images à partir d'une liste.

Pour programmer les images il suffit de renseigner la liste liste_images en y indiquant les numéros des images à calculer :

# liste des images à créer :
liste_images=['A36AF14','A36AF18','A36AF19']

Ce programme n'affiche pas les images à l'écran, mais il les enregistre directement dans des fichiers PNG portant le numéro de l'image (par exemple A36AF18.png pour l'image n°A36AF18), avec une résolution de 800x600 pixels (et 100 pixels par pouce) et en utilisant la palette de couleur RdBu.

Pour préparer la liste des images à calculer en Python on peut utiliser l'explorateur de l'ensemble de Mandelbrot sur Gecif.net.

Il est alors très facile de préparer une liste d'images en quelques clics et par un simple copier/coller . Exemple :

# liste des images à créer :
liste_images=['9759',
'9752',
'97550',
'97551',
'97552',
'97553',
'97554',
'97555',
'97556',
'97557',
'97558',
'97559',
'9755A',
'9755B',
'9755C',
'9755D',
'9755E',
'9755F']

Libre à vous désormais d'aller explorer l'ensemble de Mandelbrot à la recherche d'images fractales exceptionnelles et encore jamais calculées !

 

  

 

Site Internet : python.gecif.net

Auteur : Jean-Christophe MICHEL

Professeur de Sciences Industrielles de l'Ingénieur
option Informatique et Numérique

Courriel : jc.michel@gecif.net