用python玩微信跳一跳系列-棋子定位之像素遍歷

前言
在前幾篇博客中,分別就棋子的顏色識別、模板匹配等定位方式進行了介紹和實踐,這一篇博客就來驗證一下github中最熱門的跳一跳外掛中採用的像素遍歷的方法。
方法說明
像素遍歷的實質依然是顏色識別。
在github中給出的方法中,採用像素遍歷的方法是:

  1. 從高度的1/3處開始至高度的2/3處進行遍歷;
  2. 首先間隔50像素進行搜索
  3. 當像素的顏色和每一行開始的像素顏色不同時,認爲找到了最上面的棋盤位置,則返回上一個間隔處開始遍歷(i-50);
  4. 對每一行的像素都進行遍歷,當滿足給定的顏色範圍時,記錄最下面一行的y值,x值的和與個數,平均即可得到中心x值。
  5. 所得到的x值和y值即爲棋子最底部的中心位置;
  6. 按照自己手機的分辨率調整棋子的高度(減去一個固定值)

    上訴方法的代碼如下(可以自行到github下載):

def find_piece_and_board(im):
    #尋找關鍵座標
    w, h = im.size

    piece_x_sum = 0
    piece_x_c = 0
    piece_y_max = 0
    board_x = 0
    board_y = 0
    scan_x_border = int(w / 8)  # 掃描棋子時的左右邊界
    scan_start_y = 0  # 掃描的起始 y 座標
    im_pixel = im.load()
    # 以 50px 步長,嘗試探測 scan_start_y
    for i in range(int(h / 3), int(h*2 / 3), 50):
        last_pixel = im_pixel[0, i]
        for j in range(1, w):
            pixel = im_pixel[j, i]
            # 不是純色的線,則記錄 scan_start_y 的值,準備跳出循環
            if pixel != last_pixel:
                scan_start_y = i - 50
                break
        if scan_start_y:
            break
    print('scan_start_y: {}'.format(scan_start_y))

    # 從 scan_start_y 開始往下掃描,棋子應位於屏幕上半部分,這裏暫定不超過 2/3
    for i in range(scan_start_y, int(h * 2 / 3)):
        # 橫座標方面也減少了一部分掃描開銷
        for j in range(scan_x_border, w - scan_x_border):
            pixel = im_pixel[j, i]
            # 根據棋子的最低行的顏色判斷,找最後一行那些點的平均值,這個顏
            # 色這樣應該 OK,暫時不提出來
            if (50 < pixel[0] < 60) \
                    and (53 < pixel[1] < 63) \
                    and (95 < pixel[2] < 110):
                piece_x_sum += j
                piece_x_c += 1
                piece_y_max = max(i, piece_y_max)

    if not all((piece_x_sum, piece_x_c)):
        return 0, 0, 0, 0
    piece_x = int(piece_x_sum / piece_x_c)
    piece_y = piece_y_max - piece_base_height_1_2  # 上移棋子底盤高度的一半

遍歷過程動態演示
這裏寫圖片描述

實際運行動畫
以下是實際運行的定位動畫。
這裏寫圖片描述

優缺點分析
像素遍歷的好處是無需額外的python庫,但其速度顯然明顯低於我在前面用過的其它方法,這不奇怪,外接庫用到的顏色識別方法其實是經過優化和集成的,像素遍歷是其底層的技術方案,速度慢理所當然。

改進
其實上述方法還可以進一步優化,以大大減小遍歷的面積:

  1. 以50像素爲間隔從1/3高度開始遍歷;
  2. 當首次滿足給定的棋子顏色時,記錄x值的和與個數,平均後得到棋子的x值;
  3. 沿x值從上向下對高度進行遍歷,可以得到滿足棋子顏色的最大y值和最小y值;
  4. 對y值進行處理,如減去一個固定高度,即可得到棋子的底部中心y值;
  5. 對最高點和最低點進行平均,即可得到棋盤的中心y值。

    遍歷的過程如下:
    這裏寫圖片描述

後記
可以看到,優化後的遍歷個數大大減小,速度得到極大提高。

發佈了68 篇原創文章 · 獲贊 60 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章