python實現自動找茬遊戲,python實現找茬

來源:互聯網
上載者:User

python實現自動找茬遊戲,python實現找茬

http://blog.csdn.net/pipisorry/article/details/46564967

找茬遊戲地址[美女大家來找茬]

遊戲視窗探查

下載安裝PyWin32庫(對windows介面的Python封裝)http://sourceforge.net/projects/pywin32/,但不能直接點Download表徵圖,不然下下來是一個Readme.txt,點“Browse All Files”尋找需要的版本。

使用spy++找到視窗控制代碼(或者找到視窗類別名lpClassName和視窗名lpWindowName)[python指定視窗-spy++用法]

hwnd = win32gui.FindWindow("MozillaWindowClass", "遊戲全屏 - Mozilla Firefox")if not hwnd:    print(RED, 'window not found!', DEFAULT)else:    print(hwnd)# hwnd = 918912  #或者直接使用控制代碼
Note:

1. FindWindow函數:

FindWindow這個函數檢索處理最上層視窗的類名和視窗名稱匹配指定的字串。這個函數不搜尋子視窗。

函數功能:該函數獲得一個頂層視窗的控制代碼,該視窗的類名和視窗名與給定的字串相匹配。這個函數不尋找子視窗。在尋找時不區分大小寫。
函數型:HWND FindWindow(LPCTSTR IpClassName,LPCTSTR IpWindowName);
參數:
    IpClassName :指向一個指定了類名的空結束字串,或一個標識類名字串的成員的指標。如果該參數為一個成員,則它必須為前次調用theGlobafAddAtom函數產生的全域成員。該成員為16位,必須位於IpClassName的低16位,高位必須為0。
    IpWindowName:指向一個指定了視窗名(視窗標題)的空結束字串。如果該參數為空白,則為所有視窗全匹配。
    返回值:如果函數成功,返回值為具有指定類名和視窗名的視窗控制代碼;如果函數失敗,返回值為NULL。

[FindWindow用法]

[findwindow-baike.baidu]

2. 控制代碼

直接使用控制代碼可能的問題:

1)firefox中每個頁面tab都是同一個控制代碼,程式中找到的控制代碼對應當前tab,如果當前tab不是找茬遊戲就不對了

2)使用視窗類別名lpClassName和視窗名lpWindowName時如果當前tab不是找茬遊戲會找不到相應控制代碼

上面問題一個有效解決方案是將找茬遊戲單獨在新視窗中開啟

也可以使用spy++反向從控制代碼找到控制代碼對應視窗,檢查是否正確。


遊戲圖片提取

提取圖片採用了截屏的方式,找到視窗後將視窗提到最前,再作視窗截屏。

下載安裝PIL圖形處理庫[linux和windows下安裝python拓展包-...PIL、pythonqt...]

win32gui.ShowWindow(hwnd, win32con.SW_MAXIMIZE)  # 強行顯示介面後才好,SW_RESTORE初始大小win32gui.SetForegroundWindow(hwnd)  # 將視窗提到最前# 裁剪得到全圖game_rect = win32gui.GetWindowRect(hwnd)# src_image = ImageGrab.grab(game_rect)src_image = ImageGrab.grab((game_rect[0] + 20, game_rect[1] + 176, game_rect[2] - 523, game_rect[1] + 176 + 514))# src_image.show()width, hight = src_image.size# 分別裁剪左右內容圖片left_box = (0, 0, width // 2 + 1, hight)right_box = (width // 2 + 1, 0, width, hight)image_left = src_image.crop(left_box)image_right = src_image.crop(right_box)# image_left.show()# image_right.show()
Note:

1.win32gui.GetWindowRect函數

l,t,r,b =win32gui.GetWindowRect(self.hwnd)    #返回圖形左、上、右、下邊界

2.ImageGrab.grab函數:ImageGrab是PIL的一個模組,用於映像的抓取。不帶參數的ImageGrab.grab()進行全屏截屏,返回一個Image對象,也可使用一個元組作為參數指定要截取的範圍(左上與右下兩點的座標),這兩種截屏都是不帶滑鼠指標的。

上面用到的座標都為為了示範代碼簡單填的,實際上可使用了變數參數,而且要區分解析度什麼的。參數也可以為圖形要截取的左、上、右、下邊界

還有一個ImageGrab.grabclipboard()可從系統剪貼簿採集映像。

