【源码解读】AI实现跳一跳

源码来源:https://github.com/Prinsphield/Wechat_AutoJump

【OpenCV】

OpenCV帮助文档:https://docs.opencv.org/

cv2.imread():
功能:图像读入
参数:总共2个。第一个指定图片路径。
第二个参数是要告诉函数应该如何读取这幅图片:
cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略, 这是默认参数。
cv2.IMREAD_GRAYSCALE:以灰度模式读入图像
调用opencv,就算图像的路径是错的,OpenCV 也不会提醒你的,但是当你使用命
令print img时得到的结果是None。

示例代码(Lena图片可网上下载):

#/usr/bin/env python
# -*- coding: utf-8 -*-
# 这段代码的作用是在Lena.jpg中匹配对应的模版图片的坐标,并用矩形框画出

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 以灰度模式读入图片,这样img.shape就只有二维。否则还会多一维表示彩色
img=cv2.imread('Lena.jpg',cv2.IMREAD_GRAYSCALE)
img2 = img.copy()
# 指定第二个参数0会导致mathTemplate执行报错:template = cv2.imread('Lena_eyes.png',0)
template = cv2.imread('Lena_eyes.png',cv2.IMREAD_GRAYSCALE)

w, h = template.shape[::-1]

# Apply template Matching
res = cv2.matchTemplate(img2,template,cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)

cv2.rectangle(img2,top_left,bottom_right,255,2)

# 绘制1行2列的grid,图片显示在第二个位置
plt.subplot(122), plt.imshow(img2,cmap = 'gray')
# 使用plt.xticks([])关闭坐标轴刻度
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle("TM_CCOEFF_NORMED")
plt.show()

cv2.resize():
函数原型:cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst
功能:图像缩放
注意:是缩放,不是裁剪

interpolation 选项及对应的插值方法:
INTER_NEAREST: 最近邻插值
INTER_LINEAR: 双线性插值(默认设置)
INTER_AREA: 使用像素区域关系进行重采样。 它可能是图像抽取的首选方法,因为它会产生无云纹理的结果。 但是当图像缩放时,它类似于INTER_NEAREST方法
INTER_CUBIC: 4×4像素邻域的双三次插值
INTER_LANCZOS4:8×8像素邻域的Lanczos插值

示例代码:
import cv2
pic = cv2.imread('./Elegent_Girl.jpg')
# 缩放成宽:400,高:200
pic = cv2.resize(pic, (400, 200), interpolation=cv2.INTER_CUBIC)
cv2.imshow('', pic)
cv2.waitKey(0)
cv2.destroyAllWindows()

需要特别注意的是,cv2.resize指定的顺序是(宽,高),而pic.shape数组中,pic.shape[0]是高,pic.shape[1]是宽。即:resize里的参数与shape数组的值顺序是相反的。

cv2.cvtColor():
原型:cv2.cvtColor(src, code[, dst[, dstCn]]) -> dst
功能:Converts an image from one color space to another,即颜色空间转换
背景:生活中大多数看到的彩色图片都是RGB类型,但是在进行图像处理时,需要用到灰度图、二值图、HSV、HSI等颜色制式,opencv提供了cvtColor()函数来实现这些功能。
原理:在opencv中,其默认的颜色制式排列是BGR而非RGB。对于24位颜色图像来说,前8-bit是蓝色,中间8-bit是绿色,最后8-bit是红色。根据图片格式及目标格式的不同,转换可能会出现信息损失,此处先不深入该话题。

# 例子:将图像转换为灰度图 
state=cv2.imread('./player.png') 
state = cv2.cvtColor(state, cv2.COLOR_BGR2GRAY)

图像匹配:
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
cv2.matchTemplate(): 在模板块和输入图像之间寻找匹配,获得匹配结果图像
cv2.minMaxLoc(): 在给定的矩阵中寻找最大和最小值(包括它们的位置),仅支持单一通道

