
项目简介
近年来,随着虚拟现实技术和计算机图形学技术的迅猛发展,越来越多的体感游戏在市场上出现并受到欢迎。要让体感游戏具备良好的表现,就需要使用大量的传感器,甚至需要使用高性能的计算机和图形处理器。这不仅会增加游戏的成本,还会影响游戏的流畅性和操作体验。因此,如何在不使用传感器的情况下,实现高性能的体感游戏开发成为了一个颇具难度的问题。
为了解决这个问题,本文提出了基于关键点检测模型和摄像头的体感游戏开发方案。其中,PP-TinyPose 模型是飞桨推出的人体检测算法,它可以快速、准确地检测出人体关键点,从而实现人体的实时跟踪和动作捕捉。而通过飞桨推理部署工具 FastDeploy,可以将 PP-TinyPose 模型与推理引擎相结合,实现高效的推理部署,从而让游戏可以在仅使用 USB 摄像头的情况下,流畅地运行在一般电脑上。
当前已经开发完毕的小游戏包括
详细信息:
使用 FastDeploy 调用 PP-TinyPose 的优势:
import fastdeploy
import cv2
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)
后端
通过 PyQt5 创建前端页面,初始化需4个部分
游戏管理器初始化:用于创建游戏变量
设备初始化:开启摄像头
class Window(QWidget):
def __init__(self):
super().__init_
_()
self.game_obj = GameObject()
self.keypoints = None
self.initModel()
self.initCamera()
self.initClock()
self.initUI()
def initUI(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()
def initClock(self):
# 通过定时器读取数据
self.flush_clock = QTimer()
# 定义定时器,用于控制显示视频的帧率
self.flush_clock.start(
30)
# 定时器开始计时30ms,结果是每过30ms从摄像头中取一帧显示
self.flush_clock.timeout.connect(
self.updata_frame)
# 若定时器结束,show_frame()
def initCamera(self):
# 开启视频通道
self.camera_id =
0
# 为0时表示视频流来自摄像头
self.camera = cv2.VideoCapture()
# 视频流
self.camera.open(
self.camera_id)
def initModel(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')
在周期性调用函数中,需要完成以下操作体系
读取图片进行推理
展示画面
def inferModel(self):
# read pic from camera
_, 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
def updata_frame(self):
self.inferModel()
# infer and show
# update balance
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()
if
state:
# 游戏结束
QMessageBox.information(
self,
"Oops!",
"游戏结束!\n您的分数是" + str(score),
QMessageBox.Yes)
self.game_obj.__init_
_()
class GameObject(object):
def __init__(self):
self.x =
100
self.y =
100
self.score =
0
def update(self, keypoints):
self.x = keypoints[
9][
0]
self.y = keypoints[
9][
1]
def get_game_state(self):
game_status = False
if
self.x >
250:
game_status = True
return game_status,
self.score
def draw_canvas(self):
# draw balance
img = np.ones([
500,
500,
3]).astype(
'uint8') *
255
cv2.circle(img, (int(
self.x), int(
self.y)),
5, (
255,
0,
0),
3)
# draw circle
return img
if __name__ ==
'__main__':
app = QApplication(sys.argv)
ex = Window()
sys.
exit(app.exec_())