欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何使用Python在2秒內(nèi)評(píng)估國(guó)際象棋位置詳解

 更新時(shí)間:2022年05月19日 11:35:03   作者:woshicver  
關(guān)心編程語(yǔ)言的使用趨勢(shì)的人都知道,最近幾年,國(guó)內(nèi)最火的兩種語(yǔ)言非Python與Go莫屬,下面這篇文章主要給大家介紹了關(guān)于如何使用Python在2秒內(nèi)評(píng)估國(guó)際象棋位置的相關(guān)資料,需要的朋友可以參考下

前言

經(jīng)常在 https://lichess.org/ 上觀看大師們玩的國(guó)際象棋比賽。這些棋局和棋手的水平超出了我們的想象,如果想知道誰(shuí)有優(yōu)勢(shì)。與其事后分析游戲,不如實(shí)時(shí)分析它們。

下面的 Python 程序針對(duì) https://lichess.org/ 進(jìn)行了優(yōu)化。但是你可以為 https://www.chess.com/ 或任何國(guó)際象棋網(wǎng)站修改它。

它的工作原理是截取棋盤的屏幕截圖,檢測(cè)每個(gè)棋子在棋盤上的位置,使用 python Chess 庫(kù)繪制棋盤,然后使用 Stockfish 引擎為給定位置提供評(píng)估和最佳移動(dòng)。

第 1 步:導(dǎo)入所需的模塊

使用 OpenCV (開(kāi)源計(jì)算機(jī)視覺(jué)庫(kù))和 NumPy 庫(kù)來(lái)截取棋盤,可視化棋盤方格,并比較圖像之間的差異。

如果你不熟悉OpenCV,鼓勵(lì)你了解有關(guān)它的更多信息。接下來(lái),使用 PIL(Pillow)庫(kù)來(lái)修改圖像(例如,裁剪)。CompareImages 模塊使用 OpenCV 來(lái)查找并突出顯示兩個(gè)圖像之間的差異。

稍微修改 CodeDeepAI 的代碼,可以查看:https://codedeepai.com/finding-difference-between-multiple-images-using-opencv-and-python/,你可以從這個(gè) GitHub 頁(yè)面下載模塊:https://github.com/aaljaish/Lichess-Board-Evaluator

mss 庫(kù)是一種快速簡(jiǎn)便的方法來(lái)獲取監(jiān)視器的屏幕截圖并將圖像保存為 PNG 文件。接下來(lái),使用chess庫(kù),用于移動(dòng)生成、驗(yàn)證和可視化。

最后,使用stockfish 引擎來(lái)評(píng)估國(guó)際象棋的位置并確定最佳走法。你可以從他們的網(wǎng)站下載 Stockfish 引擎:https://stockfishchess.org/download/

在 Windows 中為這個(gè)項(xiàng)目使用 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")

第 2 步:確保正確捕獲棋盤。

接下來(lái),創(chuàng)建了一個(gè)函數(shù)來(lái)定位顯示器上的棋盤。該函數(shù)接受三個(gè)輸入:棋盤左上角的 X 和 Y 坐標(biāo)以及棋盤上每個(gè)方格的寬度。

在顯示器上,X 和 Y 坐標(biāo)為像素(585、163),每個(gè)正方形的寬度為 90 像素(圖 1)。你需要為你的顯示器配置這些輸入。

圖 1:lichess.org 上棋盤的方向。左上角位于我屏幕的像素 (585, 163) 處,棋盤內(nèi)的每個(gè)正方形都是 90 像素寬。

當(dāng)你運(yùn)行“capture_board”功能時(shí),它將打開(kāi)一個(gè)窗口,根據(jù)輸入?yún)?shù)顯示監(jiān)視器的實(shí)時(shí)視圖。它還將繪制一個(gè) 8x8 網(wǎng)格。確保藍(lán)色框與棋盤格緊密對(duì)齊(圖 2)。

左側(cè)的圖像可能會(huì)導(dǎo)致對(duì)棋位的評(píng)估不佳或根本不起作用。

相反,請(qǐng)確保藍(lán)線與棋盤格對(duì)齊以準(zhǔn)確捕獲棋子(右圖)。

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)

第 3 步:創(chuàng)建一個(gè)函數(shù),對(duì)棋盤進(jìn)行截圖并根據(jù)上面的輸入進(jìn)行裁剪。

在第三步中,創(chuàng)建了一個(gè)函數(shù),該函數(shù)根據(jù) capture_board 函數(shù)的輸入獲取棋盤位置的單個(gè)屏幕截圖。此屏幕截圖將保存在本地目錄中,并在接下來(lái)的步驟中進(jìn)行處理。

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)[]()

