在PIL中创建棋盘

时间:2019-01-28 22:09:01

标签: python python-imaging-library

背景

我一直在尝试在PIL模块中创建一个棋盘,我已经获得了前两行的常规模式,但是无法弄清楚如何将其应用于整个棋盘。如您所见,我创建了一个图像:

from PIL import Image

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

我对前两行的解决方案

注意-我仍在学习Python,因此此代码似乎效率很低,但是可以随时提出改进建议。

第二行:

代码:

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

这给了我所有放置黑色像素的水平索引位置。因此,对于我创建的15x15电路板,它返回[0, 2, 4, 6, 8, 10, 12, 14]

第一行:

代码:

然后我使用第二行计算出第一行的水平索引位置

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)

对于我创建的15x15像素板,它返回[1, 3, 5, 7, 9, 11, 13]。我创建了if语句,因为我意识到如果木板长度均匀,最后一个黑色像素不会显示,那似乎可以解决问题。

将像素更改为黑色:

# 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()

无论大小如何,如何将这两种图案都应用于电路板的其余部分?

我怀疑需要一个for var in range()循环,但是我不确定它会如何变化,具体取决于木板的高度(img.size[1])是奇数还是偶数。

到目前为止的总体模式:

Chessboard

black_1适用于第一行

black_2应用于第二行

4 个答案:

答案 0 :(得分:3)

国际象棋棋盘有64个正方形而不是256个正方形。首先,您需要(8,8),然后可以使用double for循环将颜色分配给所有8行。

任何大小的常规示例

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()

enter image description here

答案 1 :(得分:1)

这是一种简单的方法。万一它使您感到困惑,图像中的一个像素对应于棋盘的整个正方形,如果需要,您可以在最后放大它。

#!/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')

如果您希望将其放大,则只需在最后调整大小即可。因此,假设您希望电路板的每个正方形为15px x 15px:

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

enter image description here

答案 2 :(得分:1)

解决方案:

使用numpy模数,它非常快,您只有11个循环(也不循环遍历每个像素,而是遍历模式)。棋盘有多大都没关系。处理应该相似得很快

定时: 2400 x 2400像素棋盘-> 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()

答案 3 :(得分:0)

您可以使用PIL.Image.paste在其自身上粘贴img

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

使用所有现有代码,只需将其添加在底部即可。