您好,登錄后才能下訂單哦!
這篇文章主要介紹了python如何實(shí)現(xiàn)連連看圖像識(shí)別輔助程序,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
總體思路
1、獲取連連看程序的窗口并前置
2、游戲界面截圖,將每個(gè)一小圖標(biāo)切圖,并形成由小圖標(biāo)組成的二維列表
3、對(duì)圖片的二維列表遍歷,將二維列表轉(zhuǎn)換成由數(shù)字組成的二維數(shù)組,圖片相同的數(shù)值相同。
4、遍歷二維數(shù)組,找到可消除的對(duì)象,實(shí)現(xiàn)算法:
兩個(gè)圖標(biāo)相鄰。(一條線連接)
兩個(gè)圖標(biāo)同行,同列,且中間的圖標(biāo)全部為空(數(shù)值為0)(一條線連接)
兩條線連接,轉(zhuǎn)彎一次,路徑上所有圖標(biāo)為空。(二條線連接)
三條線連接,轉(zhuǎn)彎二次,路徑上所有圖標(biāo)為空。(三條線連接)
分別點(diǎn)擊兩個(gè)圖標(biāo),并將對(duì)應(yīng)的二維數(shù)據(jù)值置為0
實(shí)現(xiàn)過(guò)程中遇到的問(wèn)題
圖片切割
im = image.crop((left,top,right,bottom)) //image.crop參數(shù)為一個(gè)列表或元組,順序?yàn)?left,top,right,bottom)
找到游戲運(yùn)行窗口
hdwd = win32gui.FindWindow(0,wdname) # 設(shè)置為最前顯示 win32gui.SetForegroundWindow(hdwd)
窗口不要點(diǎn)擊最小化,點(diǎn)擊后無(wú)法彈出來(lái)。
圖片縮放并轉(zhuǎn)為灰度
img1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L')
Image.ANTIALIAS 為抗鋸齒的選項(xiàng),圖片無(wú)毛邊。
獲取圖片每個(gè)點(diǎn)的RGB值
pi1 = list(img1.getdata())
列表每個(gè)元素為一個(gè)三位數(shù)的值,分別代表該點(diǎn)的RGB值。列表pi1共400個(gè)元素。(因?yàn)閳D片為20*20)
鼠標(biāo)點(diǎn)擊消除
PyMouse.click()該方法默認(rèn)雙擊,改為PyMouse.press() 或 PyMouse.release()
判斷圖片相似
漢明距離,平均哈希
def compare_img(self,im1,im2): img1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L') img2 = im2.resize((20, 20), Image.ANTIALIAS).convert('L') pi1 = list(img1.getdata()) pi2 = list(img2.getdata()) avg1 = sum(pi1) / len(pi1) avg2 = sum(pi2) / len(pi2) hash2 = "".join(map(lambda p: "1" if p > avg1 else "0", pi1)) hash3 = "".join(map(lambda p: "1" if p > avg2 else "0", pi2)) match = 0 for i in range(len(hash2)): if hash2[i] != hash3[i]: match += 1 # match = sum(map(operator.ne, hash2, hash3)) # match 值越小,相似度越高 return match
計(jì)算直方圖
from PIL import Image # 將圖片轉(zhuǎn)化為RGB def make_regalur_image(img, size=(8, 8)): gray_image = img.resize(size).convert('RGB') return gray_image # 計(jì)算直方圖 def hist_similar(lh, rh): assert len(lh) == len(rh) hist = sum(1 - (0 if l == r else float(abs(l - r)) / max(l, r)) for l, r in zip(lh, rh)) / len(lh) return hist # 計(jì)算相似度 def calc_similar(li, ri): calc_sim = hist_similar(li.histogram(), ri.histogram()) return calc_sim if __name__ == '__main__': image1 = Image.open('1-10.jpg') image1 = make_regalur_image(image1) image2 = Image.open('2-11.jpg') image2 = make_regalur_image(image2) print("圖片間的相似度為", calc_similar(image1, image2)) # 值在[0,1]之間,數(shù)值越大,相似度越高
圖片余弦相似度
from PIL import Image from numpy import average, dot, linalg # 對(duì)圖片進(jìn)行統(tǒng)一化處理 def get_thum(image, size=(64, 64), greyscale=False): # 利用image對(duì)圖像大小重新設(shè)置, Image.ANTIALIAS為高質(zhì)量的 image = image.resize(size, Image.ANTIALIAS) if greyscale: # 將圖片轉(zhuǎn)換為L(zhǎng)模式,其為灰度圖,其每個(gè)像素用8個(gè)bit表示 image = image.convert('L') return image # 計(jì)算圖片的余弦距離 def image_similarity_vectors_via_numpy(image1, image2): image1 = get_thum(image1) image2 = get_thum(image2) images = [image1, image2] vectors = [] norms = [] for image in images: vector = [] for pixel_tuple in image.getdata(): vector.append(average(pixel_tuple)) vectors.append(vector) # linalg=linear(線性)+algebra(代數(shù)),norm則表示范數(shù) # 求圖片的范數(shù)?? norms.append(linalg.norm(vector, 2)) a, b = vectors a_norm, b_norm = norms # dot返回的是點(diǎn)積,對(duì)二維數(shù)組(矩陣)進(jìn)行計(jì)算 res = dot(a / a_norm, b / b_norm) return res if __name__ == '__main__': image1 = Image.open('1-9.jpg') image2 = Image.open('8-6.jpg') cosin = image_similarity_vectors_via_numpy(image1, image2) print('圖片余弦相似度', cosin) # 值在[0,1]之間,數(shù)值越大,相似度越高,計(jì)算量較大,效率較低
完整代碼
import win32gui import time from PIL import ImageGrab , Image import numpy as np from pymouse import PyMouse class GameAuxiliaries(object): def __init__(self): self.wdname = r'寵物連連看經(jīng)典版2,寵物連連看經(jīng)典版2小游戲,4399小游戲 www.4399.com - Google Chrome' # self.wdname = r'main.swf - PotPlayer' self.image_list = {} self.m = PyMouse() def find_game_wd(self,wdname): # 取得窗口句柄 hdwd = win32gui.FindWindow(0,wdname) # 設(shè)置為最前顯示 win32gui.SetForegroundWindow(hdwd) time.sleep(1) def get_img(self): image = ImageGrab.grab((417, 289, 884, 600)) # image = ImageGrab.grab((417, 257, 885, 569)) image.save('1.jpg','JPEG') for x in range(1,9): self.image_list[x] = {} for y in range(1,13): top = (x - 1) * 38 + (x-2) left =(y - 1) * 38 +(y-2) right = y * 38 + (y-1) bottom = x * 38 +(x -1) if top < 0: top = 0 if left < 0 : left = 0 im_temp = image.crop((left,top,right,bottom)) im = im_temp.crop((1,1,37,37)) im.save('{}-{}.jpg'.format(x,y)) self.image_list[x][y]=im # 判斷兩個(gè)圖片是否相同。漢明距離,平均哈希 def compare_img(self,im1,im2): img1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L') img2 = im2.resize((20, 20), Image.ANTIALIAS).convert('L') pi1 = list(img1.getdata()) pi2 = list(img2.getdata()) avg1 = sum(pi1) / len(pi1) avg2 = sum(pi2) / len(pi2) hash2 = "".join(map(lambda p: "1" if p > avg1 else "0", pi1)) hash3 = "".join(map(lambda p: "1" if p > avg2 else "0", pi2)) match = 0 for i in range(len(hash2)): if hash2[i] != hash3[i]: match += 1 # match = sum(map(operator.ne, hash2, hash3)) # match 值越小,相似度越高 return match # 將圖片矩陣轉(zhuǎn)換成數(shù)字矩陣 def create_array(self): array = np.zeros((10,14),dtype=np.int32) img_type_list = [] for row in range(1,len(self.image_list)+1): for col in range(1,len(self.image_list[1])+1): # im = Image.open('{}-{}.jpg'.format(row,col)) im = self.image_list[row][col] for img in img_type_list: match = self.compare_img(im,img) # match = test2.image_similarity_vectors_via_numpy(im,img) if match <15: array[row][col] = img_type_list.index(img) +1 break else: img_type_list.append(im) array[row][col] = len(img_type_list) return array def row_zero(self,x1,y1,x2,y2,array): '''相同的圖片中間圖標(biāo)全為空''' if x1 == x2: min_y = min(y1,y2) max_y = max(y1,y2) if max_y - min_y == 1: return True for y in range(min_y+1,max_y): if array[x1][y] != 0 : return False return True else: return False def col_zero(self,x1,y1,x2,y2,array): '''相同的圖片同列''' if y1 == y2: min_x = min(x1,x2) max_x = max(x1,x2) if max_x - min_x == 1: return True for x in range(min_x+1,max_x): if array[x][y1] != 0 : return False return True else: return False def two_line(self,x1,y1,x2,y2,array): '''兩條線相連,轉(zhuǎn)彎一次''' for row in range(1,9): for col in range(1,13): if row == x1 and col == y2 and array[row][col]==0 and self.row_zero(x1,y1,row,col,array) and self.col_zero(x2,y2,row,col,array): return True if row == x2 and col == y1 and array[row][col]==0 and self.row_zero(x2,y2,row,col,array) and self.col_zero(x1,y1,row,col,array): return True return False def three_line(self,x1,y1,x2,y2,array): '''三條線相連,轉(zhuǎn)彎兩次''' for row1 in range(10): for col1 in range(14): for row2 in range(10): for col2 in range(14): if array[row1][col1] == array[row2][col2] == 0 and self.row_zero(x1,y1,row1,col1,array) and self.row_zero(x2,y2,row2,col2,array) and self.col_zero(row1,col1,row2,col2,array): return True if array[row1][col1] == array[row2][col2] == 0 and self.col_zero(x1,y1,row1,col1,array) and self.col_zero(x2,y2,row2,col2,array) and self.row_zero(row1,col1,row2,col2,array): return True if array[row1][col1] == array[row2][col2] == 0 and self.row_zero(x2,y2,row1,col1,array) and self.row_zero(x1,y1,row2,col2,array) and self.col_zero(row1,col1,row2,col2,array): return True if array[row1][col1] == array[row2][col2] == 0 and self.col_zero(x2,y2,row1,col1,array) and self.col_zero(x1,y1,row2,col2,array) and self.row_zero(row1,col1,row2,col2,array): return True return False def mouse_click(self,x,y): top = (x - 1) * 38 + (x - 2) left = (y - 1) * 38 + (y - 2) right = y * 38 + (y - 1) bottom = x * 38 + (x - 1) if top < 0: top = 0 if left < 0: left = 0 self.m.press(int(417+(left+right)/2) ,int(289+(top+bottom)/2) ) def find_same_img(self,array): for x1 in range(1,9): for y1 in range(1,13): if array[x1][y1] == 0: continue for x2 in range(1,9): for y2 in range(1,13): if x1==x2 and y1 == y2: continue if array[x2][y2] == 0 : continue if array[x1][y1] != array[x2][y2] : continue if array[x1][y1] ==array[x2][y2] and (self.row_zero(x1,y1,x2,y2,array) or self.col_zero(x1,y1,x2,y2,array) or self.two_line(x1,y1,x2,y2,array) or self.three_line(x1,y1,x2,y2,array)): print("可消除!x{}y{} 和 x{}y{}".format(x1,y1,x2,y2)) self.mouse_click(x1,y1) time.sleep(0.1) self.mouse_click(x2,y2) time.sleep(0.1) array[x1][y1]=array[x2][y2]=0 def run(self): #找到游戲運(yùn)行窗口 self.find_game_wd(self.wdname) # 截圖,切割成小圖標(biāo) self.get_img() # 將圖片矩陣轉(zhuǎn)換成數(shù)字矩陣 array = self.create_array() print(array) # 遍歷矩陣,找到可消除項(xiàng),點(diǎn)擊消除 for i in range(10): self.find_same_img(array) print(array) if __name__ == '__main__': ga = GameAuxiliaries() ga.run()
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“python如何實(shí)現(xiàn)連連看圖像識(shí)別輔助程序”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。