边缘在人类视觉和计算机视觉中均起着重要的作用。


人类能够仅凭一张背景剪影或一个草图就识别出物体类型和姿态。


其中OpenCV提供了许多边缘检测滤波函数,这些滤波函数都会将非边缘区域转为黑色,将边缘区域转为白色或其他饱和的颜色。


不过这些滤波函数都很容易将噪声错误地识别为边缘,所以需要进行模糊处理。


本次的模糊操作使用高斯模糊(低通滤波器),最常用的模糊滤波器(平滑滤波器)之一,是一个削弱高频信号强度的低通滤波器。


低通滤波器,在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度,主要用于去噪和模糊化。


边缘检测则是使用OpenCV的Canny函数实现,算法虽然很复杂,但是代码却很简单。


5个步骤,使用高斯滤波器对图像去噪、计算梯度、在边缘上使用非最大抑制(NMS)、在检测到的边缘上使用双(double)阈值去除阳性(false positive)、分析所有的边缘及其连接,保留真正的边缘并消除不明显的边缘。


下面就来实现一下「跳一跳」的边缘检测,得以获取方块的中心位置。



/ 01 / 边缘检测


Canny边缘检测代码如下。


import cv2
import numpy as np

# 读取原图像
img = cv2.imread('game.png'0)

# 显示原图像
cv2.namedWindow('img'0)
cv2.resizeWindow('img'400600)
cv2.imshow('img', img)

# 高斯模糊
img_rgb = cv2.GaussianBlur(img, (55), 0)
canny_img = cv2.Canny(img_rgb, 110)

# 显示边缘检测图像
cv2.namedWindow('canny'0)
cv2.resizeWindow('canny'400600)
cv2.imshow('canny', canny_img)

# 输出边缘检测图像的高和宽
H, W = canny_img.shape
print(H, W)


输出的图像高宽分别为1920和1080。


下面是原图像灰度图和边缘检测图像。



接下来,通过边缘检测图像找到方块的第一个顶点(上顶点)。


# 第一个顶点的高度,row为列表(代表每一行的像素值),max(row)获取列表中最大的像素值
y_top = np.nonzero([max(row) for row in canny_img[400:]])[0][0] + 400


对图像高度大于400的行进行遍历(这样可以去除上方数字270以及小程序块的影响)。


np.nonzero()表示获取列表元素数值不为0的位置,第一个即为上顶点的高度值。



接下来获取上顶点的宽度值。


# 第一个顶点的宽度
x_top = int(np.mean(np.nonzero(canny_img[y_top])))


这里发现有好几个水平点,所以最后取平均值。


接下来对方块下顶点的位置进行确定。



为了跳过小白圈的影响,在上顶点高度的基础上加上80个像素大小。


然后往下方遍历,宽度值保持不变,直至找到像素值不为0的点。


便得到了方块的下顶点坐标。


# 跳过小白圈,然后遍历
y_bottom = y_top + 80
for row in range(y_bottom, H):
    if canny_img[row, x_top] != 0:
        y_bottom = row
        break

# 得到方块的中心点
x_center, y_center = x_top, (y_top + y_bottom) // 2

# 绘制以方块中心点为圆心的圆
cv2.circle(canny_img, (x_center, y_center), 33, (2550255), 2)

# 显示得到的图像
cv2.namedWindow('result'0)
cv2.resizeWindow('result'400600)
cv2.imshow('result', canny_img)

# 结束
cv2.waitKey(0)
cv2.destroyAllWindows()


最后通过上下顶点的坐标,得到方块的中心点。



左图为边缘检测原图,右图为找到方块中心点并以中心点为圆心绘制圆形的图像。



/ 02 / 跳动实现


现在结合之前模板匹配获得到的小跳棋位置,计算两中心的距离。


勾三股四弦五,便能得到两个中心的距离了。


看下图,一目了然。



玩过跳一跳的应该都知道,对于不同的距离,我们需要按压的时间是不同的。


所以可以给距离和按压时间设置一个相关参数,此处设置为1.35。


对于我的手机简直完美匹配(与屏幕大小有关)。


最后通过adb命令完成一定的按压时间,完成「跳一跳」自动化。



/ 03 / 总结


跳一跳」自动化马上就要实现,全部源码下期见。


万水千山总是情,点个「在看」行不行。





···  END  ···



©著作权归作者所有:来自51CTO博客作者mb5fe18ec4a4df8的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. OpenYurt v0.3.0 重磅发布:全面提升边缘场景下应用部署效率
  2. 一文读懂 SuperEdge 边缘容器架构与原理
  3. 去除Chrome浏览器文本框边缘的黄线
  4. 在networkx中添加和删除随机边缘
  5. 在NumPy中更改数组边缘的值
  6. 从“顶点小说”下载完整小说——python爬虫
  7. 2D Numpy Array的边缘值

随机推荐

  1. Android Display
  2. Android Button在中间显示
  3. android:tint
  4. android:定制checkbox 图片
  5. android 停止Handler
  6. 【Android Http Post】android post 请求
  7. Android 数据存储
  8. android开发指南中文版
  9. 阅读《Android(安卓)从入门到精通》(5)——
  10. android 动画模块分析