每个人儿时都有一个武侠梦,梦想自己有一天10块钱买到一本如来神掌,从此仗剑走天涯,不过在桃花岛,真的有一本秘籍:隔空玩游戏,今天,就带领大家翻阅翻阅这本秘籍。

这本秘籍全部都是用python来完成的哦,想要学会它然后仗剑走天涯,就要先学会一部分python知识,好了,我们先来看看效果吧~

演示完毕,现在我们来进入教学阶段吧~本次我们只讨论手势识别的过程,用python写游戏,我们放在后续的章节放出来吧。

首先,一个很复古很经典的问题:把大象放进冰箱需要几步?

1. 打开冰箱门

2. 把大象放进去

3. 关上门

手势识别的过程也是这样:

1. 打开摄像头

2. 识别手势

3. 关闭摄像头

4. 本文结束哈哈哈

好了,进入正题吧!这次手势识别用到的python库主要有OpenCV(一个很强大很好用免费开源的计算机视觉工具)、NumPy(矩阵运算)。

打开摄像头:

我们在python中导入必要的模块

import cv2

import numpy as np

定义好摄像头

camera = cv2.VideoCapture(0) # 0代表本机自带摄像头

写一个循环,不停的从摄像头中取数据,摄像头会把每一帧画面都传回来

while camera.isOpened():

ret, frame = camera.read()# 读取摄像头的数据 frame为画面 ret 为标识

将图像初步处理并显示

frame = cv2.bilateralFilter(frame, 5, 50, 100) # 双边滤波

frame = cv2.flip(frame, 1) # 图片翻转 Y轴翻转

cv2.rectangle(frame, (int(cap_region_x_begin * frame.shape[1]), 0),

(frame.shape[1], int(cap_region_y_end * frame.shape[0])), (255, 0, 0), 2) # 画框框

cv2.imshow('original', frame)

这里我们首先使用了bilateralFilter-双边滤波,为什么要使用呢,双边滤波是减除噪声并边缘保留的图像平滑滤波器,在图像的每个像素强度值处被从附近的像素强度值的加权平均来取代,让图像去除噪声更平滑。

例:

原图

双边滤波后(图像平滑不少,边缘未改变)

然后将图片沿中心左右对称,因为摄像头返回的图像显示出来之后不是镜面的,我们需要翻转后,让我们看到的画面像镜子一样。

镜面翻转后

之后在画面的右上角画了一个矩形,为什么要这样呢,因为我们最后只在矩形框内拾取,矩形外的画面不会进行检测识别,说的简单粗暴一点,矩形框就是我们玩游戏用的操作空间。

如图:

最后,我们用cv2.imshow()函数将画面显示出来。

2. 手势检测识别

在OpenCV中,它已经帮我们封装好了一个动态运动物体检测的函数:BackgroudSubtractorMOG2()。

这个方法的原理就是通过混合高斯分布对背景图像建模,然后做图像比对,最后找出动态运动物体,数学公式推到什么的太长,有兴趣自己找找论文。

它的算法原理用最简单粗暴的话来说,可以理解为:背景是不变的,首先对背景图像的前200帧每一个像素点建模,如果新读入的图像中某处像素点与背景模型做匹配,如果存在与新像素匹配的单模型,就认为该像素点是背景,然后提升该点处模型的权重,如果匹配未找到,该像素则认定为前景。

前景提取:

首先我们建立背景模型:

bgModel = cv2.createBackgroundSubtractorMOG2(50, bgSubThreshold)

然后提取前景:

fgmask = bgModel.apply(frame) # 提取前景

kernel = np.ones((3, 3), np.uint8)

fgmask = cv2.erode(fgmask, kernel, iterations=1) # 腐蚀

res = cv2.bitwise_and(frame, frame, mask=fgmask) # 和运算

用背景模型和新读入的图像做比对(apply函数)。

然后定义一个3x3的kernel核,把前景图像做腐蚀操作。腐蚀的作用主要用作于一些去除噪声、弱化或分割图像之间的半岛型连接,腐蚀的方法其实就是用卷积核去图像上进行卷积操作。

腐蚀前前景图

腐蚀之后前景图

最后再用图像和运算(就是相加)来得到原图中的前景,再提取图像中某个区域,这里我们就把前景中手部提取出来了。

和运算后的前景

图像提取

前景处理:

截至目前,我们提取到了前景图像。接下来,我们要对前景图像进行处理。

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转成灰度图

blur = cv2.GaussianBlur(gray, (blurValue, blurValue), 0) # 高斯滤波 去噪

