携手创作,一起生长!这是我参与「日新计划 8 月更文应战」的第29天,点击检查活动详情

项目需求

  相信我们不少的人从前都玩过找不同游戏的,今天想趁热打铁,做一个找不同游戏的“辅佐”来进行主动找不同。先来介绍找不同游戏的操作逻辑:

1. 登录游戏网页端,全屏显现便于清晰检查不同点;
2. 画面中显现两张类似的图画,这两张图画只存在部分当地存在差异;
3. 点击存在差异的当地即认可为完结了“找不同”任务

  介绍完游戏的操作逻辑,咱们依据操作逻辑进行“主动找不同”程序设计完结上述逻辑:

1. 截取当时游戏画面(固定);
2. 分别锚定两张类似图画并切割下来(由于游戏画面固定,出现图画的方位也会固定);
3. 对两张类似的图画进行处理得到不同方位的方位,并输出中心点坐标。

需求剖析

  完结“找不同”一件很难的工作,程序设计的前两个需求并不是很难,经过前面两个辅佐的制造,能够经过pyautogui.screenshot() 和 pymouse 能够完结屏幕画面的截取和鼠标的移动点击;经过OpenCvd的切割能够完结类似图的切割。较为难完结的是找到不同的方位,本文也将重点剖析如何找到不同!

  网上流传较为广的是一种遍历两张图画的像素,当像素不一样的时候输出此时的方位。这里我就不阐述它的逻辑了。我将按照如下的几种计划完结找不同任务:

1. 对裁剪下来的两张图画进行灰度化后做差得到结果进行二值化;
2. 运用图画匹配法完结“找不同”
3. 遍历像素完结

实施验证

  今天时间有限,先做个“丐版”的找不同。从技能完结的角度有限处理核心部分,完结“有无”的难题。咱们提早将两张类似的图画截取下来:

不要傻乎乎的去找不同了,一起来用代码完成“找不同”游戏吧
不要傻乎乎的去找不同了,一起来用代码完成“找不同”游戏吧

运用作差法完结:

import cv2
img_1 = cv2.imread("1.png") # Slicing to crop the image
img_2 = cv2.imread("2.png")
img_1 = cv2.cvtColor(img_1,cv2.COLOR_BGR2GRAY)
img_2 = cv2.cvtColor(img_2,cv2.COLOR_BGR2GRAY)
img3 = img_1 - img_2
ret, img3 = cv2.threshold(img3, 50, 255,  cv2.THRESH_BINARY_INV)
cv2.imshow("a", img3)
cv2.waitKey(0)
不要傻乎乎的去找不同了,一起来用代码完成“找不同”游戏吧

运用遍历像素完结:

import cv2
img_1 = cv2.imread("1.png") # Slicing to crop the image
img_2 = cv2.imread("2.png")
img_11 = cv2.cvtColor(img_1, cv2.COLOR_BGR2GRAY)
img_22 = cv2.cvtColor(img_2, cv2.COLOR_BGR2GRAY)
width,height = img_11.shape
for i in range(width):
    for j in range(height):
        x = img_11[i][j]
        y = img_22[i][j]
        if abs(x - y) > 30:
            img_1[i][j] = [0, 0, 0]
cv2.imshow("result", img_1)
cv2.waitKey(0)
不要傻乎乎的去找不同了,一起来用代码完成“找不同”游戏吧

图画匹配法

图画匹配法是借用某位大神的代码,结果供我们参阅一下:

import cv2
import numpy as np
from matplotlib import pyplot as plt
import argparse
def matchAB(fileA, fileB):
    # 读取图画数据
    imgA = cv2.imread(fileA)
    imgB = cv2.imread(fileB)
    # 转换成灰色
    grayA = cv2.cvtColor(imgA, cv2.COLOR_BGR2GRAY)
    grayB = cv2.cvtColor(imgB, cv2.COLOR_BGR2GRAY)
    # 获取图片A的巨细
    height, width = grayA.shape
    # 取部分图画,寻觅匹配方位
    result_window = np.zeros((height, width), dtype=imgA.dtype)
    for start_y in range(0, height - 100, 10):
        for start_x in range(0, width - 100, 10):
            window = grayA[start_y:start_y + 100, start_x:start_x + 100]
            match = cv2.matchTemplate(grayB, window, cv2.TM_CCOEFF_NORMED)
            _, _, _, max_loc = cv2.minMaxLoc(match)
            matched_window = grayB[max_loc[1]:max_loc[1] + 100, max_loc[0]:max_loc[0] + 100]
            result = cv2.absdiff(window, matched_window)
            result_window[start_y:start_y + 100, start_x:start_x + 100] = result
    # 用四边形圈出不同部分
    _, result_window_bin = cv2.threshold(result_window, 30, 255, cv2.THRESH_BINARY)
    _, contours, _ = cv2.findContours(result_window_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    imgC = imgA.copy()
    for contour in contours:
        min = np.nanmin(contour, 0)
        max = np.nanmax(contour, 0)
        loc1 = (min[0][0], min[0][1])
        loc2 = (max[0][0], max[0][1])
        cv2.rectangle(imgC, loc1, loc2, 0, 2)
    plt.subplot(1, 3, 1), plt.imshow(cv2.cvtColor(imgA, cv2.COLOR_BGR2RGB)), plt.title('A'), plt.xticks([]), plt.yticks(
        [])
    plt.subplot(1, 3, 2), plt.imshow(cv2.cvtColor(imgB, cv2.COLOR_BGR2RGB)), plt.title('B'), plt.xticks([]), plt.yticks(
        [])
    plt.subplot(1, 3, 3), plt.imshow(cv2.cvtColor(imgC, cv2.COLOR_BGR2RGB)), plt.title('Answer'), plt.xticks(
        []), plt.yticks([])
    plt.show()
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--source_image',
        type=str,
        default='1.png',
        help='source image'
    )
    parser.add_argument(
        '--target_image',
        type=str,
        default='2.png',
        help='target image'
    )
    FLAGS, unparsed = parser.parse_known_args()
    matchAB(FLAGS.source_image, FLAGS.target_image)

不要傻乎乎的去找不同了,一起来用代码完成“找不同”游戏吧