Calculer la valeur de π en comptant des pixels

Voici une méthode de truand pour calculer une approximation de la valeur du nombre π, simplement en comptant des pixels de couleurs...

La méthode est vraiment empirique et les mathématiciens pourront me jeter des tomates 🍅.

Définitions

  • l'aire d'un disque de rayon R est π * R * R
  • l'aire d'un carré de côté X est X * X. On déclare que X = 2 * R. L'aire du carré est donc 4 * R * R

Principe

On génère une image de 8x8, en noir et blanc, sans antialliasing, avec :

  • un carré blanc de côté X
  • un disque noir centré de rayon R
1⬜⬜⬛⬛⬛⬛⬜⬜
2⬜⬛⬛⬛⬛⬛⬛⬜
3⬛⬛⬛⬛⬛⬛⬛⬛
4⬛⬛⬛⬛⬛⬛⬛⬛
5⬛⬛⬛⬛⬛⬛⬛⬛
6⬛⬛⬛⬛⬛⬛⬛⬛
7⬜⬛⬛⬛⬛⬛⬛⬜
8⬜⬜⬛⬛⬛⬛⬜⬜

Maintenant on compte les pixels en les regroupant par couleur :

  • Total pixels image: 64
  • Total pixels disque: 52

π est une constante qui est liée au rapport entre l'aire du disque et l'aire du carré.

aire du disque / aire du carré = π * R * R / 4 * R * R = π / 4

π = aire disque / aire carré * 4

52 / 64 * 4 = 3.25

On est sur une approximation pas folle, mais qu'on a pu calculer de tête !

Plus l'image est grande, meilleur sera l'approximation de π, alors essayons maintenant de créer des images avec plus de pixels.

Génération automatisée d'une image de taille paramétrable

L'outil ImageMagick via sa commande convert permet de faire tout un tas de choses pour manipuler, redimensionner et générer des images.

100x100

Pour générer notre ascii art géométrique précédent avec un carré de 100 pixels cette fois :

1convert -size 100x100 xc: -draw 'circle 50,50,50,0' -colorspace gray -depth 1 circle-100.bmp

Je force une palette monochrome (soit couleur blanc soit couleur noir) pour ne pas avoir d'antialliasing. Le Format BMP était pour éviter la compression et pouvoir extraire plus facilement la donnée dans le fichier binaire mais je découvre que convert permet aussi de compter les pixels d'une couleur donnée 😎:

1$ convert circle-100.bmp -monochrome txt:- | grep -c '#000000'
27943

Notre image qui fait 10000 pixels (c'est aussi l'aire du carré ⬜) possède 7943 pixels noirs (c'est l'aire du cercle ⚫).

7943 / 10000 * 4 = 3.1772

un peu mieux !

1000x1000

On continue :

1$ convert -size 1000x1000 xc: -draw 'circle 500,500,500,0' -colorspace gray -depth 1 circle-1000.bmp
2$ convert circle-1000.bmp -monochrome txt:- | grep -c '#000000'
3786295

786295 / 1000000 * 4 = 3.14518

mieux !!

10000x10000

1$ convert -size 10000x10000 xc: -draw 'circle 5000,5000,5000,0' -colorspace gray -depth 1 circle-10000.bmp
2$ convert circle-10000.bmp -monochrome txt:- | grep -c '#000000'
378548891 # 1 minute de calcul sur Apple M1

78548891 / 100000000 * 4 = 3.14195564

Encore mieux !!

Et ainsi de suite ...

On pourrait aussi utiliser une palette en niveaux de gris plutôt que monochrome et affecter une pondération proportionnelle au niveau de gris, plutôt que de décupler le nombre de pixels qui rend le temps de calcul très long.

Ressources

comments powered by Disqus