个人兴趣,用python实现连连看的辅助程序,总结实现过程及知识点。
总体思路
1、获取连连看程序的窗口并前置
2、游戏界面截图,将每个一小图标切图,并形成由小图标组成的二维列表
3、对图片的二维列表遍历,将二维列表转换成由数字组成的二维数组,图片相同的数值相同。
4、遍历二维数组,找到可消除的对象,实现算法:
实现过程中遇到的问题
图片切割
im = image.crop((left,top,right,bottom)) //image.crop参数为一个列表或元组,顺序为(left,top,right,bottom)
找到游戏运行窗口
hdwd = win32gui.FindWindow(0,wdname) # 设置为最前显示 win32gui.SetForegroundWindow(hdwd)
窗口不要点击最小化,点击后无法弹出来。
img1 = im1.resize((20, 20), Image.ANTIALIAS).convert('L')
Image.ANTIALIAS 为抗锯齿的选项,图片无毛边。
pi1 = list(img1.getdata())
列表每个元素为一个三位数的值,分别代表该点的RGB值。列表pi1共400个元素。(因为图片为20*20)
PyMouse.click()该方法默认双击,改为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) hash1 = "".join(map(lambda p: "1" if p > avg1 else "0", pi1)) hash2 = "".join(map(lambda p: "1" if p > avg2 else "0", pi2)) match = 0 for i in range(len(hash1)): if hash1[i] != hash2[i]: match += 1 # match = sum(map(operator.ne, hash1, hash2)) # match 值越小,相似度越高 return match
from PIL import Image # 将图片转化为RGB def make_regalur_image(img, size=(8, 8)): gray_image = img.resize(size).convert('RGB') return gray_image # 计算直方图 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 # 计算相似度 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]之间,数值越大,相似度越高
from PIL import Image from numpy import average, dot, linalg # 对图片进行统一化处理 def get_thum(image, size=(64, 64), greyscale=False): # 利用image对图像大小重新设置, Image.ANTIALIAS为高质量的 image = image.resize(size, Image.ANTIALIAS) if greyscale: # 将图片转换为L模式,其为灰度图,其每个像素用8个bit表示 image = image.convert('L') return image # 计算图片的余弦距离 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(代数),norm则表示范数 # 求图片的范数?? norms.append(linalg.norm(vector, 2)) a, b = vectors a_norm, b_norm = norms # dot返回的是点积,对二维数组(矩阵)进行计算 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]之间,数值越大,相似度越高,计算量较大,效率较低
完整代码
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'宠物连连看经典版2,宠物连连看经典版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) # 设置为最前显示 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 # 判断两个图片是否相同。汉明距离,平均哈希 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) hash1 = "".join(map(lambda p: "1" if p > avg1 else "0", pi1)) hash2 = "".join(map(lambda p: "1" if p > avg2 else "0", pi2)) match = 0 for i in range(len(hash1)): if hash1[i] != hash2[i]: match += 1 # match = sum(map(operator.ne, hash1, hash2)) # match 值越小,相似度越高 return match # 将图片矩阵转换成数字矩阵 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): '''相同的图片中间图标全为空''' 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): '''两条线相连,转弯一次''' 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): '''三条线相连,转弯两次''' 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): #找到游戏运行窗口 self.find_game_wd(self.wdname) # 截图,切割成小图标 self.get_img() # 将图片矩阵转换成数字矩阵 array = self.create_array() print(array) # 遍历矩阵,找到可消除项,点击消除 for i in range(10): self.find_same_img(array) print(array) if __name__ == '__main__': ga = GameAuxiliaries() ga.run()
总结
该程序其实未能完全实现辅助功能,主要是因为图片切割时未找到更好的规则,造成图片识别困难,缩放比例和判断阀值未找到一个平衡点,阀值太大,则将不同的图标识别为相同,阀值太小,相同的图标又判断为不一样。
更多关于python游戏的精彩文章请点击查看以下专题:
python俄罗斯方块游戏集合
python经典小游戏汇总
python微信跳一跳游戏集合
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍python实现连连看辅助之图像识别延伸,包括了python实现连连看辅助之图像识别延伸的使用技巧和注意事项,需要的朋友参考一下 python实现连连看辅助–图像识别延伸(百度AI),供大家参考,具体内容如下 百度AI平台提供图片相似检索API接口,并有详细的API文档说明,可以更好的实现图片识别。 百度AI平台提供非常多的API接口,值得研究。 代码 以上就是本文的全部内容,希望对
本文向大家介绍python实现连连看游戏,包括了python实现连连看游戏的使用技巧和注意事项,需要的朋友参考一下 编程一直是在课余时间,放假时间自学,到现在为止也有半年了。 这是我自己用python实现的连连看,也是第一个完成的游戏,虽然极其简陋。 思路呢,一开始是想要从一个点出发开始寻路,遇到数字就换一条路,直到找到第二个点,但是这样就得做到不断寻路且不能和重复之前走过的路径,这就有点让我犯难
本文向大家介绍原生javascript实现连连看游戏,包括了原生javascript实现连连看游戏的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了js实现连连看游戏的具体代码,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍Android实现简单图库辅助器,包括了Android实现简单图库辅助器的使用技巧和注意事项,需要的朋友参考一下 写在前面 实际开发经常会遇到读取相册或者拍照功能,网上也很非常多图库框架,都各有风格,也因此与自己的项目格格不入。再者,框架API太多,需要的配置太多,还要吃力研究。所以,本人摸索大多图库框架,提炼核心,写一个只提供核心的辅助类,剩下的就可以自行玩耍。 实现步骤 第一步,
本文向大家介绍微信跳一跳python辅助软件思路及图像识别源码解析,包括了微信跳一跳python辅助软件思路及图像识别源码解析的使用技巧和注意事项,需要的朋友参考一下 本文将梳理github上最火的wechat_jump_game的实现思路,并解析其图像处理部分源码 首先废话少说先看效果 核心思想 获取棋子到下一个方块的中心点的距离 计算触摸屏幕的时间 点击屏幕 重要方法 计算棋子到下一个方块中心
本文向大家介绍java基于swing实现的连连看代码,包括了java基于swing实现的连连看代码的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了java基于swing实现连连看代码。分享给大家供大家参考。 主要功能代码如下: