先放制作好的游戏视频链接:(纯粹是兴趣分享)

连连看不一样的玩法-图像相似度识别-python_单机游戏热门视频

https://www.ixigua.com/7076826558106698253?logTag=f2d215ea6e6372c45362

这两个视频是我本人自制投稿,感兴趣可以观看一下。下面是截图展示:

程序主要功能是先将练练看的整个大图切分成单个小图,然后进行循环遍历找出相似的图片,并在矩阵中进行记录,然后依据练练看两个图片连接的规则进行连接。直接放代码:

1.相似度计算模块(用一个算法就行了,我这里写了好几个)

import cv2
import numpy as np
import matplotlib
matplotlib.use('TkAgg')# 均值哈希算法
def aHash(img):# 缩放为8*8# img = cv2.imread(img)img = np.asanyarray(img)img = cv2.resize(img, (8, 8))# 转换为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# s为像素和初值为0,hash_str为hash值初值为''s = 0hash_str = ''# 遍历累加求像素和for i in range(8):for j in range(8):s = s+gray[i, j]# 求平均灰度avg = s/64# 灰度大于平均值为1相反为0生成图片的hash值for i in range(8):for j in range(8):if gray[i, j] > avg:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_str# 差值哈希算法
def dHash(img):# 缩放8*8# img = cv2.imread(img) #此种方法只能用于本地图片读取img = np.asanyarray(img)img = cv2.resize(img, (9, 8))# 转换灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)hash_str = ''# 每行前一个像素大于后一个像素为1,相反为0,生成哈希for i in range(8):for j in range(8):if gray[i, j] > gray[i, j+1]:hash_str = hash_str+'1'else:hash_str = hash_str+'0'return hash_str# 感知哈希算法
def pHash(img):# 缩放32*32# img = cv2.imread(img)img = np.asanyarray(img)img = cv2.resize(img, (32, 32))  # , interpolation=cv2.INTER_CUBIC# 转换为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 将灰度图转为浮点型,再进行dct变换dct = cv2.dct(np.float32(gray))# opencv实现的掩码操作dct_roi = dct[0:8, 0:8]hash = []avreage = np.mean(dct_roi)for i in range(dct_roi.shape[0]):for j in range(dct_roi.shape[1]):if dct_roi[i, j] > avreage:hash.append(1)else:hash.append(0)return hash# 灰度直方图算法
def calculate(image1, image2):# 计算单通道的直方图的相似值# 均值、差值、感知哈希算法三种算法值越小,则越相似,相同图片值为0# 三直方图算法和单通道的直方图 0-1之间,值越大,越相似。 相同图片为1# image1 = cv2.imread(image1)# image2 = cv2.imread(image2)image1 = np.asanyarray(image1)image2 = np.asanyarray(image2)hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])# 计算直方图的重合度degree = 0for i in range(len(hist1)):if hist1[i] != hist2[i]:degree = degree + \(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))else:degree = degree + 1degree = degree / len(hist1)return degree# 三通道直方图算法
def classify_calculate(image1, image2):# 计算单通道的直方图的相似值# 均值、差值、感知哈希算法三种算法值越小,则越相似,相同图片值为0# 三直方图算法和单通道的直方图 0-1之间,值越大,越相似。 相同图片为1hist1 = cv2.calcHist([image1], [0], None, [256], [0.0, 255.0])hist2 = cv2.calcHist([image2], [0], None, [256], [0.0, 255.0])# 计算直方图的重合度degree = 0for i in range(len(hist1)):if hist1[i] != hist2[i]:degree = degree + \(1 - abs(hist1[i] - hist2[i]) / max(hist1[i], hist2[i]))else:degree = degree + 1degree = degree / len(hist1)return degree# RGB每个通道的直方图相似度
def classify_hist_with_split(image1, image2, size=(256, 256)):# 将图像resize后,分离为RGB三个通道,再计算每个通道的相似值image1 = np.asanyarray(image1)image2 = np.asanyarray(image2)image1 = cv2.resize(image1, size)image2 = cv2.resize(image2, size)sub_image1 = cv2.split(image1)sub_image2 = cv2.split(image2)sub_data = 0for im1, im2 in zip(sub_image1, sub_image2):sub_data += classify_calculate(im1, im2)sub_data = sub_data / 3return sub_data# Hash值对比
def cmpHash(hash1, hash2):# 均值、差值、感知哈希算法三种算法值越小,则越相似,相同图片值为0# 三直方图算法和单通道的直方图 0-1之间,值越大,越相似。 相同图片为1# 算法中1和0顺序组合起来的即是图片的指纹hash。顺序不固定,但是比较的时候必须是相同的顺序。# 对比两幅图的指纹,计算汉明距离,即两个64位的hash值有多少是不一样的,不同的位数越小,图片越相似# 汉明距离:一组二进制数据变成另一组数据所需要的步骤,可以衡量两图的差异,汉明距离越小,则相似度越高。汉明距离为0,即两张图片完全一样n = 0# hash长度不同则返回-1代表传参出错if len(hash1) != len(hash2):return -1# 遍历判断for i in range(len(hash1)):# 不相等则n计数+1,n最终为相似度if hash1[i] != hash2[i]:n = n + 1return n

