¿Cómo hacer un tablero de ajedrez en numpy?

Estoy usando numpy para inicializar una matriz de píxeles en un tablero de ajedrez gris (la representación clásica de “sin píxeles” o transparente). Parece que debería haber una manera extraña de hacerlo con las increíbles operaciones de asignación / corte / corte en cuadritos de Numpy, pero esto es lo mejor que he encontrado:

w, h = 600, 800 sq = 15 # width of each checker-square self.pix = numpy.zeros((w, h, 3), dtype=numpy.uint8) # Make a checkerboard row = [[(0x99,0x99,0x99),(0xAA,0xAA,0xAA)][(i//sq)%2] for i in range(w)] self.pix[[i for i in range(h) if (i//sq)%2 == 0]] = row row = [[(0xAA,0xAA,0xAA),(0x99,0x99,0x99)][(i//sq)%2] for i in range(w)] self.pix[[i for i in range(h) if (i//sq)%2 == 1]] = row 

Funciona, pero esperaba algo más simple.

esto debería hacerlo

cualquier tablero de ajedrez del tamaño que desee (solo pase ancho y alto, como w, h); También tengo la altura / anchura de la celda codificada de forma rígida a 1, aunque, por supuesto, esto también podría parametrizarse para que se pase un valor arbitrario:

 >>> import numpy as NP >>> def build_checkerboard(w, h) : re = NP.r_[ w*[0,1] ] # even-numbered rows ro = NP.r_[ w*[1,0] ] # odd-numbered rows return NP.row_stack(h*(re, ro)) >>> checkerboard = build_checkerboard(5, 5) >>> checkerboard Out[3]: array([[0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]]) 

Con esta matriz 2D, es simple renderizar una imagen de un tablero de ajedrez, así:

 >>> import matplotlib.pyplot as PLT >>> fig, ax = PLT.subplots() >>> ax.imshow(checkerboard, cmap=PLT.cm.gray, interpolation='nearest') >>> PLT.show() 

Yo usaría el producto Kronecker kron :

 np.kron([[1, 0] * 4, [0, 1] * 4] * 4, np.ones((10, 10))) 

El tablero de ajedrez en este ejemplo tiene 2 * 4 = 8 campos de tamaño 10×10 en cada dirección.

Aquí hay otra forma de hacerlo usando ogrid que es un poco más rápido:

 import numpy as np import Image w, h = 600, 800 sq = 15 color1 = (0xFF, 0x80, 0x00) color2 = (0x80, 0xFF, 0x00) def use_ogrid(): coords = np.ogrid[0:w, 0:h] idx = (coords[0] // sq + coords[1] // sq) % 2 vals = np.array([color1, color2], dtype=np.uint8) img = vals[idx] return img def use_fromfunction(): img = np.zeros((w, h, 3), dtype=np.uint8) c = np.fromfunction(lambda x, y: ((x // sq) + (y // sq)) % 2, (w, h)) img[c == 0] = color1 img[c == 1] = color2 return img if __name__ == '__main__': for f in (use_ogrid, use_fromfunction): img = f() pilImage = Image.fromarray(img, 'RGB') pilImage.save('{0}.png'.format(f.func_name)) 

Aquí están los resultados de timeit:

 % python -mtimeit -s"import test" "test.use_fromfunction()" 10 loops, best of 3: 307 msec per loop % python -mtimeit -s"import test" "test.use_ogrid()" 10 loops, best of 3: 129 msec per loop 

No estoy seguro de si esto es mejor que lo que tenía:

 c = numpy.fromfunction(lambda x,y: ((x//sq) + (y//sq)) % 2, (w,h)) self.chex = numpy.array((w,h,3)) self.chex[c == 0] = (0xAA, 0xAA, 0xAA) self.chex[c == 1] = (0x99, 0x99, 0x99) 

Tarde, pero para la posteridad:

 def check(w, h, c0, c1, blocksize): tile = np.array([[c0,c1],[c1,c0]]).repeat(blocksize, axis=0).repeat(blocksize, axis=1) grid = np.tile(tile, ( h/(2*blocksize)+1, w/(2*blocksize)+1, 1)) return grid[:h,:w] 

¿No puedes usar hstack y vstack? Ver aqui Me gusta esto:

 >>> import numpy as np >>> b = np.array([0]*4) >>> b.shape = (2,2) >>> w = b + 0xAA >>> r1 = np.hstack((b,w,b,w,b,w,b)) >>> r2 = np.hstack((w,b,w,b,w,b,w)) >>> board = np.vstack((r1,r2,r1,r2,r1,r2,r1)) 
 def checkerboard(shape): return np.indices(shape).sum(axis=0) % 2 

Más compacta, probablemente la más rápida, y también la única solución publicada que generaliza a n-dimensiones.

 import numpy as np a=np.array(([1,0]*4+[0,1]*4)*4).reshape((8,8)) print(a) [[1 0 1 0 1 0 1 0] [0 1 0 1 0 1 0 1] [1 0 1 0 1 0 1 0] [0 1 0 1 0 1 0 1] [1 0 1 0 1 0 1 0] [0 1 0 1 0 1 0 1] [1 0 1 0 1 0 1 0] [0 1 0 1 0 1 0 1]] 
 import numpy as np x = np.ones((3,3)) print("Checkerboard pattern:") x = np.zeros((8,8),dtype=int) # (odd_rows, even_columns) x[1::2,::2] = 1 # (even_rows, odd_columns) x[::2,1::2] = 1 print(x) 

He modificado la respuesta de hass de la siguiente manera.

 import math import numpy as np def checkerboard(w, h, c0, c1, blocksize): tile = np.array([[c0,c1],[c1,c0]]).repeat(blocksize, axis=0).repeat(blocksize, axis=1) grid = np.tile(tile,(int(math.ceil((h+0.0)/(2*blocksize))),int(math.ceil((w+0.0)/(2*blocksize))))) return grid[:h,:w] 

Hace poco quiero la misma función y modifiqué la respuesta de doug de la siguiente manera:

 def gen_checkerboard(grid_num, grid_size): row_even = grid_num/2 * [0,1] row_odd = grid_num/2 * [1,0] checkerboard = numpy.row_stack(grid_num/2*(row_even, row_odd)) return checkerboard.repeat(grid_size, axis = 0).repeat(grid_size, axis = 1) 

La implementación más sencilla de la misma.

 import numpy as np n = int(input()) checkerboard = np.tile(np.array([[0,1],[1,0]]), (n//2, n//2)) print(checkerboard) 
 n = int(input()) import numpy as np m=int(n/2) a=np.array(([0,1]*m+[1,0]*m)*m).reshape((n,n)) print (a) 

Entonces, si la entrada es n = 4, entonces la salida sería como:

 [[0 1 0 1] [1 0 1 0] [0 1 0 1] [1 0 1 0]]