函数返回值:
cv2.matchTemplate()返回的是一个矩阵数组表示的灰度图片,该矩阵的每个元素都用来衡量这个点附近的像素与模板图片的匹配程度。
所以在执行了cv2.matchTemplate后,我们根据匹配方法的不同,可以调用cv2.minMaxLoc()函数,找出与模板图片最匹配的那个点,进而画出识别出来的矩形框。

实现原理:
为了确定匹配区域, 我们不得不滑动模板图像和原图像进行 比较。
通过 滑动, 我们的意思是图像块一次移动一个像素 (从左往右,从上往下). 在每一个位置, 都进行一次度量计算来表明它是 “好” 或 “坏” 地与那个位置匹配 (或者说块图像和原图像的特定区域有多么相似).
对于 Template 覆盖在 Image 上的每个位置,你把度量值 保存 到 结果图像矩阵 (R) 中. 在 R 中的每个位置 (x,y) 都包含匹配度量值。
实际上, 我们使用函数 minMaxLoc 来定位在矩阵 R 中的最大值点 (或者最小值, 根据函数输入的匹配参数) 。

模板匹配算法. 可用的方法有6个:
1.平方差匹配 method=CV_TM_SQDIFF 
2.标准平方差匹配 method=CV_TM_SQDIFF_NORMED
(这两类方法利用平方差来进行匹配,最好匹配为0,匹配值越大,匹配结果越差)

3.相关匹配 method=CV_TM_CCORR
4.标准相关匹配 method=CV_TM_CCORR_NORMED
5.相关匹配 method=CV_TM_CCOEFF
6.标准相关匹配 method=CV_TM_CCOEFF_NORMED
(这类方法采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果)

性能:
通常,随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可获得越来越准确的匹配(同时也意味着越来越大的计算代价)

# 例子:
# Apply template Matching
res = cv2.matchTemplate(img,template,method)
# 这里调用cv2.minMaxLoc()返回的4个值,每个值都是一个二维坐标
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
   top_left = min_loc
else:
   top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)

# 根据左上,右下两个坐标,绘制出矩形框,边框颜色灰度值255,宽度2像素
cv2.rectangle(img,top_left,bottom_right,255,2)
#完整的代码请参考:
https://docs.opencv.org/3.1.0/d4/dc6/tutorial_py_template_matching.html

【numpy】

函数原型:numpy.where(condition[, x, y])
参数:
condition : array_like, bool
x, y : array_like, optional
返回:
ndarray or tuple of ndarrays
If both x and y are specified, the output array contains elements of x where condition is True, and elements from y elsewhere.
If only condition is given, return the tuple condition.nonzero(), the indices where condition is True. 参考网址:https://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.where.html#numpy.where

简单的理解:
numpy.where()函数是三元表达式x if condition else y的矢量化版本。
例子:
>>>import numpy as np 
>>>x = np.arange(9.).reshape(3, 3)
>>> x
array([[0., 1., 2.],
 [3., 4., 5.],
 [6., 7., 8.]])
>>> np.where(x>7)  (只有8符合,结果输出8所在的数组下标索引x[2][2])
(array([2]), array([2]))
>>> np.where(x>6)  (值:7,8符合,结果输出7,8所在的数组下标索引x[2][1],x[2][2])
(array([2, 2]), array([1, 2]))
>>> np.where(x<5,x,-1)  (如果数组元素小于5,打印元素本身,否则打印-1)
array([[ 0., 1., 2.],
 [ 3., 4., -1.],
 [-1., -1., -1.]])
>>>

np.linspace():
原型:linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
功能:用此来创建等差数列。

例子:
import numpy as np
x1=np.linspace(1-0.3, 1+0.3, 10)[::-1]
效果:生成0.7-1.3之间的10个等差数,-1指定倒序排列

print(x1),输出为:
[1.3 1.23333333 1.16666667 1.1 1.03333333 0.96666667
 0.9 0.83333333 0.76666667 0.7 ]

【Matplotlib】