去后厂村开游戏厅吧!基于PP-TinyPose的简易体感游戏开发框架

01 项目简介

近年来,跟着虚拟现实技能和核算机图形学技能的迅猛发展,越来越多的体感游戏在市场上呈现并遭到欢迎。要让体感游戏具备良好的表现,就需求运用很多的传感器,乃至需求运用高功用的核算机和图形处理器。这不只会增加游戏的本钱,还会影响游戏的流畅性和操作体验。因此,如安在不运用传感器的情况下,完成高功用的体感游戏开发成为了一个颇具难度的问题。

为了处理这个问题,本文提出了依据要害点检测模型和摄像头的体感游戏开发计划。其间,PP-TinyPose 模型是飞桨推出的人体检测算法,它能够快速、精确地检测出人体要害点,然后完成人体的实时跟踪和动作捕捉。而经过飞桨推理布置东西 FastDeploy,能够将 PP-TinyPose 模型与推理引擎相结合,完成高效的推理布置,然后让游戏能够在仅运用 USB 摄像头的情况下,流畅地运转在一般电脑上。

当时现已开发结束的小游戏包含

依据 pp-tinypose 的体感贪吃蛇游戏 aistudio.baidu.com/aistudio/pr…

依据 pp-tinypose 的体感飙车避障游戏aistudio.baidu.com/aistudio/pr…

本文综合了上述项目的开发经历,介绍了一个简易的体感游戏开发结构,能够在该结构的基础上轻松自制依据摄像头和要害点检测模型的体感小游戏。

  • 源码链接:

Liyulingyue/PaddleGames: Some games based on paddlepaddle (github.com)

02 项目运用模型及东西

PP-TinyPose 模型

PP-TinyPose 模型是飞桨方针检测套件 PaddleDetection 针对移动端设备优化的实时要害点检测模型,其能够流畅地在移动端设备上履行多人姿势估计使命。结合轻量化检测网络 PP-PicoDet 能够快速高效地完成检测使命,并应用在手机等核算才能有限的边缘设备上。

  • 详细信息:

github.com/PaddlePaddl…

FastDeploy 推理布置东西

FastDeploy 是飞桨推出的一款全场景、易用灵活、极致高效的AI推理布置东西,供给很多的开箱即用的布置体验。现在,FastDeploy 支持的模型包含了物体检测、字符识别、NLP、Stable Diffusion 文图生成等。内置的推理后端包含了 TensorRT、OpenVINO 等。

运用 FastDep loy 调用 PP-TinyPose 的优势:

  • 开箱即用,调用快捷

经过下述三行代码即可完成推理进程,无需对数据进行预处理。

importfastdeploy
importcv2
model=fastdeploy.vision.keypointdetection.PPTinyPose('PP_TinyPose_128x96_infer/model.pdmodel','PP_TinyPose_128x96_infer/model.pdiparams','PP_TinyPose_128x96_infer/infer_cfg.yml')
img=cv2.imread('test.jpg')
result=model.predict(img)
  • 推理效率更快

PaddleDetection 仓库已供给了功用优秀的的预练习模型。在此基础上, FastDeploy 不只供给了开箱即用的 API ,对运算进程进行了一定的优化,然后提高了模型推理的实时性,有利于在线解算。

03 项目开发结构

依据 PyQt5 的通用简易体感游戏开发结构

去后厂村开游戏厅吧!基于PP-TinyPose的简易体感游戏开发框架
游戏结构运转逻辑示例图

一个简略的游戏结构能够没有任何关卡,乃至没有得分,只担任游戏的环境运营即可。例如贪吃蛇游戏,能够不设关卡,一向进行,直到蛇的身体充满整个屏幕。这个最简略的逻辑结构总共需求预备两个部分的内容。

  • 前端

如上图(右)所示,主要担任初始化页面信息,周期性地调用摄像头数据,而且推理,将推理成果传给后端,并获取当时的游戏画面。

  • 后端

如上图(左)所示,能够声明为一个类,在游戏开端时会创立这个类,而且周期性地调用更新函数,依据要害点信息更新游戏的变量,而且依据当时的游戏数据,制作游戏画面。

这儿分开来表述只是为了后续保护便利,实际上完全能够混在一同。而且上图的表述更为偏向人而非代码的逻辑,所以会和后续的代码介绍有些出入。下面分别对游戏开发结构的前后端代码进行介绍。

前端

前端主要分为两个部分:初始化和周期性调用函数。

经过 PyQt5 创立前端页面,初始化需4个部分

  • 游戏管理器初始化:用于创立游戏变量
  • 界面初始化:用于界说用于展现的前端页面组件
  • 计时器初始化:初始一次,就会周期性调用指定的函数
  • 设备初始化:敞开摄像头