2.基本功能(截图,图片转换)

from PIL import ImageGrab
import numpy as np#截图方法
#传入图片像素位置以及所需比例宽度高度 #引入自己写的模块
from LLKgame.similarFunctinos import cmpHash, pHash, classify_hist_with_split, calculate#传入截图的左上右下坐标,宽的小图数量,长的小图数量,小图的高度和宽度
#如cutPicture(304, 271, 1226, 870,10,14,60.2,65.9)在坐标(304,271)(1226,870)处截取140个小图,小图的高是60.2,宽是65.9def cutPicture(left,top,right,botton,pWidth,pHeight,height,width):  # 截图size = (left, top, right, botton)img = ImageGrab.grab(size)# img.size(200,100)print(img.size)print(img)# img.save("D://cut.jpg")# img.show()# 2、分切小图image_list = {}for x in range(pWidth):image_list[x] = {}for y in range(pHeight):# print("show",x, y)# exit()top1 = x * heightleft1 = y * widthright1 = (y + 1) * widthbotton1 = (x + 1) * height# 用crop函数切割成小图标,参数为图标的左上角和右下角左边im = img.crop((left1, top1, right1, botton1))# im.show()# time.sleep(1)# 将切割好的图标存入对应的位置image_list[x][y] = imprint(image_list)return image_list#创造数字矩阵
#传入矩阵的宽高和初始矩阵
def makeArray(pWidth,pHeight,image_list):image_type_list = []arr = np.zeros((pWidth + 2,pHeight + 2), dtype=np.int32)  # 创建矩阵以数字代替图片for i in range(len(image_list)):for j in range(len(image_list[0])):im = image_list[i][j]# 验证当前图标是否已存入index = getIndex(10,0.65,im, image_type_list)# 不存在image_type_listif index < 0:image_type_list.append(im)arr[i + 1][j + 1] = len(image_type_list)else:arr[i + 1][j + 1] = index + 1print("图标数:", len(image_type_list))# self.im2num_arr = arrreturn arr# 检查数组中是否有图标,如果有则返回索引下表
#传入标准相似度similar1 similar2 和需要验证图片
def getIndex(similar1,similar2,im, im_list):global flagfor i in range(len(im_list)):flag = 0# if self.compare_image_with_hash(im, im_list[i],6):#     return ival1 = calculate(im,im_list[i])val2 = classify_hist_with_split(im,im_list[i])val3 = cmpHash(pHash(im), pHash(im_list[i]))if val2 >= similar2:flag = 1if val1 >= similar2:flag = flag + 1if val3 <= similar1:flag = flag + 1if flag >= 2:return ireturn -1

3.连连看连接逻辑

