我在玩QQ游戏 比如大家来找茬的时候 眼力不是很好 经常找不到,但是又好奇 这我没找到的位置都在哪里呢?所以我做个辅助帮我把两幅图的像素相减,再把得到的噪点值粘回去到某幅图上,总体流程列出来就是
找到”大家来找茬”游戏窗口句柄,窗口提到最前好截图 切分左右两张图片,切成小图后根据像素区间分布找出差值比较大的矩形标出 OpenCv的两张图像像素相减,去噪 显示结果,把步骤2的标识图片+步骤3的像素差噪图合在一起Ok 大致就是这样 showCodeTime
# -*- coding:utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') ### 系统自带的模块 from datetime import datetime import ImageGrab import shutil import math import os ### 可能需要额外安装的模块部分 # 自动化模块 import win32gui import win32con # 图片处理模块 import ImageDraw import Image # OpenCv模块 import cv2 import numpy as np ### 全局变量 # 当前文件夹路径 CUR_DIR = os.getcwd() # 获得句柄 game_hwnd = win32gui.FindWindow(None, u"大家来找茬") # 强行显示界面后才好截图 win32gui.ShowWindow(game_hwnd, win32con.SW_RESTORE) # 将游戏窗口提到最前 win32gui.SetForegroundWindow(game_hwnd) # 裁剪得到部分主要图片,作为处理素材 game_rect = win32gui.GetWindowRect(game_hwnd) src_image = ImageGrab.grab((game_rect[0] + 9, game_rect[1] + 190, game_rect[2] - 9, game_rect[1] + 190 + 450)) # # 将得到的图片保存下来 后面如果要改进也好当素材 sucai = os.path.join(CUR_DIR, 'sucai') ICount = len(os.listdir(sucai)) if not os.path.exists(sucai): os.makedirs(sucai) save_path = os.path.join(sucai, datetime.now().strftime("%Y_%m_%d_%H_%M_%S_")+str(ICount))+'.png' src_image.save(save_path) """ ### 这部分代码主要是拿素材来测试结果的 file_name = "full.png" file_name = os.path.join(sucai, os.listdir(sucai)[11]) src_image = Image.open(file_name) """ def compare(image_a, image_b): """ 用来获得两图比较的数值差: 返回两图的差异值 返回两图红绿蓝差值万分比之和 image_a : 图a, image_b : 图b """ histogram_a = image_a.histogram() histogram_b = image_b.histogram() if len(histogram_a) != 768 or len(histogram_b) != 768: return # 红 差值比率 red_a = 0 red_b = 0 for i in xrange(0, 256): red_a += histogram_a[i + 0] * i red_b += histogram_b[i + 0] * i diff_red = 0 max_red = red_a + red_b if red_a + red_b > 0: diff_red = abs(red_a - red_b) * 10000 / max_red # 绿 差值比率 green_a = 0 green_b = 0 for i in xrange(0, 256): green_a += histogram_a[i + 256] * i green_b += histogram_b[i + 256] * i diff_green = 0 max_green = green_a + green_b if green_a + green_b > 0: diff_green = abs(green_a - green_b) * 10000 / max_green # 蓝 差值比率 blue_a = 0 blue_b = 0 for i in xrange(0, 256): blue_a += histogram_a[i + 512] * i blue_b += histogram_b[i + 512] * i diff_blue = 0 max_blue = blue_a + blue_b if blue_a + blue_b > 0: diff_blue = abs(blue_a - blue_b) * 10000 / max_blue mSum = max_red + max_green + max_blue result = 0 if mSum > 0: # 自定义权重计算 result = ( max(red_a, red_b) + max(green_a, green_b) + max(blue_a, blue_b) ) - ( min(red_a, red_b) + min(green_a, green_b) + min(blue_a, blue_b) ) result = result * 10000 / (max_red + max_green + max_blue) # 颜色白的图片 集体像素都比较高 所以总像素深度可以作为一个参考量 result = result * math.pow( (max_red + max_green + max_blue) / 100000.0 , 0.7 ) return result def pic_sub(dest, s1, s2, threshod): """ 这个函数主要是计算两张图片的相熟差的 dest : 结果存贮矩阵, s1 : 图1, s2 : 图2, threshod : 阈值 """ for x in range(dest.shape[0]): for y in range(dest.shape[1]): if (s2[x,y] > s1[x,y]): dest[x,y] = s2[x,y] - s1[x,y] else: dest[x,y] = s1[x,y] - s2[x,y] if (dest[x,y] < threshod): dest[x,y] = 0 else: dest[x,y] = 255 ### 创建一个类 找茬 class findCha(object): def __init__(self, src_image): super(findCha, self).__init__() # 传入要分析的窗口图片 self.src_image = src_image self.init() def init(self): # 这里主要是找到左右两张用来比对的图片 由于是我个人娱乐所用 暂时没考虑不同电脑的分辨率 left_box = (84, 124, 464, 408) right_box = (541, 124, 541 + 380, 408) # 切开找到左右两图 self.image_left = self.src_image.crop(left_box) self.image_right = self.src_image.crop(right_box) # 两张图片保存到本地media文件夹下 为何要保存了 因为我用了像素分布比较+OpenCV的两张图像素相减 这里保存的图就是给cv用的 self.saveMedia() # OpenCV 找到两张图像素相减的差异 self.bitDiff() # 根据像素分布区间差 用画矩阵的形式标识出 self.drawRect(1, 1500) # 展示图片保存结果 self.saveImage() def saveMedia(self): """ 找到要找的茬 两张图片保存到本地media文件夹下 """ media = os.path.join(CUR_DIR, 'media') if os.path.exists(media): shutil.rmtree(media) os.makedirs(media) self.image_left_path = os.path.join(media, 'img_left.png') self.image_left.save(self.image_left_path) self.image_right_path = os.path.join(media, 'image_right.png') self.image_right.save(self.image_right_path) def bitDiff(self): """ 两张图片像素相减 去燥后的图片 """ threshod = 20 s1 = cv2.imread(self.image_left_path, 0) s2 = cv2.imread(self.image_right_path, 0) # 初始空矩阵 用于存储相减结果 emptyimg = np.zeros(s1.shape, np.uint8) pic_sub(emptyimg, s1, s2, threshod) # 保存 二值图像,两者的差值图片 self.bit_diff_path = os.path.join(CUR_DIR, 'media', 'bit_diff.png') cv2.imwrite(self.bit_diff_path, emptyimg) def drawRect(self, multiple, low_limit): """ 在图片上画矩阵作为标识 multiple : 图片切分大小倍数, low_limit : 根据像素区间差 差量大于这个下限值要显示 """ img_width = 380 img_height = 284 # 横向切割为几张图片 div_x = int(19 * multiple) # 纵向切割图片 div_y = int(15 * multiple) # 切成小图的长宽值 width = int(math.ceil(img_width / div_x)) height = int(math.ceil(img_height / div_y)) # 设置画板 draw = ImageDraw.Draw(self.image_right) for col in xrange(0, div_x + 1): for row in xrange(0, div_y + 1): clip_box = (col * width, row * height, (col + 1) * width, (row + 1) * height) # 左右两边裁剪出相应位置小图来比对 clip_image_left = self.image_left.crop(clip_box) clip_image_right = self.image_right.crop(clip_box) clip_diff = compare(clip_image_left, clip_image_right) if clip_diff > low_limit: draw.rectangle(clip_box) # 消除滑板 del draw def saveImage(self): """ 显示结果和保存图片 """ toImage = Image.new('RGBA', (380, 284*3)) toImage.paste(self.image_left, (0, 0)) # 左右图片像素相减后的噪点图 bit_diff_img = Image.open(self.bit_diff_path).convert(self.image_left.mode) bit_diff_img = bit_diff_img.resize(self.image_left.size) img = Image.blend(self.image_right, bit_diff_img, 0.7) toImage.paste(img, (0, 284)) toImage.paste(self.image_right, (0, 284*2)) toImage.show() if __name__ == '__main__': findCha(src_image)
大致就是这样 现在想做成标识出差异的图片 之后去燥做得更好一些再做成自动点击自动和自动下一局的
部分结果显示