封校大学生在宿舍无聊玩起图像大找茬——一个关于游戏的练手小项目(一起领略Python脚本的风采吧)

图像大找茬

  • 前言
  • 基础知识
  • 图片找茬
  • 抓取句柄图片
  • GUI界面搭建

前言

在一个月黑风高的夜晚,我的舍友小许摇起我来,面色惊恐地说道:“快来帮我,我要不行了o(╥﹏╥)o”。我连忙起身,问到他你怎么了,他把我拉到他电脑面前,一脸凝重的说道:这两张图片我找不出第五个不同的地方。我上来...就给他个大B兜,睡觉。凄凄惨惨戚戚,独留一人守空房...


基础知识

  1. 首先我们要想分清两种图片的不同就要想起它——灰度图。
  2. 其次我们找到一个可以获取不同页面句柄的库实时截取图片(这里不采用抓包
  3. PyQt5设计页面

图片找茬

原图

        灰度图使用skimage库可以轻松解决pip install scikit-image,同时安装pip install opencv-python以显示图片。

imageA = cv2.imread("./first.png")imageB = cv2.imread("./second.png")grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

扩展:用到了SSIM原理,也可以叫他结构相似性指数,是一种衡量两幅图像相似度的指标。

#调用ssim函数from skimage.metrics import structural_similarity#返回三个值mssim, grad , S = structural_similarity(grayA, grayB, gradient=True,full=True)'''mssim:float图像上的平均结构相似性指数。grad:ndarrayim1 和 im2 [2]之间结构相似性的梯度。这仅在梯度设置为 True 时返回。S:ndarray完整的 SSIM 图像。这仅在full设置为 True 时返回。'''
可以打印mssim数值观察ssim指数,此指数越高说明越相似 但是需要注意的是SSIM返回的ndarray里面的值为[0, 1]的float型,而OpenCV的[0, 255]为uint8型,用如下转换
grad= (grad* 255).astype("uint8")

grad对应图片

然后用cv2中图像阈值处理threshold函数去寻找轮廓,然后用imutils.grab_contours返回cnts中的countors(轮廓),然后用cv2.boundingRect获取边界框位置,直接用cv2.rectangle画出方框

thresh = cv2.threshold(S, 0, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]cnts = imutils.grab_contours(cnts)

threshold函数寻找到的轮廓

for c in cnts:    #获取边界框位置   (x, y, w, h) = cv2.boundingRect(c)   cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), thickness = 4)   cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), thickness = 4)

最后打印图片保存即可。
源码

#Image_Compare from skimage.metrics import structural_similarityimport imutilsimport cv2import argparsedef Make_picture() -> object:    parser = argparse.ArgumentParser(description="查找茬图像输入")    parser.add_argument("-f","--first",default=False,help="first image")    parser.add_argument("-s","--second",help="first image")    args = vars(parser.parse_args())    imageA = cv2.imread("./first.png")    imageB = cv2.imread("./second.png")    #灰度图    grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)    grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)    #计算两幅图像之间的结构相似性指数(SSIM,确保返回差异图像    (mssim, grad ,S) = structural_similarity(grayA, grayB, full=True,gradient=True)    S = (S * 255).astype("uint8")    thresh = cv2.threshold(S, 0, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)    cnts = imutils.grab_contours(cnts)    for c in cnts:        (x, y, w, h) = cv2.boundingRect(c)        cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), thickness = 4)        cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), thickness = 4)    cv2.waitKey(0)    cv2.imwrite(filename="Find_Different.png", img=imageB)#测试时解开注释#Make_picture()

抓取句柄图片

需要安装pip install pywin32,这个库可以完成根据自己电脑打开的程序抓取所需句柄(也就是已经打开的任意程序
具体操作:打开qq游戏大厅中的大家来找茬小游戏,咳咳,找个座位坐下,进入游戏前点开程序,然后开始游戏后点击开始!开始检测!十图场乱杀

#PyQt5_catchWindows.pyimport win32guifrom PyQt5.QtWidgets import QApplicationfrom PyQt5.QtGui import *import sysfrom Image_Compare import  Make_picturefrom PIL import Image # 导入PIL库import win32conhwnd_title = dict()def get_all_hwnd(hwnd,mouse):    if win32gui.IsWindow(hwnd) and win32gui.IsWindowEnabled(hwnd) and win32gui.IsWindowVisible(hwnd):        hwnd_title.update({hwnd: win32gui.GetWindowText(hwnd)})        hwnd_title.update({hwnd:win32gui.GetWindowText(hwnd)})        win32gui.EnableWindow(hwnd,True)    #print(win32gui.IsWindow(hwnd))def Get_Windows():#通过将句柄依次传递给应用程序定义的回调函数,枚举屏幕上的所有顶级窗口。    win32gui.EnumWindows(get_all_hwnd, 0)    for h,t in hwnd_title.items():        if t != '':           print(h,t)        if t == '大家来找茬':            hwnd = win32gui.FindWindow(None, t)            #返回屏幕坐标中窗口的矩形            b = win32gui.GetWindowRect(hwnd)            screen = QApplication.primaryScreen()            img1 = screen.grabWindow(hwnd,549,311,383,288).toImage()            img1.save("first.png", "png")            img2 = screen.grabWindow(hwnd, 92, 311, 383, 288).toImage()            img2.save("second.png", "png")            clsname = win32gui.GetClassName(hwnd)            title = win32gui.GetWindowText(hwnd)            return img1,img2        #print(clsname, title)def Start():    img1,img2 = Get_Windows()    Make_picture()

GUI界面搭建

按上述操作完成后打开界面如下

#Pyqt_UI.pyimport sysfrom PyQt5 import QtWidgets, QtCore, QtGuifrom PyQt5.QtWidgets import *from PyQt5.QtCore import *import PyQt5_catchWindowsclass picture(QWidget):    def __init__(self):        super(picture, self).__init__()        self.setWindowTitle("显示图片")        self.label = QLabel(self)        self.label.setText("生成图像框")        self.label.setFixedSize(383,288)        self.label.move(10, 10)        self.label.setStyleSheet("QLabel{background:white;}"                                 "QLabel{color:rgb(300,300,300,120);"                                 "font-size:70px;font-weight:bold;"                                 "font-family:黑体;}"                                 )        btn = QPushButton(self)        btn.setText("开始检测")        print(1)        btn.move(160, 330)        btn.clicked.connect(self.openimage)    def openimage(self):        PyQt5_catchWindows.Start()        imgName = "Find_Different.png"        jpg = QtGui.QPixmap(imgName).scaled(self.label.width(), self.label.height())        self.label.setPixmap(jpg)if __name__ == "__main__":    app = QtWidgets.QApplication(sys.argv)    my = picture()    my.show()    sys.exit(app.exec_())

纯纯辅助神器,喜欢的朋友们可以去玩一玩哦😘😘求一键三连。

项目地址

 
友情链接
鄂ICP备19019357号-22