个人兴趣,用python实现连连看的辅助程序,总结实现过程及知识点。
总体思路
1、获取连连看程序的窗口并前置
2、游戏界面截图,将每个一小图标切图,并形成由小图标组成的二维列表
3、对图片的二维列表遍历,将二维列表转换成由数字组成的二维数组,图片相同的数值相同。
4、遍历二维数组,找到可消除的对象,实现算法:
- 两个图标相邻。(一条线连接)
- 两个图标同行,同列,且中间的图标全部为空(数值为0)(一条线连接)
- 两条线连接,转弯一次,路径上所有图标为空。(二条线连接)
- 三条线连接,转弯二次,路径上所有图标为空。(三条线连接)
- 分别点击两个图标,并将对应的二维数据值置为0
实现过程中遇到的问题
图片切割
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 为抗锯齿的选项,图片无毛边。
- 获取图片每个点的RGB值
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)):<b style="color:transparent">本文来源gao@!dai!ma.com搞$$代^@码网*</b> 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]之间,数值越大,相似度越高,计算量较大,效率较低