2010-01-30 52 views
14

Estoy usando numpy para inicializar una matriz de píxeles en un tablero de damas gris (la representación clásica de "sin píxeles", o transparente). Parece que debe haber una manera whizzy hacerlo con la numpy asignación increíble variedad/rebanar/operaciones de corte en dados, pero esto es lo mejor que he llegado con:¿Cómo hacer un tablero de ajedrez en numpy?

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 para algo más simple.

Respuesta

2

¿No puedes usar hstack y vstack? Ver here. De esta manera:

>>> 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)) 
+0

no tengo ningún respeto aquí, pero esto es correcto. http://telliott99.blogspot.com/2010/01/heres-question-on-so-about-how-to-make.html – telliott99

+0

Esto no crea una matriz del tamaño correcto, aunque parece que expandió tu respuesta en tu publicación de blog. ¡Pero no podemos votar la publicación del blog! :) Sheesh! –

10

esto debería hacerlo

cualquier tablero de ajedrez tamaño que desee (sólo tiene que pasar en anchura y altura, como w, h); También he duro codificadas celular altura/anchura a 1, aunque por supuesto esto también podría ser parametrizado de manera que un valor arbitrario se pasa en:

>>> 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 para hacer que una imagen de una tablero de ajedrez, así:

>>> import matplotlib.pyplot as PLT 

>>> fig, ax = PLT.subplots() 
>>> ax.imshow(checkerboard, cmap=PLT.cm.gray, interpolation='nearest') 
>>> PLT.show() 
+0

Esto está cerca, aunque hay que tener cuidado con algunas cosas: quería que los cheques tuvieran más de 1 píxel de ancho (los tenía como 15), y no se puede asumir que los cheques se ajustarán uniformemente en el ancho y altura del tablero de damas deseado. –

+0

¡Agradable! ro puede escribirse simplemente como re^1.(solo XORing re con 1) –

+0

Esto funciona para el ancho/alto par e impar: 'import numpy' ' def checkerboard (w, h, a = 0, b = 1): ' ' row0 = numpy. r_ [int (w/2.0) * [a, b] + (w% 2) * [a]] ' ' row1 = row0^1' 'return numpy.row_stack (int (h/2.0) * (row0 , row1) + (h% 2) * (row0,)) ' –

3

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

ésta es otra manera de hacerlo utilizando 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)) 

Éstos son los resultados 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 
+0

¿Puedes adaptar esto para que funcione si mis colores de píxel no son de color gris puro? Supongamos que quiero que los dos colores sean (0xFF, 0x80, 0x00) y (0x80, 0xFF, 0x00) –

+0

Claro. Fue una mala elección de diseño por mi parte suponer que el color tenía que ser gris ... – unutbu

2

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] 
0

recientemente Quiero la misma función y modifiqué la respuesta de Doug un poco 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) 
0

I modified 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] 
+3

Lo ideal sería indicar qué ventaja tiene esta respuesta sobre otra, en lugar de solo decirnos que la ha modificado. –

5

que haría uso de la Kronecker productkron:

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 10x10 en cada dirección.

+0

¡Respuesta elegante y algebraica! Una posible mejora (como con la mayoría de las demás respuestas) sería usar la escala de grises original del OP para ilustrar la generalidad. – Tanaya

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


[[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]] 
Cuestiones relacionadas