首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

​【壹零学院】用PoseNet人体姿态估计实现动作监测

在目前的人体部位关键点众多视觉检测模型中,PoseNet人体姿态估计模块功能较强,它能够通过检测关键身体关节等位置来快速估计图像(或视频)中的人体姿态。与之前我们使用MediaPipe对人体的33个关键点进行检测制作的简易健身计数器类似,PoseNet模型检测的人体关键点(KeyPoints)数目是17个(如图1),在Python编程时进行调用及相关的计算方式基本类似,比如制作实现一个运动拉伸动作的持续时间监测模块。 

1.库模块的导入、函数的自定义及变量的初始化

从《用MediaPipe视觉识别制作健身计数器》一文中的Sports_Counter.py程序中复制出point_3_angle(p1,p2,p3)函数的自定义代码部分,准备用来计算平面内三个关键点形成的两个矢量夹角大小。建立变量pass_time并赋值为“0”,作用是进行运动热身动作就位后持续时间的记录;建立变量file_model并赋值为“"posenet_mobilenet_v1_100_257x257_multi_kpt_stripped.tflite"”,建立变量interpreter并赋值为“tflite.Interpreter(model_path=file_model)”,再通过语句“interpreter.allocate_tensors()”,实现预训练模型文件的读取和加载。建立变量input_details和output_details,

分别赋值为“interpreter.get_input_details()”和“interpreter.get_output_details()”,作用是进行输入与输出数据的获取,其中包括若干多维数组矩阵的特征位置及各个关键点坐标的二维偏移量等数据。建立变量height和width,分别赋值为“input_details[0]['shape'][1]”和“input_details[0]['shape'][2]”,作用是从input_details中进行PoseNet格式要求的图像高度与宽度的获取;再建立变量cap并赋值为“cv2.VideoCapture(0)”,作用是打开摄像头(如图2)。 

2.“while True:”循环部分

语句“ret,img = cap.read()”的作用是读取摄像头监测的每一帧画面,语句“im_H,im_W,_ = np.shape(img)”的作用是获取每帧画面的高度和宽度值;建立变量img_rgb并赋值为“cv2.cvtColor(img,cv2.COLOR_BGR2RGB)”,作用是进行BGR到RGB的图像模式转换;建立变量img_resized并赋值为“cv2.resize(img_rgb,(width,height))”,作用是按照PoseNet的网络输入要求进行画面大小的缩放;建立变量input_data并赋值为“np.expand_dims(img_resized,axis=0) input_data = np.expand_dims(img_resized,axis=0)”,作用是进行数据维度的扩张,然后通过语句“(np.float32(input_data)-128)/128”进行尺度的计算缩放——即“像素值的正则化”,

将数据值限制在(-1,+1)之间;语句“interpreter.set_tensor(input_details[0]['index'],input_data)”和“interpreter.invoke()”的作用分别是将数据输入至PoseNet网络和关键点的检测;建立变量heatmaps并赋值为“interpreter.get_tensor(output_details[0]['index'])[0]”,作用是获取置信度信息(其中存储的是特征点数据);建立变量offsets并赋值为“interpreter.get_tensor(output_details[1]['index'])[0]”,作用是获取特征点的位置信息(二维坐标偏移量);语句“h_output,w_output,n_KeyPoints= np.shape(heatmaps)”的作用是进行heatmaps的高度、宽度及关键点数目的获取;建立变量keypoints并赋值为“[]”空列表,作用是存储关键点的位置数据;建立变量score并赋值为“0”,作用是将关键点的置信度设置为0。 

在“for i in range(n_KeyPoints):”循环结构中对每个关键点进行遍历,先是建立变量heatmap并赋值为“heatmaps[:,:,i]”,遍历每一个heatmap;建立变量max_index和max_val,

分别赋值为“np.where(heatmap==np.max(heatmap))”和“np.max(heatmap)”,实现对最大值及对应的位置值的获取;建立变量offset_x和offset_y,分别赋值为“offsets[max_index[0],max_index[1],i+n_KeyPoints]”和

“offsets[max_index[0],max_index[1],i]”,作用是获取x和y两个坐标方向各自的偏移量;建立变量pos_x和pos_y,分别赋值为“max_index[1]/(w_output-1)*width + offset_x”和“max_index[0]/(h_output-1)*height + offset_y”,作用是计算出经过偏移量修正后的坐标数据(PoseNet的输入图像);建立变量pos_x和pos_y,分别赋值为“pos_x/(width-1)*im_W”和“pos_y/(height-1)*im_H”,作用是计算出源图像中的二维坐标数据;通过语句“keypoints.append([int(pos_x[0]),int(pos_y[0])])”,将每个关键点的位置数据追加至之前建立的空列表keypoints中;建立变量score并赋值为“score +1/(np.exp(-max_val)+1)”,作用是计算出每一个关键点的置信度。 

通过语句“score=score/n_KeyPoints”进行平均值的计算,得到最终的置信度数据;接下来对变量score的置信度值进行判断,若在0.5以上则认定为有效,进行17个关键点的描绘及左右臂、左右腿等相关联点的“骨架”连线,使用的是OpenCV中的circle()和polylines()命令,不再一一赘述。

运动拉伸动作是否做到位的判断规则比较灵活,比如较为常见的“双腿呈八字直立时双手轮流抓握对侧的小腿”动作,对照图1所标注的各关键点序号,先设置好双腿的直立状态的判定,建立变量left_knee和right_knee,分别赋值为“point_3_angle(keypoints[11],keypoints[13],keypoints[15])”

和“point_3_angle(keypoints[12],keypoints[14],keypoints[16])”,通过调用point_3_angle(p1,p2,p3)函数计算出左右膝关节的弯曲角度;建立变量left_shank和right_shank,分别赋值为“(keypoints[13][1]+keypoints[15][1])/2”和“(keypoints[14][1]+keypoints[16][1])/2”,作用是分别获取左右小腿中间位置的纵坐标y值;接着构建条件判断语句“if left_knee>=160 and right_knee>=160 and keypoints[9][1]>=right_shank or keypoints[10][1]>=left_shank:”,其中的左右膝关节弯曲角度设置的有效阈值为160度(而不是表示理想直立状态的180度),目的是减小动作实现难度,“keypoints[9][1]”和“keypoints[10][1]”则对应左右手腕的纵坐标y值,分别与右侧和左侧的小腿中间位置y值进行比较。当动作被判定为有效时,开始执行语句“time.sleep(1)”和“pass_time += 1”进行持续时间的累加计时,并通过两个cv2.putText()语句将相关的信息显示在窗口画面上。 

最后,仍是进行热键退出响应设置和关闭摄像头释放资源等常规操作(如图3)。

3.程序的运行测试

将程序保存为PoseNet_PassTime.py,按F5键进行测试。在摄像头前方做运动拉伸动作,注意每次动作到位后要尽量保持,程序就会在监测到有效动作后进行持续时间的计时,结果显示在屏幕画面的右上角位置(如图4),效果非常不错,大家不妨一试。 

邮发代号:77-19

单价:8元,年价:408元

编辑|张毅

审核|吴新

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OK0Yap9stY87HD0oFA66ozHQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券