第 4 步(可選):確定棋盤是否翻轉(zhuǎn)。

下面的函數(shù)檢測(cè)棋盤是否翻轉(zhuǎn)。它通過(guò)檢測(cè)棋盤左上角的車(黑色或白色)來(lái)工作。如果游戲開(kāi)始并且車已經(jīng)從原來(lái)的位置移動(dòng),此函數(shù)可能無(wú)法正常工作。

你可以通過(guò)在棋盤翻轉(zhuǎn)時(shí)取消注釋“is_board_flipped=True”或在棋盤未翻轉(zhuǎn)時(shí)取消注釋“is_board_flipped=False”(即,棋盤底部為白色)來(lái)覆蓋此函數(shù)。

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)

第5步:棋盤的方向。

下面的數(shù)組將根據(jù)棋盤是否翻轉(zhuǎn)來(lái)排列。我在下一步中使用該數(shù)組來(lái)檢測(cè)棋盤上哪個(gè)方格上的棋子。如果棋盤沒(méi)有翻轉(zhuǎn),方塊 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

第6步:識(shí)別棋子。

這一步只運(yùn)行一次(假設(shè)棋盤的大小在游戲之間沒(méi)有變化)。確定每個(gè)棋子的像素?cái)?shù)后,你可以刪除此部分。

想找到一種簡(jiǎn)單、高效且一致的方法來(lái)檢測(cè)和識(shí)別棋子。計(jì)算每個(gè)棋格上的黑/白像素?cái)?shù)效果很好。

下面的代碼集按照構(gòu)成每個(gè)塊的黑白像素的數(shù)量來(lái)排列黑白塊;請(qǐng)注意,我手動(dòng)執(zhí)行了此步驟,但你的順序應(yīng)該相同。你會(huì)注意到黑色國(guó)王擁有最少的黑色像素,而黑色騎士擁有最多的黑色像素。白象的白色像素?cái)?shù)最少,而白騎士的白色像素?cái)?shù)最多。BPieceType和WPieceType與 Chess 庫(kù)分配的棋子類型一致。

你可以在Python Chess 文檔中閱讀更多相關(guān)信息:

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 循環(huán)將從提供的棋盤圖像中裁剪并保存 64 張圖像。64 個(gè)圖像中的每一個(gè)都將根據(jù)步驟 5 中指定的方向與特定的正方形對(duì)齊。確保在主目錄中創(chuàng)建一個(gè)“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

下面的代碼旨在識(shí)別每個(gè)棋子的黑白像素?cái)?shù)。我已經(jīng)從上面創(chuàng)建了一個(gè)包含黑白像素?cái)?shù)量的列表。

對(duì)于每種顏色,我執(zhí)行以下操作:

  • 保留唯一的像素值
  • 以升序?qū)α斜磉M(jìn)行排序,并保留六個(gè)最大的像素值
  • 每個(gè)像素值將與BPieces / Wpieces中指定的部分對(duì)齊
# 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)

第 7 步:為每個(gè)棋子分配像素?cái)?shù)。

如果這是第一次運(yùn)行代碼,請(qǐng)使用步驟 6 輸出為“BlackPieces”分配黑色像素?cái)?shù),為“WhitePieces”分配白色像素?cái)?shù)。下面的代碼以我的顯示器為例。

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())]

第 8 步:設(shè)置評(píng)估棋盤的函數(shù)。

我們已經(jīng)完成了所有的設(shè)置步驟。我們首先將 stockfish 的等級(jí)設(shè)置為 3000 ELO,并將深度設(shè)置為 15。你可以將深度設(shè)置為 26,但這會(huì)顯著增加處理時(shí)間。然后我們創(chuàng)建“evaluate_position”函數(shù)。該函數(shù)將:

  • 截屏
  • 將彩色圖像轉(zhuǎn)換為灰度并保存圖像
  • 確定每個(gè)棋子在棋盤上的位置,并使用國(guó)際象棋庫(kù)將這些棋子放置在棋盤上的適當(dāng)位置
  • 將該回合分配給指定的顏色。默認(rèn)是輪到白棋。
  • 根據(jù)國(guó)際象棋庫(kù)中的位置分配 stockfish 中的 FEN 位置
  • 生成請(qǐng)求的輸出
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)

第 9 步:運(yùn)行棋盤評(píng)估。

