携手创作,一起生长!这是我参与「日新计划 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)