3. 得到Image映像後可用show()方法,使用系統預設的映像查看工具開啟,方便調試。

也可以用save(filename)儲存成檔案,對應的可以Image.open(filename)開啟獲得。

4. crop(box)方法:參數為左上和右下標點座標

grab得到了一個包含左右圖片的Image對象後,用crop(box)方法可裁剪得到其中指定的地區,分別拿到左右兩個遊戲圖片。


對比獲得兩圖內容不同的地區

把兩圖裁剪成N個小圖片分別對比,左右統一地區對應的小圖片不相等則為“茬”區,問題是怎麼判斷兩個圖片內容不一致?

Image.histogram()函數:用於得到映像的顏色長條圖。長條圖可以表示一張圖片中各種亮度(或顏色)的數量,兩張自然圖片的長條圖基本是不一樣的,除非兩圖對稱、顏色一致但排列不一,但就算如此,將兩圖繼續分割下去,其子圖的長條圖也會不一樣。長條圖就是一種圖形到數值的轉換,對比兩圖的顏色數值就可知是否存在差異。一張用RBG顏色格式的映像,histogram()函數將返回一個長度為768的數組,第0-255表示紅色的0-255,第256-511表色綠色的0-255,第512-767表色藍色的0-255,數值表示該顏色像素的個數。因此,histogram()列表所有成員之和等於改映像的像素值 x 3。

用來獲得兩圖比較的數值差的函數

def channel_compare(cha_a, cha_b):    '''    比較兩個色彩通道的差異值並返回    '''    sum_a = sum([i * v for i, v in enumerate(cha_a)])    sum_b = sum([i * v for i, v in enumerate(cha_b)])    # red_a = 0    # red_b = 0    # for i in range(0, 256):    # red_a += histogram_a[i + 0] * i    # red_b += histogram_b[i + 0] * i    if sum_a + sum_b > 0:        diff_channel = abs(sum_a - sum_b) * 10000 / max(sum_a, sum_b)    return diff_channeldef image_compare(image_a, image_b):    '''    返回兩圖的差異值, 返回兩圖紅綠藍差值萬分比之和    '''    histogram_a = image_a.histogram()    histogram_b = image_b.histogram()    if len(histogram_a) != 768 or len(histogram_b) != 768:        print(RED, "get histogram error", DEFAULT)        return None    print([i * v for i, v in enumerate(histogram_a)][0:10])    diff_red = channel_compare(histogram_a[:256], histogram_b[:256])    diff_green = channel_compare(histogram_a[256:512], histogram_b[256:512])    diff_blue = channel_compare(histogram_a[512:768], histogram_b[512:768])    return diff_red, diff_green, diff_blue
Note:將函數返回的紅綠藍差值相加,如果超過了預定定的閥值2000,則表示該地區不同。這個計算方式有點“土”,但對這次要解決的問題很有效,就沒再繼續改進。

把兩圖裁剪成N個小圖片分別對比

# 將左右大圖裁剪成多個小圖分別進行對比result = zeros((width // 10, hight // 10))for col in range(0, width // 10):    for row in range(0, hight // 10):        clip_box = (col * 10, row * 10, (col + 1) * 10, (row + 1) * 10)        clip_image_left = image_left.crop(clip_box)        clip_image_right = image_right.crop(clip_box)        clip_diff = image_compare(clip_image_left, clip_image_right)        if sum(clip_diff) > 2000:            result[row][col] = 1
Note:大圖是780*520,分隔成10x10的小塊,定義一個78*52的二位元組儲存結果,分別比較後將差值大於閥值的數組地區標記為1.


在遊戲上標記兩邊不同的地區

可以使用PyWin32的函數,獲得遊戲視窗控制代碼後直接在上面繪製,但要熟悉Windows編程,解決遊戲自身重繪後將我的標記擦除的問題。

也可以使用Qt。下面用Qt建立了一個和遊戲大小一樣透明的QWidget視窗,疊加在遊戲視窗上,用遮罩來繪製標記。標記資料已記錄在result數組中,在指定的位置繪製一個方格則表示該地區左右不同,要注意兩個方格間的邊界不要繪製,避免格子太多幹擾了遊戲。除標記外,還繪製了兩個按鈕來觸發對比與擦除。


這裡我沒有替換變數,太麻煩了,能看清楚演算法就行。



from:http://blog.csdn.net/pipisorry/article/details/46564967

ref:PIL Document


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.