import cv2 # OpenCV library
import numpy as np
import time
from PIL import Image # Pillow library will be used to open and crop images
from CompareImages import compare_images # This code compares and detects differences
# between images.
from mss import mss # will be used for grabbing screenshots
sct=mss()
import chess #used for chess baord visualization, move generation, and move validation.
from stockfish import Stockfish # The Stockfish chess engine will be used to evaluate
# a given position and identify the top moves.
stockfish = Stockfish(r"Enter Your Path Here//stockfish.exe")
第 2 步:确保正确捕获棋盘。
接下来,创建了一个函数来定位显示器上的棋盘。该函数接受三个输入:棋盘左上角的 X 和 Y 坐标以及棋盘上每个方格的宽度。
在显示器上,X 和 Y 坐标为像素(585、163),每个正方形的宽度为 90 像素(图 1)。你需要为你的显示器配置这些输入。
def capture_board(y_coords=163,x_coords=585, box_widths=90):
global y_coord, x_coord, box_width
y_coord, x_coord, box_width = y_coords, x_coords, box_widths
This functions grabs a screenshot of your monitor based on the specified parameters.
It then draws an 8x8 grid based on the specified box width parameter. Make sure that
each blue square aligns closely with the chessboard squares.
x_coord: This x coordinate is for the top left corner of the board. You will need to
modify it for your monitor.
y_coord: This y coordinate is for the top left corner of the board. You will need to
modify it for your monitor.
box_width: This is the width of each square on the chessboard. You may need to modify
it based on the size of your board.
with mss() as sct:
monitor = {"top": y_coord, "left": x_coord,
"width": (box_width)*8, "height": box_width*8}
while True:
screenshot = np.array(sct.grab(monitor))
for i in range(1,8):
# Draw 7 vericle blue lines with thickness of 3 px
cv2.line(screenshot,((box_width)*i,0),((box_width)*i,
y_coord+(box_width)*8),
(255,0,0),3)
# Draw 7 horizontal blue lines with thickness of 3 px
cv2.line(screenshot,(0,(box_width)*i),(x_coord+(box_width)*8,
(box_width)*i),
(255,0,0),3)
cv2.imshow('Chess Board', screenshot)
if cv2.waitKey(1) == ord('q'): # press any key to quit.
cv2.destroyAllWindows()
break
## Run the above function
capture_board(y_coords=163,x_coords=585, box_widths=90)
def flipped_board():
# Take a screenshot of the chessboard and save the image in local library.
take_screenshot('InitialBoard.png')
im = Image.open('InitialBoard.png')
# Crop the upper left-hand sqaure and process it.
im1 = im.crop((5, 5, 70, 70))
im1.save('CurrentRook.png')
image = cv2.imread('CurrentRook.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Assume the rook is white if the upper left-hand square has more than 300 white pixels.
# otherwise, the rook is black and the board is not flipped.
is_board_flipped=True if np.sum(gray==255)>300 else False
return is_board_flipped
is_board_flipped=flipped_board()
# is_board_flipped=True
# is_board_flipped=False
print('Is the board flipped?', is_board_flipped)
myList=[list(range(56,64)),
list(range(48,56)),
list(range(40,48)),
list(range(32,40)),
list(range(24,32)),
list(range(16,24)),
list(range(8,16)),
list(range(0,8))]
if is_board_flipped:
myList.reverse()
for i in range(8):
myList[i].reverse()
myList
# The pieces are arranged by the total number of black pixels. The black king has
# the fewest number of black pixels, and the black knight has the largest number
# of black pixels.
BPieces=['BlackKing','BlackBishop','BlackPawn','BlackRook','BlackQueen','BlackKnight']
BPieceType=[6,3,1,4,5,2]
# The pieces are arranged by the total number of white pixels. The white bishop has
# the smallest number of white pixels, and the white knight has the largest number
# of white pixels.
WPieces=['WhiteBishop','WhiteQueen','WhiteRook','WhitePawn','WhiteKing','WhiteKnight']
WPieceType=[3,5,4,1,6,2]
下面的 for 循环将从提供的棋盘图像中裁剪并保存 64 张图像。64 个图像中的每一个都将根据步骤 5 中指定的方向与特定的正方形对齐。确保在主目录中创建一个“Pieces”文件夹;裁剪后的图像将保存在此文件夹中。
BlackPixelList, WhitePixelList=[],[]
nn=0;
# Take a screenshot of the entire chessboard and save the image
take_screenshot('image1.png')
#Read the chessboard into memory
image = cv2.imread('image1.png')
# Convert the color image to a gray scale image and save it.
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite('gray image.png', gray)
im = Image.open('gray image.png')
# Crop each squre of the chess board and save the 64 gray scale images. Each image
# will align with a specific square on the chessboard.
for i in range(8):
for j in range(8):
im1=im.crop(
(j*(box_width),
i*(box_width),
(j+1)*(box_width-0),
(i+1)*(box_width-0)))
im1.save('pieces//'+str(nn)+'.png')
n=myList[i][j]
image = cv2.imread('pieces//'+str(nn)+'.png')
# count the number of black pixels per image
BlackPiece=np.sum(image==0)
BlackPixelList.append(BlackPiece)
# count the number of white pixels per image
WhitePiece=np.sum(image==255)
WhitePixelList.append(WhitePiece)
nn+=1
下面的代码旨在识别每个棋子的黑白像素数。我已经从上面创建了一个包含黑白像素数量的列表。
对于每种颜色,我执行以下操作:
保留唯一的像素值
以升序对列表进行排序,并保留六个最大的像素值
每个像素值将与BPieces / Wpieces中指定的部分对齐
# Filter out values equal 0 and keep unique pixel values
# sort the list in ascending order
# keep the six largest pixel values
BlackPixelList=set(list(filter(lambda x: x > 0, BlackPixelList)))
BlackPixelList=list(BlackPixelList)
BlackPixelList.sort()
BlackPixelList=BlackPixelList[-6:]
WhitePixelList=set(list(filter(lambda x: x > 0, WhitePixelList)))
WhitePixelList=list(WhitePixelList)
WhitePixelList.sort()
WhitePixelList=WhitePixelList[-6:]
# Create a dictionary for each color and assign
# pixel value to each chess piece, piece type,
# and piece color (False=Black, True=White).
BlackPieces={}
for i, val in enumerate(BPieces):
BlackPieces[val] = (BlackPixelList[i],BPieceType[i],False)
WhitePieces={}
for i, val in enumerate(WPieces):
WhitePieces[val] = (WhitePixelList[i],WPieceType[i],True)
stockfish.set_elo_rating(3000)
stockfish.set_depth(15)
def evaluate_position(white_turn=True, board_flipped=is_board_flipped):
start_time = time.time()
# take a screenshot of the board
take_screenshot('image1.png')
image = cv2.imread('image1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imwrite('gray image.png', gray)
im = Image.open('gray image.png')
# Set up the board from the Chess library
board = chess.Board()
# Remove all the pieces because they will be specified in the next step
board.clear()
# Set the turn to White to play, unless otherwise specified
board.turn = white_turn
nn=0;
for i in range(8):
for j in range(8):
im1=im.crop((j*(box_width), i*(box_width), (j+1)*(box_width-0), (i+1)*(box_width-0)))
im1.save('pieces//'+str(nn)+'.png')
n=myList[i][j]
# Read each cropped chess square and identify the chess piece and color.
image = cv2.imread('pieces//'+str(nn)+'.png')
BlackPiece=np.sum(image==0)
WhitePiece=np.sum(image==255)
res_val=(0,0,True)
if BlackPiece>min(BlackPixelValues)-50:
# Identify the chess piece based on he number of black pixels closest to the
# values from the BlackPieces dictionary.
col_key, res_val = min(BlackPieces.items(), key=lambda x: abs(BlackPiece - x[1][0]))
if WhitePiece>min(WhitePixelValues)-50:
# Identify the chess piece based on he number of white pixels closest to the
# values from the BlackPieces dictionary.
col_key, res_val = min(WhitePieces.items(), key=lambda x: abs(WhitePiece - x[1][0]))
# set the chess piece on the board based on it position, piece type, and color.
board.set_piece_at(n,piece=chess.Piece(piece_type=res_val[1],color=res_val[2]))
nn+=1
#create the FEN based on the current position
turn_fen=' w - - 1 0' if board.turn == True else ' b - - 0 1'
current_fen=board.board_fen()+turn_fen
# Assign the postion in Stockfish based on FEN
stockfish.set_fen_position(current_fen)
# Get the top moves
top_moves=stockfish.get_top_moves()
#Get the best move
my_move=top_moves[0]['Move']
# Move the chess piece based on the best move
board.push(chess.Move.from_uci(my_move))
#Create output
print('Time:',time.time()-start_time)
print('Best Move:', my_move)
print('Evaluation:', stockfish.get_evaluation())
print('Top moves:')
for i in top_moves:
print(i)
if board_flipped:
board.apply_transform(chess.flip_vertical)
board.apply_transform(chess.flip_horizontal)
display(board)
else:
display(board)