cv2.imshow(‘blur’, blur)

ret, thresh = cv2.threshold(blur, threshold, 255, cv2.THRESH_BINARY) # 二值化

cv2.imshow(‘ori’, thresh)

首先我们把彩色图转换成灰度图(cvtColor),彩色图像由RGB三通道组成,灰度图只有单通道,灰度图是不是有种小时候家里黄河黑白电视机的感觉,彩色图就是现在的大彩电。

灰度图(很明显,有很多噪声)

然后再次进行高斯滤波,去除噪声。

高斯滤波去噪()

最后再将图像二值化,就是将图像的所有像素点转换成0/1两种数值,这才是真正意义上的黑白图。

二值化

手势识别:

现在我们已经完成了视频中手部的图像提取与处理,接下来,就是要对手势进行判断了。

判断的方法由很多种:1.训练机器学习模型 2.特征法判断,训练模型在后面的文章中会详细讲解,尽情期待,今天我们就用最传统的特征法来判断吧。

首先我们用findContours()函数来拟合图像中的外轮廓,传进来的图像是二值化图像。

_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 拟合轮廓

拟合出轮廓之后,我们可以在面积最大的轮廓中寻找凸包,就是这个轮廓凸出的地方,比如三角形的顶点等等。

for i in range(length): # 找到面积最大的轮廓

res = contours[ci]

hull = cv2.convexHull(res) # 寻找凸包,就是凸出来的点

drawing = np.zeros(img.shape, np.uint8)

cv2.drawContours(drawing, [res], 0, (0, 255, 0), 2) # 画出轮廓

cv2.drawContours(drawing, [hull], 0, (0, 0, 255), 3)

现在我们已经可以找到轮廓凸包处的位置和手部的轮廓了,并在屏幕上已经用线条画出来了,接下来,我们就要检测当前的手势是什么了。

defects = cv2.convexityDefects(res, hull) # 凸缺陷检测

凸缺陷其实就是对象上的任何凹陷,找到凹陷之后,经过计算,我们就可以得到我们手指窝(不知道这样描述的对不对)的位置了。通常,我们五指自然张开,每两个相邻指头的夹角不会超过90°(自然张开!,自然张开!,自然张开!,重要的事说三遍)。

我们判断凹陷部位凸点处的夹角,如果小于90°,就认定为手指窝。然后根据手指窝的数量来判断当前的手势。

cnt = 0

for i in range(defects.shape[0]): # calculate the angle

s, e, f, d = defects[i][0]

start = tuple(res[s][0])

end = tuple(res[e][0])

far = tuple(res[f][0])

a = math.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)

b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)

c = math.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)

angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) # cosine theorem

if angle <= math.pi / 2: # angle less than 90 degree, treat as fingers

cnt += 1

cv2.circle(drawing, far, 8, [211, 84, 0], -1)

这里,cnt就是手指窝的个数,根据手指窝的数量,就可以判断当前手势:0: 握拳、 1:伸出两根手指。。。。

手势

手势识别判定就到这里了,控制游戏的话,代码如下:

if cnt == 2:

our_plane.move_up()

elif cnt == 0:

our_plane.move_down()

elif cnt == 4:

our_plane.move_left()

elif cnt == 3:

our_plane.move_right()

就是根据手势,执行控制函数,游戏不属于这篇文章的范畴,如有兴趣,后面会做分享。

这就是一个最基本最基础的计算机视觉应用了,这次手势识别使用最原始的图像处理方法来实现,也有一些问题值得思考:

如果摆出了rock的手势呢,用手指窝数量的方式不就识别不出来了?

如果背景也是持续在变化的呢?

如果光线变化呢?

这些问题都需要得到优化解决,不过作为欢乐的计算机视觉第一篇文章,就不讲太多了,后面会用计算机视觉领域中其他的算法来解决这些问题,敬请期待。

