<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
經常在 https://lichess.org/ 上觀看大師們玩的國際象棋比賽。這些棋局和棋手的水平超出了我們的想象,如果想知道誰有優勢。與其事後分析遊戲,不如實時分析它們。
下面的 Python 程式針對 https://lichess.org/ 進行了優化。但是你可以為 https://www.chess.com/ 或任何國際象棋網站修改它。
它的工作原理是擷取棋盤的螢幕截圖,檢測每個棋子在棋盤上的位置,使用 python Chess 庫繪製棋盤,然後使用 Stockfish 引擎為給定位置提供評估和最佳移動。
使用 OpenCV (開源計算機視覺庫)和 NumPy 庫來擷取棋盤,視覺化棋盤方格,並比較影象之間的差異。
如果你不熟悉OpenCV,鼓勵你瞭解有關它的更多資訊。接下來,使用 PIL(Pillow)庫來修改影象(例如,裁剪)。CompareImages 模組使用 OpenCV 來查詢並突出顯示兩個影象之間的差異。
稍微修改 CodeDeepAI 的程式碼,可以檢視:https://codedeepai.com/finding-difference-between-multiple-images-using-opencv-and-python/,你可以從這個 GitHub 頁面下載模組:https://github.com/aaljaish/Lichess-Board-Evaluator
mss 庫是一種快速簡便的方法來獲取監視器的螢幕截圖並將影象儲存為 PNG 檔案。接下來,使用chess庫,用於移動生成、驗證和視覺化。
最後,使用stockfish 引擎來評估國際象棋的位置並確定最佳走法。你可以從他們的網站下載 Stockfish 引擎:https://stockfishchess.org/download/
在 Windows 中為這個專案使用 Stockfish 14.1 (AVX2)。
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")
接下來,建立了一個函數來定位顯示器上的棋盤。該函數接受三個輸入:棋盤左上角的 X 和 Y 座標以及棋盤上每個方格的寬度。
在顯示器上,X 和 Y 座標為畫素(585、163),每個正方形的寬度為 90 畫素(圖 1)。你需要為你的顯示器設定這些輸入。
圖 1:lichess.org 上棋盤的方向。左上角位於我螢幕的畫素 (585, 163) 處,棋盤內的每個正方形都是 90 畫素寬。
當你執行“capture_board”功能時,它將開啟一個視窗,根據輸入引數顯示監視器的實時檢視。它還將繪製一個 8x8 網格。確保藍色框與棋盤格緊密對齊(圖 2)。
左側的影象可能會導致對棋位的評估不佳或根本不起作用。
相反,請確保藍線與棋盤格對齊以準確捕獲棋子(右圖)。
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)
在第三步中,建立了一個函數,該函數根據 capture_board 函數的輸入獲取棋盤位置的單個螢幕截圖。此螢幕截圖將儲存在本地目錄中,並在接下來的步驟中進行處理。
def take_screenshot(filename): ## Screen shot and then crop image filename1 = sct.shot(output=filename) im = Image.open(filename1) # (left, upper, right , lower ) im1 = im.crop(( x_coord , y_coord, x_coord+box_width*8, y_coord+box_width*8)) # Saves image in local directory im1.save(filename1)[]()
下面的函數檢測棋盤是否翻轉。它通過檢測棋盤左上角的車(黑色或白色)來工作。如果遊戲開始並且車已經從原來的位置移動,此函數可能無法正常工作。
你可以通過在棋盤翻轉時取消註釋“is_board_flipped=True”或在棋盤未翻轉時取消註釋“is_board_flipped=False”(即,棋盤底部為白色)來覆蓋此函數。
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)
下面的陣列將根據棋盤是否翻轉來排列。我在下一步中使用該陣列來檢測棋盤上哪個方格上的棋子。如果棋盤沒有翻轉,方塊 A1 將在左下角;否則,A1 方塊將位於右上角。
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
這一步只執行一次(假設棋盤的大小在遊戲之間沒有變化)。確定每個棋子的畫素數後,你可以刪除此部分。
想找到一種簡單、高效且一致的方法來檢測和識別棋子。計算每個棋格上的黑/白畫素數效果很好。
下面的程式碼集按照構成每個塊的黑白畫素的數量來排列黑白塊;請注意,我手動執行了此步驟,但你的順序應該相同。你會注意到黑色國王擁有最少的黑色畫素,而黑色騎士擁有最多的黑色畫素。白象的白色畫素數最少,而白騎士的白色畫素數最多。BPieceType和WPieceType與 Chess 庫分配的棋子型別一致。
你可以在Python Chess 檔案中閱讀更多相關資訊:
https://python-chess.readthedocs.io/en/latest/core.html
棋子型別
Pawn = 1
Knight = 2
Bisphop = 3
Rook = 4
Queen = 5
King = 6
# 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; n=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+=1 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
下面的程式碼旨在識別每個棋子的黑白畫素數。我已經從上面建立了一個包含黑白畫素數量的列表。
對於每種顏色,我執行以下操作:
# 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)
如果這是第一次執行程式碼,請使用步驟 6 輸出為“BlackPieces”分配黑色畫素數,為“WhitePieces”分配白色畫素數。下面的程式碼以我的顯示器為例。
BlackPieces= {'BlackKing': (5028, 6, False), 'BlackBishop': (5052, 3, False), 'BlackPawn': (5679, 1, False), 'BlackRook': (6489, 4, False), 'BlackQueen': (6495, 5, False), 'BlackKnight': (7623, 2, False)} WhitePieces= {'WhiteBishop': (2520, 3, True), 'WhiteQueen': (3039, 5, True), 'WhiteRook': (3741, 4, True), 'WhitePawn': (3933, 1, True), 'WhiteKing': (4410, 6, True), 'WhiteKnight': (6057, 2, True)} BlackPixelValues=[i[0] for i in list(BlackPieces.values())] WhitePixelValues=[i[0] for i in list(WhitePieces.values())]
我們已經完成了所有的設定步驟。我們首先將 stockfish 的等級設定為 3000 ELO,並將深度設定為 15。你可以將深度設定為 26,但這會顯著增加處理時間。然後我們建立“evaluate_position”函數。該函數將:
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; n=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+=1 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)
恭喜,你完成了!指定是輪到白(設定 white_turn=True)還是輪到黑(white_turn=False)並執行評估函數。該函數將輸出:
如果位置發生變化,重新執行evaluate_postition函數;你不需要重新執行前面的步驟。
evaluate_position(white_turn=True)
evaluate_position 輸出範例。
你可以執行上述程式碼來捕獲和評估在 https://lichess.org/ 上的任何國際象棋位置。此外,你可以輕鬆地為任何線上棋盤修改程式碼:https://github.com/aaljaish/Lichess-Board-Evaluator
到此這篇關於如何使用Python在2秒內評估國際象棋位置的文章就介紹到這了,更多相關Python評估國際象棋位置內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45