2
votes

Créer un échiquier dans PIL

Contexte

J'ai essayé de créer un échiquier dans le module PIL et j'ai le modèle général pour les deux premières lignes, mais je n'arrive pas à comprendre comment l'appliquer à l'ensemble du tableau. Comme vous pouvez le voir, j'ai créé une image:

# hardcoded to check patterns
for i in black_1:
    pixels[i,0] = (0,0,0)

for k in black_2:
    pixels[k,1] = (0,0,0)

img.show()

Ma solution pour les deux premières lignes

Note - J'apprends toujours Python donc ce code peut sembler très inefficace, mais n'hésitez pas à suggérer des améliorations.

La deuxième ligne:

Code:

black_1 = [i-1 for i in black_2 if i > 0]
if img.size[0] % 2 == 0: # 'that' if statement
    black_1.append(img.size[0]-1)

Cela me donne toutes les positions d'index horizontales sur où mettre un pixel noir . Par conséquent, pour le tableau 15x15 que j'ai créé, il renvoie [0, 2, 4, 6, 8, 10, 12, 14]

La première ligne:

Code:

J'utilise ensuite la deuxième ligne pour calculer les positions d'index horizontales pour la première ligne

black_2 = []
for i in range(img.size[0]):
    if i % 2 == 0:
        black_2.append(i)

Pour le tableau 15x15 pixels I créé, il renvoie [1, 3, 5, 7, 9, 11, 13] . J'ai créé cette instruction if parce que je me suis rendu compte que le dernier pixel noir ne montrait pas si le tableau avait une longueur égale, et cela semblait le corriger.

Changer les pixels en noir:

from PIL import Image

img = Image.new("RGB", (15,15), "white") # create a new 15x15 image
pixels = img.load() # create the pixel map

Comment puis-je appliquer les deux motifs au reste du tableau, quelle que soit sa taille?

Je soupçonne qu'une boucle for var in range () est nécessaire, mais je ne sais pas comment cela changerait en fonction de la hauteur ( img.size [ 1] ) du tableau est impair ou pair.

Modèle global jusqu'à présent:

 Chessboard

black_1 s'applique à la première ligne

black_2 s'applique à la deuxième ligne


0 commentaires

4 Réponses :


0
votes

Vous pouvez utiliser PIL.Image.paste pour coller img sur lui-même.

for n in range(15/2):
    img.paste(img, (0, n*2))

En utilisant tout votre code existant, ajoutez simplement ceci en bas.


3 commentaires

Que seraient HEIGHT_OF_THE_BOARD_IN_SQUARES et HEIGHT_OF_A_SQUARE_IN_PX dans le contexte d'une image de 15 sur 15 pixels?


Oui, désolé, j'ai raté cette partie.


Je pensais que tu avais plusieurs pixels par carré



4
votes

Un échiquier a 64 carrés au lieu de 256. Premièrement, vous avez besoin de (8,8) et ensuite vous pouvez utiliser des boucles doubles pour attribuer la couleur aux 8 lignes.

Exemple général pour toutes les tailles

from PIL import Image

size = 16
img = Image.new("RGB", (size,size), "white") # create a new 15x15 image
pixels = img.load() # create the pixel map

black_2 = []
for i in range(img.size[0]):
    if i % 2 == 0:
        black_2.append(i)

black_1 = [i-1 for i in black_2 if i > 0]
if img.size[0] % 2 == 0: # 'that' if statement
    black_1.append(img.size[0]-1)


for i in black_1:
    for j in range(0, size, 2):
        pixels[i,j] = (0,0,0)

for k in black_2:
    for l in range(1, size+1, 2):
        pixels[k,l] = (0,0,0)

img.show()

 entrez la description de l'image ici


2 commentaires

Cela fonctionne, mais n'y a-t-il aucun moyen de l'adapter à n'importe quelle taille?


Merci. Assurez-vous de changer pour l dans la plage (1, taille + 1, 2): en pour l dans la plage (1, taille, 2): pour que cela fonctionne



2
votes

C'est une manière simple. Au cas où cela vous confondrait, un pixel de l'image correspond à un carré entier de l'échiquier et vous pouvez l'agrandir à la fin si vous le souhaitez.

img = img.resize((15*w,15*h), Image.NEAREST)

Si vous le souhaitez une image plus grande, il suffit de redimensionner à la fin. Donc, disons que vous voulez que chaque carré du plateau soit 15px x 15px:

#!/usr/bin/env python3

from PIL import Image

# Create new black image of entire board
w, h = 12, 6
img = Image.new("RGB", (w,h))
pixels = img.load()

# Make pixels white where (row+col) is odd
for i in range(w):
    for j in range(h):
        if (i+j)%2:
            pixels[i,j] = (255,255,255)

img.save('result.png')

 Échiquier produit par le code

p>


1 commentaires

Solution élégante



1
votes

En utilisant le module numpy, c'est très rapide et vous n'avez que 11 boucles (pas non plus en boucle à travers chaque pixel, mais plutôt à travers des motifs). Peu importe la taille de l'échiquier. Le traitement doit être tout aussi rapide

timing: échiquier 2400 x 2400 pixels -> 0,17s

import numpy as np
from PIL import Image
n = 50 # size of one element, row = 8*n, chessboard = 8*n x 8*n

segment_black = np.zeros(shape = [n,n])
segment_white = np.ones(shape = [n,n])*255
chessboard = np.hstack((segment_black,segment_white))
for i in range(4):
    chessboard = np.hstack((chessboard,segment_black))
    chessboard = np.hstack((chessboard,segment_white))
temp = chessboard
for i in range(7):
    chessboard = np.concatenate((np.fliplr(chessboard),temp))
img = Image.fromarray(chessboard.astype(np.uint8))
img.save('chess.jpg')
img.show()


0 commentaires