import time
from pymouse import *from LLKgame.baseFunctions import cutPicture, makeArrayclass run_game():#初始截图左上右下坐标位置,初始截图总宽总高,初始单个图像宽高def __init__(self,left,top,right,botton,pWidth,pHeight,height,width):self.left = leftself.top = topself.right = rightself.botton = bottonself.pWidth = pWidthself.pHeight = pHeightself.width = widthself.height = heightself.im2num_arr = []#点击事件def pClick(self, x1, y1, x2, y2):m = PyMouse()p1_x = int(self.left + (y1) * self.width - int((self.width / 2)))p1_y = int(self.top + (x1) * self.height - int((self.height / 2)))p2_x = int(self.left + (y2) * self.width - int((self.width / 2)))p2_y = int(self.top + (x2) * self.height - int((self.height / 2)))time.sleep(0.3)#沉睡时间m.click(int(p1_x / 1.25), int(p1_y / 1.25))time.sleep(0.3)m.click(int(p2_x / 1.25), int(p2_y / 1.25))# time.sleep(0.1)# 设置矩阵值为0self.im2num_arr[x1][y1] = 0self.im2num_arr[x2][y2] = 0print("消除:(%d, %d) (%d, %d)" % (x1, y1, x2, y2))# 是否为同行或同列且可连#X1 Y1 元素坐标x值以及y值 X2 Y2 元素坐标x值 y值def isReachable(self, x1, y1, x2, y2):# 1、先判断值是否相同if self.im2num_arr[x1][y1] != self.im2num_arr[x2][y2]:return False# 判断横向连通if self.isSameRow(x1, y1, x2, y2):return True# 判断纵向连通if self.isSameCol(x1, y1, x2, y2):return True# 判断一个拐点可连通if self.turnOnceCheck(x1, y1, x2, y2):return True# 判断两个拐点可连通if self.turnTwiceCheck(x1, y1, x2, y2):return True# 不可联通返回Falsereturn False#是否两个元素同行def isSameRow(self, x1, y1, x2, y2):if (abs(y1 - y2) == 1 and x1 == x2):  # 同行且相邻return Trueif (abs(y1 - y2) > 1 and x1 == x2):  # 同行不相邻# if (x1 == 0 or x1 == (self.pHeight - 1)):  # 最外行#     return Trueflag = 0for i in range(min(y1, y2) + 1, max(y1, y2)):if self.im2num_arr[x1][i] == 0:flag = flag + 0else:flag = flag + 1if (flag == 0):return Truereturn False#是否同列def isSameCol(self, x1, y1, x2, y2):if (abs(x1 - x2) == 1 and y1 == y2):  # 同列且相邻return Trueif (abs(x1 - x2) > 1 and y1 == y2):  # 同列不相邻# if (y1 == 0 or y1 == (self.pWidth - 1)):  # 在最外列#     return Trueflag = 0for i in range(min(x1, x2) + 1, max(x1, x2)):if self.im2num_arr[i][y1] == 0:flag = flag + 0else:flag = flag + 1if (flag == 0):return Truereturn False# 判断一个拐点可联通def turnOnceCheck(self, x1, y1, x2, y2):if x1 == x2 or y1 == y2:return Falsecx = x1cy = y2dx = x2dy = y1# 拐点为空,从第一个点到拐点并且从拐点到第二个点可通,则整条路可通。if self.im2num_arr[cx][cy] == 0:if self.isSameRow(x1, y1, cx, cy) and self.isSameCol(cx, cy, x2, y2):return Trueif self.im2num_arr[dx][dy] == 0:if self.isSameRow(x1, y1, dx, dy) and self.isSameCol(dx, dy, x2, y2):return Truereturn False# 判断两个拐点可联通def turnTwiceCheck(self, x1, y1, x2, y2):if x1 == x2 and y1 == y2:return False# 遍历整个数组找合适的拐点for i in range(0, len(self.im2num_arr)):for j in range(0, len(self.im2num_arr[1])):# 不为空不能作为拐点if self.im2num_arr[i][j] != 0:continue# 不和被选方块在同一行列的不能作为拐点if i != x1 and i != x2 and j != y1 and j != y2:continue# 作为交点的方块不能作为拐点if (i == x1 and j == y2) or (i == x2 and j == y1):continueif self.turnOnceCheck(x1, y1, i, j) and (self.isSameRow(i, j, x2, y2) or self.isSameCol(i, j, x2, y2)):return Trueif self.turnOnceCheck(i, j, x2, y2) and (self.isSameRow(x1, y1, i, j) or self.isSameCol(x1, y1, i, j)):return Truereturn False# 判断矩阵是否全为0def isAllZero(self, arr):for i in range(0, self.pWidth + 2):for j in range(0, self.pHeight + 2):if arr[i][j] != 0:return Falsereturn Truedef start(self):# 3、遍历查找可以相连的坐标global num1global num2num1 = 0#循环判断num2 = 0 #结束符print(self.im2num_arr)while not self.isAllZero(self.im2num_arr):if num1 == 10:for i in range(0, self.pWidth + 2):for j in range(0, self.pHeight + 2):self.im2num_arr[i][j] = 0num2 = 1for x1 in range(0, self.pWidth + 2):for y1 in range(0, self.pHeight + 2):if self.im2num_arr[x1][y1] == 0:continuefor x2 in range(0, self.pWidth + 2):for y2 in range(0, self.pHeight + 2):if self.im2num_arr[x2][y2] == 0 or (x1 == x2 and y1 == y2):continueif self.im2num_arr[x1][y1] == self.im2num_arr[x2][y2]:if self.isReachable(x1, y1, x2, y2):self.pClick(x1, y1, x2, y2)num1 = num1 + 1return num2
if __name__ == '__main__':t = run_game(304, 271, 1226, 870,10,14,60.2,65.9)#设置元素坐标time.sleep(3)#等待3秒image = cutPicture(304, 271, 1226, 870,10,14,60.2,65.9)#截图arr = makeArray(10,14,image)#设置矩阵t.im2num_arr = arrnum = t.start()print("游戏结束!")

总结:程序难点在于两个图片之间相似度识别的精确性,不过对于练练看这个游戏来说,这个程序所使用的计算算法是够用的。

遇到问题:程序往往错误判断两个图片可以连接

解决方案:细微调整截图以及小图切分的像素位置,往往小图的切分是问题导致的关键,只要调整好切分的像素坐标,是没有问题的。

再次放视频链接:感兴趣可以看看,这是自制文章和视频,纯粹是兴趣分享,请在视频中点个赞吧!https://www.ixigua.com/7076826558106698253?logTag=f2d215ea6e6372c45362

