def _identify_piece_color(Im, classification, s1_is_black): # -1 : black # 1 : white # 0 : not a piece board = zeros((8,8)) pieces = zip(*nonzero(classification == 1)) for piece in pieces: W = find_board.get_patch(Im, piece) # compute the sample kurtosis k = stats.kurtosis(W[:,:,0].flatten()) if mod(sum(piece),2) == 0 and s1_is_black: square_color = -1 else: square_color = 1 if square_color == -1: if k < 1: board[piece] = 1 else: board[piece] = -1 if square_color == 1: if k < -.9: board[piece] = -1 else: board[piece] = 1 return board
def _identify_occupied_squares(Im, w, perspective = [1,1,1,1]): # 1 : is a piece # -1 : not a piece squares = [(i,j) for i in range(8) for j in range(8)] classification = zeros((8,8)) for (i,j) in squares: # extract the patch W = find_board.get_patch(Im, (i,j)) # make some features f = array(_make_features(W, perspective=perspective))[newaxis,:] # classify the patch classification[i,j] = w.predict(f).flatten() return classification
def train_detector(frames, piece_locations, board_corners, p=20): """ Given a list of frames and known piece locations, trains a piece detector. Required arguments: frames -- a python list of numpy arrays, where each array is a color image piece_locations -- a python list of lists of tuples describing the position of pieces on the board. The tuple (i,j) describes that there is a piece in the ith row, jth column, where the 0th row/column is the square whose upper left corner is first in board_corners. For a frame where the pieces are in the default starting locations, this is just: [[(i,j) for in range(8) for j in range(8)]] board_corners -- a list of board_corners as generated by find_board Keyword arguments: p -- An exponential factor which describes how much the board's perspective should be taken into account when classifying squares as pieces/non-pieces. Default: 20 Return value: train_detector returns a sklearn object describing a trained linear SVM. """ # shape an array for features and a list for classes features = zeros((0,N_FEATURES)) classes = [] # compute the perspective descriptors a1 = sqrt(sum((array(board_corners[0]) - array(board_corners[8]))**2)) a2 = sqrt(sum((array(board_corners[72]) - array(board_corners[80]))**2)) b1 = sqrt(sum((array(board_corners[8]) - array(board_corners[80]))**2)) b2 = sqrt(sum((array(board_corners[0]) - array(board_corners[72]))**2)) perspective = (b1/b2)**p, 1, (b1/b2)**p * (a1/a2)**p, (a1/a2)**p # for every frame, get the image patches, compute features, and add to the training data for k,f in enumerate(frames): squares = [(i,j) for i in range(8) for j in range(8)] for (i,j) in squares: f_warp = find_board.align_image(f, board_corners)[0] # get the patch W = find_board.get_patch(f_warp, (i,j)) # now compute some features current_features = _make_features(W,perspective) # add to training data features = vstack((features, current_features)) # determine the class of this patch and add to training data if (i,j) in piece_locations[k]: classes.append(1) else: classes.append(-1) # now we have our features and classes, and so we train up a linear least squares model w = svm.SVC() w.fit(features, classes) return w