chess / chessfenbot /helper_functions.py
rosenthal's picture
v1 of chess space
e936283
raw
history blame
No virus
6.23 kB
import numpy as np
# Imports for visualization
import PIL.Image
# DEBUG for ipython notebook visualizations.
# from IPython.display import clear_output, Image, display
# def display_array(a, fmt='jpeg', rng=[0,1]):
# """Display an array as a picture."""
# a = (a - rng[0])/float(rng[1] - rng[0]) # normalized float value
# a = np.uint8(np.clip(a*255, 0, 255))
# f = StringIO()
# PIL.Image.fromarray(np.asarray(a, dtype=np.uint8)).save(f, fmt)
# display(Image(data=f.getvalue()))
# def display_weight(a, fmt='jpeg', rng=[0,1]):
# """Display an array as a color picture."""
# a = (a - rng[0])/float(rng[1] - rng[0]) # normalized float value
# a = np.uint8(np.clip(a*255, 0, 255))
# f = StringIO()
# v = np.asarray(a, dtype=np.uint8)
# # blue is high intensity, red is low
# # Negative
# r = 255-v.copy()
# r[r<127] = 0
# r[r>=127] = 255
# # None
# g = np.zeros_like(v)
# # Positive
# b = v.copy()
# b[b<127] = 0
# b[b>=127] = 255
# #np.clip((v-127)/2,0,127)*2
# #-1 to 1
# intensity = np.abs(2.*a-1)
# rgb = np.uint8(np.dstack([r,g,b]*intensity))
# PIL.Image.fromarray(rgb).save(f, fmt)
# display(Image(data=f.getvalue(), width=100))
# def display_image(a, fmt='png'):
# """Display an image as a picture in-line."""
# f = StringIO()
# PIL.Image.fromarray(np.asarray(a, dtype=np.uint8)).save(f, fmt)
# display(Image(data=f.getvalue()))
# FEN related
def getFENtileLabel(fen,letter,number):
"""Given a fen string and a rank (number) and file (letter), return label vector"""
l2i = lambda l: ord(l)-ord('A') # letter to index
number = 8-number # FEN has order backwards
piece_letter = fen[number*8+number + l2i(letter)]
label = np.zeros(13, dtype=np.uint8)
label['1KQRBNPkqrbnp'.find(piece_letter)] = 1 # note the 1 instead of ' ' due to FEN notation
# We ignore shorter FENs with numbers > 1 because we generate the FENs ourselves
return label
# We'll define the 12 pieces and 1 spacewith single characters
# KQRBNPkqrbnp
def getLabelForSquare(letter,number):
"""Given letter and number (say 'B3'), return one-hot label vector
(12 pieces + 1 space == no piece, so 13-long vector)"""
l2i = lambda l: ord(l)-ord('A') # letter to index
piece2Label = lambda piece: ' KQRBNPkqrbnp'.find(piece)
# build mapping to index
# Starter position
starter_mapping = np.zeros([8,8], dtype=np.uint8)
starter_mapping[0, [l2i('A'), l2i('H')]] = piece2Label('R')
starter_mapping[0, [l2i('B'), l2i('G')]] = piece2Label('N')
starter_mapping[0, [l2i('C'), l2i('F')]] = piece2Label('B')
starter_mapping[0, l2i('D')] = piece2Label('Q')
starter_mapping[0, l2i('E')] = piece2Label('K')
starter_mapping[1, :] = piece2Label('P')
starter_mapping[7, [l2i('A'), l2i('H')]] = piece2Label('r')
starter_mapping[7, [l2i('B'), l2i('G')]] = piece2Label('n')
starter_mapping[7, [l2i('C'), l2i('F')]] = piece2Label('b')
starter_mapping[7, l2i('D')] = piece2Label('q')
starter_mapping[7, l2i('E')] = piece2Label('k')
starter_mapping[6, :] = piece2Label('p')
# Note: if we display the array, the first row is white,
# normally bottom, but arrays show it as top
# Generate one-hot label
label = np.zeros(13, dtype=np.uint8)
label[starter_mapping[number-1, l2i(letter), ]] = 1
return label
def name2Label(name):
"""Convert label vector into name of piece"""
return ' KQRBNPkqrbnp'.find(name)
def labelIndex2Name(label_index):
"""Convert label index into name of piece"""
return ' KQRBNPkqrbnp'[label_index]
def label2Name(label):
"""Convert label vector into name of piece"""
return labelIndex2Name(label.argmax())
def shortenFEN(fen):
"""Reduce FEN to shortest form (ex. '111p11Q' becomes '3p2Q')"""
return fen.replace('11111111','8').replace('1111111','7') \
.replace('111111','6').replace('11111','5') \
.replace('1111','4').replace('111','3').replace('11','2')
def lengthenFEN(fen):
"""Lengthen FEN to 71-character form (ex. '3p2Q' becomes '111p11Q')"""
return fen.replace('8','11111111').replace('7','1111111') \
.replace('6','111111').replace('5','11111') \
.replace('4','1111').replace('3','111').replace('2','11')
def unflipFEN(fen):
if len(fen) < 71:
fen = lengthenFEN(FEN)
return '/'.join([ r[::-1] for r in fen.split('/') ][::-1])
# For Training in IPython Notebooks
def loadFENtiles(image_filepaths):
"""Load Tiles with FEN string in filename for labels.
return both images and labels"""
# Each tile is a 32x32 grayscale image, add extra axis for working with MNIST Data format
images = np.zeros([image_filepaths.size, 32, 32, 1], dtype=np.uint8)
labels = np.zeros([image_filepaths.size, 13], dtype=np.float64)
for i, image_filepath in enumerate(image_filepaths):
if i % 1000 == 0:
#print("On #%d/%d : %s" % (i,image_filepaths.size, image_filepath))
print(".",)
# Image
images[i,:,:,0] = np.asarray(PIL.Image.open(image_filepath), dtype=np.uint8)
# Label
fen = image_filepath[-78:-7]
_rank = image_filepath[-6]
_file = int(image_filepath[-5])
labels[i,:] = getFENtileLabel(fen, _rank, _file)
print("Done")
return images, labels
def loadLabels(image_filepaths):
"""Load label vectors from list of image filepaths"""
# Each filepath contains which square we're looking at,
# since we're in starter position, we know which
# square has which piece, 12 distinct pieces
# (6 white and 6 black) and 1 as empty = 13 labels
training_data = np.zeros([image_filepaths.size, 13], dtype=np.float64)
for i, image_filepath in enumerate(image_filepaths):
training_data[i,:] = getLabelForSquare(image_filepath[-6],int(image_filepath[-5]))
return training_data
def loadImages(image_filepaths):
# Each tile is a 32x32 grayscale image, add extra axis for working with MNIST Data format
training_data = np.zeros([image_filepaths.size, 32, 32, 1], dtype=np.uint8)
for i, image_filepath in enumerate(image_filepaths):
if i % 100 == 0:
print("On #%d/%d : %s" % (i,image_filepaths.size, image_filepath))
img = PIL.Image.open(image_filepath)
training_data[i,:,:,0] = np.asarray(img, dtype=np.uint8)
return training_data