python手势控制游戏_欢乐的计算机视觉-隔空玩游戏(python手势控制飞机大战)相关推荐

  1. android h 游戏下载地址,Android h游戏_如何在Android手机上玩游戏

    最近人们喜欢在手机上玩游戏. 除了一些手机游戏(Android H游戏)之外安卓才可以玩的h,越来越多的朋友开始寻找Android手机游戏. 但是,有些人已经搜索了很长时间,还没有找到合适的游戏来玩. ...

  2. 新一代区块链游戏:超越炒作的NFT和玩游戏盈利

    为什么要用区块链和加密来制作游戏?区块链游戏无法吸引世界各地的游戏开发者和游戏玩家.许多人将区块链视为一个复杂的解决方案,以解决他们从未遇到过的问题,或者是一个扰乱他们商业模式的技术挫折.在本文中,我 ...

  3. 《有限与无限的游戏》第二章 没人能独自玩游戏:经典摘抄(1)

    没有人能独自一人玩游戏.一个人不成其为人,没有群体,便没有自我.我们并不是作为我们本身与他人有关系,相反,我们是与他人有关系的我们. 只有能够变化的,才能够持续下去,这是无限游戏的参与者所遵循的原则. ...

  4. 《有限与无限的游戏》第二章 没人能独自玩游戏:经典摘抄(3)

    将社会视为文化的一种,并不等同于要推翻甚至或改变社会,而只是去消除它感知的必要性.无限游戏的参与者有他们的规则,他们只是不忘记这一点:规则是对一致同意的一种表达,并不是对一致同意的要求. 社会由其边界 ...

  5. 如何设置计算机玩游戏不卡,win10电脑怎么设置玩游戏不卡?

    很多人说Win10系统游戏兼容性差,游戏体验差.其实这个说法很不正确.对于大多数游戏玩家来说,Win10是一个不错的游戏平台.不仅兼容性好,Xbox的原生加持也让玩家更享受.很多人不知道Win10中有 ...

  6. 计算机电脑怎么打开游戏,电脑玩游戏卡怎么办,详细教您电脑玩游戏卡怎么办...

    我们在玩游戏的时候要是遇到很卡的情况发生的话,那是真的很气的.因为正玩的好好的,就是因为电脑卡了,所以就造成游戏输了.这得多憋屈,所以小伙伴们,今天小编就告诉你们电脑玩游戏卡要怎么办. 其实小编也是一 ...

  7. python自己制作节奏大师游戏_使用pygame制作一个简单的游戏

    翻译自Will McGugan的<Beginning Game Development with Python and Pygame –From Novice to Professional&g ...

  8. python学英语游戏_美国大佬推荐,一边玩一边学Python编程,12个游戏轻松掌控Python...

    你还在坚持Python编程吗?如此枯燥的学习方式,靠自己的意志真的能坚持到最后吗? 放弃吧!与其辛苦的执着,不如看美国大佬推荐的Python编程闯关游戏,一边学编程一边玩游戏,以后连"吃鸡& ...

  9. 安卓ps模拟器_【千夜教你玩游戏】怎么使用模拟器刷任务苹果篇

    大家在玩游戏的时候,肯定经常碰到需要重复性的点点点才能完成的任务,比如<豪门>里面的友谊赛成就,一万胜场,人力去刷那是要死人的. 但活人总不能被尿憋死,变态的任务,自然需要取巧才能完成,很 ...

最新文章

  1. 2021-2027年中国智能门禁系统市场研究及前瞻分析报告
  2. shell 脚本 进行sqlite3初始化
  3. stm32f103 rtc 获取 日历 时钟
  4. 春节添彩 福州花卉市场现“买花潮”
  5. Spring Cloud(三) 熔断器Hystrix
  6. 订餐系统之同步饿了么商家订单
  7. 复习JavaScript随手记
  8. java实现抽奖游戏_Java实现游戏抽奖算法
  9. BZOJ 1007 水平可见直线
  10. iview上传文件案例
  11. 1、css引入的方式有哪些?_低氮燃烧技术都有哪些?
  12. Shell脚本学习-阶段九-数据库被攻击恢复
  13. POJ 1220 高精度进制转换
  14. javaweb超市仓库管理系统
  15. 一个很有意思的熊猫免疫器
  16. Android wpa_supplicant源码分析–扫描scan过程
  17. java ews appointment_EWS-JAVA-API的使用
  18. 赵桐正 php,php面向对象-封装性
  19. 【Unity3D】Unity3D技术栈
  20. 前端获取视频流并播放

热门文章

  1. python emit_PyQt正确使用emit()和pyqtSignal()
  2. 基于Kubernetes的微服务自动化运维
  3. 利用计算机求该货车,汽车理论习题 - 图文
  4. 为什么建议MySQL在2000W条左右记录分表
  5. 【Android音视频开发】【013】SurfaceView生命周期
  6. 天才只意味着终生不懈地努力——俄国化学家 门捷列耶夫
  7. DRGs 用sql语句如何查出医院超标准收费的一则案例
  8. 数据可视化作业(pivot_wider)(pivot_longer)
  9. 360浏览器 a标签跳转页面失效
  10. OpenCV完整教程专栏完整目录