说明:文章中引用了部分网友的知识点,不过这个程序我写的太久远的,不知道是哪篇文章了,如有引用请在评论区说明,我加个链接。

连连看不一样的玩法,利用python进行图片相似度计算相关推荐

  1. Python图像识别,图片相似度计算!

    1.背景 要识别两张图片是否相似,首先我们可能会区分这两张图是人物照,还是风景照等......对应的风景照是蓝天还是大海......做一系列的分类. 从机器学习的的角度来说,首先要提取图片的特征,将这 ...

  2. python 图像识别_python图像识别之图片相似度计算

    作者 | a1131825850疯子 来源 | Python爬虫scrapy 原文 | python图像识别---------图片相似度计算 1.背景 要识别两张图片是否相似,首先我们可能会区分这两张 ...

  3. 休闲经营的农场小游戏推荐,果蔬连连看h5版游戏玩法技巧

    想必许多80.90后的小伙伴们对农场小游戏并不陌生,当年经典的人人农场游戏,开创了农场小游戏玩法的先河,随着游戏的玩法不断更新,玩家对于农场游戏的品质也是越来越高!今天咱们就来聊聊农场游戏和农场果蔬连 ...

  4. pythonmat文件转excel,利用python将图片转换成excel文档格式

    前言 本文主要介绍了关于利用python将图片转换成excel文档的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现步骤 读取图像,获取图像每个像素点的RGB值: 根据 ...

  5. 怎样用python生成中文字符画_如何利用Python实现图片转字符画详解

    本篇文章主要介绍了Python实现图片转字符画的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 字符画真的很有意思,将图片中的像素用字符代替,就生成了字符画. 但是像 ...

  6. 利用python改图片为任意颜色

    一.利用到的库 利用python改变图片颜色的实现主要依靠pillow模块.Python的版本和pillow的版本对应是相对来说最容易使人混乱地方. 版本对应如下: 利用pycharm下载对应pill ...

  7. 【Python例】利用 python 进行图片文字信息的提取 --- OCR-EasyOCR

    [Python例]利用 python 进行图片文字信息的提取 - OCR-EasyOCR 本文主要用于记录,并使用 python 脚本进行图片文字信息的生成. 什么是 OCR? OCR OCR(Opt ...

  8. pythonmat文件转excel_利用python将图片转换成excel文档格式详解

    本文主要介绍了关于利用python将图片转换成excel文档的相关内容,编写了一小段Python代码,将图片转为了Excel,纯属娱乐,下面这篇文章主要给大家介绍了关于利用python将图片转换成ex ...

  9. python读取图片文字为表格_利用python将图片转换成excel文档格式

    前言 本文主要介绍了关于利用python将图片转换成excel文档的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 实现步骤 读取图像,获取图像每个像素点的RGB值: 根据 ...

最新文章

  1. 对比:Linux和Windows系统线程间的区别
  2. java 程序片段_20个非常有用的Java程序片段
  3. ORACLE经常使用的命令
  4. tms脚本演示代码之一
  5. python大鱼吃小鱼_python 游戏编程 大鱼吃小鱼
  6. Oracle数据库应用系统结构
  7. 安卓学习笔记33:实现逐帧动画
  8. ZAO回应被约谈...
  9. java后端简历项目经历_java后台开发个人简历怎么写
  10. vmplayer linux kernel headers
  11. 讲座笔记 | 批判性思维和论文写作
  12. 2019.7月面试题总结(三)
  13. elasticsearch+filebeat+kibana实现系统日志收集
  14. 大学计算机课程教学建议,计算机应用基础课程教学的建议
  15. 动态壁纸android,Android 十大最新版本动态壁纸大盘点
  16. 面向对象类和类之间的几种关系
  17. android tab 纵向,GitHub - luonzke/VerticalTabLayout: 垂直纵向的TabLayout、轻松创建纵向导航...
  18. 11.21 CSS学习-上午
  19. 视网膜竞争(双目竞争)现象
  20. 2015英国女王殿下的圣诞致辞

热门文章

  1. 阿里巴巴发声:假的!假的!假的!
  2. 吉祥密 让我们关爱孩子:引人深思的早教故事
  3. cubemx 读卡器_STM32CubeMX+Keil实现 STM32F4 SDcard+SPI Flash读卡器
  4. 前端:CSS3新特性transform制作雪花飘落动画
  5. 浅谈linux - virtual box设置共享文件夹
  6. c语言小子集,C语言小子集的词法分析程序
  7. PID控制介绍以及在智能车中的应用
  8. 如何使用Python 制作一副扑克牌!来看是怎么实现的!
  9. 基于SSM的电影院订票系统(Spring+SpringMVC+Mybatis)
  10. php移动d盘文件,从C盘将用户文件移动到D盘