classWindow(QWidget):
def__init__(self):
super().__init__()
self.game_obj=GameObject()
self.keypoints=None
self.initModel()
self.initCamera()
self.initClock()
self.initUI()
definitUI(self):
grid=QGridLayout()
self.setLayout(grid)
self.Game_Box=QLabel()#界说显现视频的Label
self.Game_Box.setFixedSize(500,500)
grid.addWidget(self.Game_Box,0,0,20,20)
self.Game_Box.setMouseTracking(True)
self.Pred_Box=QLabel()#界说显现视频的Label
self.Pred_Box.setFixedSize(500,500)
grid.addWidget(self.Pred_Box,0,20,20,20)
self.setWindowTitle('test')
self.show()
definitClock(self):
#经过定时器读取数据
self.flush_clock=QTimer()#界说定时器,用于操控显现视频的帧率
self.flush_clock.start(30)#定时器开端计时30ms,成果是每过30ms从摄像头中取一帧显现
self.flush_clock.timeout.connect(self.updata_frame)#若定时器结束,show_frame()
definitCamera(self):
#敞开视频通道
self.camera_id=0#为0时表示视频流来自摄像头
self.camera=cv2.VideoCapture()#视频流
self.camera.open(self.camera_id)
definitModel(self):
self.model=fastdeploy.vision.keypointdetection.PPTinyPose('../../Models/PP_TinyPose_128x96_infer/model.pdmodel','../../Models/PP_TinyPose_128x96_infer/model.pdiparams','../../Models/PP_TinyPose_128x96_infer/infer_cfg.yml')

在周期性调用函数中,需求完成以下操作系统

  • 读取图片进行推理
  • 将推理信息传递给游戏管理器
  • 获取游戏画面
  • 展现画面

需求留意的是,这儿为了拆解功用,把更新数据和展现画面分开了。代码如下:

definferModel(self):
#readpicfromcamera
_,img=self.camera.read()#从视频流中读取
img=cv2.flip(img,1)#摄像头画面回转
img2=cv2.resize(img,(500,500))#把读到的帧的巨细重新设置为640x480
showPic=QImage(img2,img2.shape[1],img2.shape[0],QImage.Format_BGR888)
self.Pred_Box.setPixmap(QPixmap.fromImage(showPic))
try:
result=self.model.predict(img)
self.keypoints=result.keypoints
showPic=QImage(img,img.shape[1],img.shape[0],QImage.Format_BGR888)
self.Pred_Box.setPixmap(QPixmap.fromImage(showPic))
except:
pass
defupdata_frame(self):
self.inferModel()#inferandshow
#updatebalance
self.game_obj.update(self.keypoints)
#制作游戏窗口
img=self.game_obj.draw_canvas()
showPic=QImage(img,500,500,QImage.Format_BGR888)
self.Game_Box.setPixmap(QPixmap.fromImage(showPic))
#游戏结束
state,score=self.game_obj.get_game_state()
ifstate:#游戏结束
QMessageBox.information(self,
"Oops!",
"游戏结束!\n您的分数是"+str(score),
QMessageBox.Yes)
self.game_obj.__init__()

后端

后端主要分为两个部分,初始化和更新信息。初始化内容由游戏信息决定,比方我们当时想要写一个能够跟着手部移动而移动的游戏,则如下所示,只需求界说 self.x、self.y、self.score 用于保存坐标点信息和得分即可。

classGameObject(object):
def__init__(self):
self.x=100
self.y=100
self.score=0

信息更新阶段也是跟着游戏内容决定的,例如关于一个能够跟着手部移动而移动的游戏,只需求每个周期依据传入的 keypoints 更新对应的坐标值即可。便利起见,能够将功用拆解,例如专门运用一个函数制作画面或判别游戏状态。例如实例中,如果坐标值超过 250 即判别为错误。

defupdate(self,keypoints):
self.x=keypoints[9][0]
self.y=keypoints[9][1]
defget_game_state(self):
game_status=False
ifself.x>250:
game_status=True
returngame_status,self.score
defdraw_canvas(self):
#drawbalance
img=np.ones([500,500,3]).astype('uint8')*255
cv2.circle(img,(int(self.x),int(self.y)),5,(255,0,0),3)#drawcircle
returnimg

运转

界说好全部后,只需求在主函数中发动 PyQt5 即可。

if__name__=='__main__':
app=QApplication(sys.argv)
ex=Window()
sys.exit(app.exec_())

依据上述结构,在开发一个简易的体感小游戏时,只需求在后端代码中更新所需求逻辑即可,不需求对前端内容进行大改。

04 总结

本文简略介绍如何运用飞桨推理布置东西 FastDeploy 布置飞桨方针检测套件 PaddleDetection 中的 PP-TinyPose 模型进行体感游戏开发,运用的前端结构为 PyQt5 。本文运用的示例较为简略,更多示例信息能够参阅Liyulingyue/PaddleGames: Some games based on paddlepaddle (github.com),其间不只有本文介绍的 demo 的源代码,还有两个基本开发结束的小游戏:体感贪吃蛇和体感飙车游戏。能够参阅这两个项目代码定制化地开发小游戏~

同样,也欢迎大家提交代码到Liyulingyue/PaddleGames: Some games based on paddlepaddle (github.com),一同改善这个 Demo 或者共同开发出更多有趣的小游戏!