恭喜,你完成了!指定是輪到白(設(shè)置 white_turn=True)還是輪到黑(white_turn=False)并運(yùn)行評(píng)估函數(shù)。該函數(shù)將輸出:

  • Time:運(yùn)行函數(shù)所花費(fèi)的時(shí)間
  • Best Move:最明智的一步
  • Evaluation:對(duì)當(dāng)前位置的評(píng)估
  • Top moves:最佳移動(dòng)
  • 當(dāng)前位置和下一個(gè)最佳移動(dòng)的視覺(jué)效果

如果位置發(fā)生變化,重新運(yùn)行evaluate_postition函數(shù);你不需要重新運(yùn)行前面的步驟。

evaluate_position(white_turn=True)

c3174bee22b059f06cdfe383404b1969.png

evaluate_position 輸出示例。

結(jié)論

你可以運(yùn)行上述代碼來(lái)捕獲和評(píng)估在 https://lichess.org/ 上的任何國(guó)際象棋位置。此外,你可以輕松地為任何在線棋盤修改代碼:https://github.com/aaljaish/Lichess-Board-Evaluator

到此這篇關(guān)于如何使用Python在2秒內(nèi)評(píng)估國(guó)際象棋位置的文章就介紹到這了,更多相關(guān)Python評(píng)估國(guó)際象棋位置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Flask wtforms實(shí)現(xiàn)表單驗(yàn)證使用

    Flask wtforms實(shí)現(xiàn)表單驗(yàn)證使用

    本文主要介紹了Flask wtforms實(shí)現(xiàn)表單驗(yàn)證使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Python數(shù)據(jù)分析numpy數(shù)組的3種創(chuàng)建方式

    Python數(shù)據(jù)分析numpy數(shù)組的3種創(chuàng)建方式

    這篇文章主要介紹了Python數(shù)據(jù)分析numpy數(shù)組的3種創(chuàng)建方式,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • Python異常?ValueError的問(wèn)題

    Python異常?ValueError的問(wèn)題

    這篇文章主要介紹了Python異常?ValueError的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • python reduce 函數(shù)使用詳解

    python reduce 函數(shù)使用詳解

    reduce()函數(shù)也是Python內(nèi)置的一個(gè)高階函數(shù)。reduce()函數(shù)接收的參數(shù)和 map()類似,一個(gè)函數(shù) f,一個(gè)list,但行為和 map()不同,今天我們就來(lái)詳細(xì)探討下
    2017-12-12
  • 利用Python實(shí)時(shí)獲取steam特惠游戲數(shù)據(jù)

    利用Python實(shí)時(shí)獲取steam特惠游戲數(shù)據(jù)

    Steam是由美國(guó)電子游戲商Valve于2003年9月12日推出的數(shù)字發(fā)行平臺(tái),被認(rèn)為是計(jì)算機(jī)游戲界最大的數(shù)碼發(fā)行平臺(tái)之一。本文將利用Python實(shí)時(shí)獲取steam特惠游戲數(shù)據(jù),感興趣的可以嘗試一下
    2022-06-06
  • Python實(shí)現(xiàn)股市信息下載的方法

    Python實(shí)現(xiàn)股市信息下載的方法

    這篇文章主要介紹了Python實(shí)現(xiàn)股市信息下載的方法,涉及Python使用urllib模塊進(jìn)行URL及文件的相關(guān)操作技巧,需要的朋友可以參考下
    2015-06-06
  • 使用Python的networkx繪制精美網(wǎng)絡(luò)圖教程

    使用Python的networkx繪制精美網(wǎng)絡(luò)圖教程

    今天小編就為大家分享一篇使用Python的networkx繪制精美網(wǎng)絡(luò)圖教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-11-11
  • python實(shí)現(xiàn)多進(jìn)程通信實(shí)例分析

    python實(shí)現(xiàn)多進(jìn)程通信實(shí)例分析

    這篇文章主要介紹了python實(shí)現(xiàn)多進(jìn)程通信實(shí)例分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 使用pandas 將DataFrame轉(zhuǎn)化成dict

    使用pandas 將DataFrame轉(zhuǎn)化成dict

    今天小編就為大家分享一篇使用pandas 將DataFrame轉(zhuǎn)化成dict,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-12-12
  • Python編程快速上手——PDF文件操作案例分析

    Python編程快速上手——PDF文件操作案例分析

    這篇文章主要介紹了Python 文件操作,結(jié)合具體實(shí)例形式分析了Python針對(duì)pdf文件的遍歷、讀寫、加密、解密等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2020-02-02

最新評(píng)論