AI时代咱用脸玩“飞机大战”,PaddleHub让你秒变“脸控”游戏达人
Posted 飞桨PaddlePaddle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AI时代咱用脸玩“飞机大战”,PaddleHub让你秒变“脸控”游戏达人相关的知识,希望对你有一定的参考价值。
AI时代还拿着手机打飞机游戏是不是out了?飞桨PaddleHub带你体验不一样的游戏玩法。
从世界上第一款游戏诞生开始,电玩都需要依赖手柄和按键进行,无论是PC游戏,还是 XBOX 、PS 这类主机游戏,控制器和手柄都是不可缺少的。
直到2009年微软发布了第一代 Kinect,将人体检测作为游戏控制,彻底颠覆了游戏的单一操作,开创了解放双手的先河,使人机互动的理念更加彻底地展现出来。但是之后,2018 年微软彻底弃用了 Kinect 实在让人惋惜!
大众流行的游戏文化中,人机互动的主流方式还是离不开手柄,即使到了手机和Pad 横行的移动时代,大多数的主流游戏依然利用的是虚拟键盘和虚拟手柄的交互方式。
人类发展的动力其实很大一部分来自于人类“懒惰”的天性,所以对我而言,如果能通过更简单、自由的交互方式玩游戏,将是非常有意思的事情。虽然我们离脑机接口和思维控制还有很长的路要走,但是随着深度学习的发展,相信不久的将来,交互方式也会产生天翻地覆的变化。
基于此,我尝试做了人脸打飞机的游戏项目!
效果展示
实现方法
打飞机游戏的实现需要完成分如下三个步骤:
-
使用PaddleHub中的 facelandmarklocalization 模型实现头部运动监测。 -
使用Pygame实现打飞机游戏主体程序。(这里用了最简单易上手,通常用来做 Python 入门初体验的 Pygame) -
将头部运动监测模块加入游戏中。
-
安装飞桨。 -
安装Paddlehub。
pip install paddlehub
这里我使用的是自己初学 Python 时,用 Pygame 制作的打飞机游戏。素材上,无论图片、飞机模型还是背景音乐网上非常多,非常容易获取(因为是入门款嘛~)
pip install pygame
if bomb_num and event.key == K_SPACE:
bomb_sound_use.play()
bomb_num -= 1
key_pressed = pygame.key.get_pressed()
if key_pressed[K_w] or key_pressed[K_UP]:
myplane.move_up() # 飞机向上飞
elif key_pressed[K_s] or key_pressed[K_DOWN]:
myplane.move_down() # 飞机向下飞
elif key_pressed[K_a] or key_pressed[K_LEFT]:
myplane.move_left() # 飞机向左飞
elif key_pressed[K_d] or key_pressed[K_RIGHT]:
myplane.move_right() # 飞机向右飞
class MyFaceDetector(object):
"""
自定义人脸检测器
"""
def __init__(self):
self.module = hub.Module(name="ultra _light_fast _generic_face _detector_1mb_320")
self.alpha = 0.75
self.start_flag = 1
def face _detection(self, images, use_gpu=False, visualization=False):
# 使用GPU运行,use _gpu=True,并且在运行整个教程代码之前设置CUDA_VISIBLE_DEVICES环境变量
result = self.module.face _detection(images=images, use_gpu=use_gpu, visualization=visualization)
if not result[ 0][ 'data']:
return result
face = result[ 0][ 'data'][ 0]
if self.start_flag == 1:
self.left_s = result[ 0][ 'data'][ 0][ 'left']
self.right_s = result[ 0][ 'data'][ 0][ 'right']
self.top_s = result[ 0][ 'data'][ 0][ 'top']
self.bottom_s = result[ 0][ 'data'][ 0][ 'bottom']
self.start_flag = 0
else:
# 加权平均上一帧和当前帧人脸检测框位置,以稳定人脸检测框
self.left _s = self.alpha * self.left_s + (1 - self.alpha) * face['left']
self.right _s = self.alpha * self.right_s + (1 - self.alpha) * face['right']
self.top _s = self.alpha * self.top_s + (1 - self.alpha) * face['top']
self.bottom _s = self.alpha * self.bottom_s + (1 - self.alpha) * face['bottom']
result[ 0][ 'data'][ 0][ 'left'] = self.left_s
result[ 0][ 'data'][ 0][ 'right'] = self.right_s
result[ 0][ 'data'][ 0][ 'top'] = self.top_s
result[ 0][ 'data'][ 0][ 'bottom'] = self.bottom_s
return result
class HeadPostEstimation():
"""
头部姿态识别
"""
def __init__(self, face_detector=None):
self.module = hub.Module(name= "face_landmark_localization", face_detector_module=face_detector)
def get_face_landmark(self, image):
"""
预测人脸的68个关键点坐标
images(ndarray): 单张图片的像素数据
"""
try:
# 选择GPU运行,use_gpu=True,并且在运行整个教程代码之前设置CUDA_VISIBLE_DEVICES环境变量
res = self.module.keypoint_detection(images=[image], use_gpu= True)
return True, res[ 0][ 'data'][ 0]
except Exception as e:
logger.error( "Get face landmark localization failed! Exception: %s " % e)
return False, None
def get_lips_distance(self, face_landmark):
"""
从face_landmark_localization的检测结果中查看上下嘴唇的距离
"""
lips_points = np.array([
face_landmark[ 52], face_landmark[ 58]
], dtype= 'float')
head_points = np.array([
face_landmark[ 25], face_landmark[ 8]
], dtype= 'float')
lips_distance = np.sum(np.square(lips_points[ 0] - lips_points[ 1]))
head_distance = np.sum(np.square(head_points[ 0] - head_points[ 1]))
relative_distance = lips_distance / head_distance
return relative_distance
def get_nose_distance(self,face_landmark):
"""
从face_landmark_localization的检测结果中获得鼻子的位置,以此判断头部运动
"""
nose_point = np.array([
face_landmark[ 31]
], dtype= 'float')
cheek_points = np.array([
face_landmark[ 3], face_landmark[ 15]
], dtype= 'float')
left_distance = np.sum(np.square(nose_point[ 0] - cheek_points[ 0]))
right_distance = np.sum(np.square(nose_point[ 0] - cheek_points[ 1]))
nose_position_h = left_distance/(left_distance+right_distance)
nose_position_v = nose_point[ 0][ 1]-cheek_points[ 0][ 1] # 获得鼻子和脸颊定位点的高度相对值,以此作为抬头/低头的判断
return nose_position_h, nose_position_v
def classify_pose(self, video):
"""
video 表示不断产生图片的生成器
"""
for index, img in enumerate(video(), start= 1):
self.img_size = img.shape
success, face_landmark = self.get_face_landmark(img)
if not success:
logger.info( "Get face landmark localization failed! Please check your image!")
continue
if not success:
logger.info( "Get rotation and translation vectors failed!")
continue
# 计算嘴唇距离
lips_distance = self.get_lips_distance(face_landmark)
# 计算鼻子左右位置
nose_position_h, nose_position_v = self.get_nose_distance(face_landmark)
# 转换成摄像头可显示的格式
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 本地显示预测视频框,AIStudio项目不支持显示视频框
#cv2.imshow('Pose Estimation', img_rgb)
return nose_position_h, nose_position_v, lips_distance
# 使用头部控制飞机
face_detector = MyFaceDetector()
# 打开摄像头
capture = cv2.VideoCapture( 0)
def generate_image():
while True:
# frame_rgb即视频的一帧数据
ret, frame_rgb = capture.read()
# 按q键即可退出
if cv2.waitKey( 1) & 0xFF == ord( 'q'):
break
if frame_rgb is None:
break
frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
yield frame_bgr
capture.release()
cv2.destroyAllWindows()
head_post = HeadPostEstimation(face_detector)
# 获取头部运动数据,并控制飞机
nose_position_h, nose_position_v, lips_distance = head_post.classify_pose(video=generate_image)
#print(nose_position_h, nose_position_v, lips_distance) # 该语句用来查看评估参数如何设计
if nose_position_h < 0.22:
myplane.move_left() # 由于摄像头演示中镜面关系,实际使用中请设置为myplane.move_right()
elif nose_position_h > 0.48:
myplane.move_right() # 由于摄像头演示中镜面关系,实际使用中请设置为myplane.move_left()
elif nose_position_v < -40:
myplane.move_up()
elif nose_position_v > -25:
myplane.move_down()
# 张嘴就是炸弹,dis_control<0.045 为闭嘴
if lips_distance < 0.045:
flag = 1
if bomb_num and lips_distance > 0.055 and flag == 1:
flag = 0
bomb_sound_use.play()
bomb_num -= 1
共同探讨
在实现过程中有几个下问题,还需要进一步研究和探讨:
由于调整参数的时候,是基于我自己的脸进行的,所以不知道别人的脸控制游戏时精度会不会有影响。
原来想再做一版人脸和飞机重叠的效果呈现,但是在 pygame 的框架下还没折腾出来怎么实现。
摄像头视角和人类视角是镜面关系,所以为了拍摄视频我调整成为了左右相反,实际中需要对调过来。
未来可期
未来可期
第二版完成后,本来想做个第三版,利用 PaddleHub 的人体骨骼监测模块,实现通过人体运动来控制飞机,但是这个模块目前还没有办法直接接入实时的视频画面,所以作罢了。
END
以上是关于AI时代咱用脸玩“飞机大战”,PaddleHub让你秒变“脸控”游戏达人的主要内容,如果未能解决你的问题,请参考以下文章