基于mediapipe的姿态识别和简单行为识别

您所在的位置:网站首页 npfromfile函数 基于mediapipe的姿态识别和简单行为识别

基于mediapipe的姿态识别和简单行为识别

2023-04-13 01:44| 来源: 网络整理| 查看: 265

文章目录 学习目标 1、可以识别到人体姿态关键点 2、可以通过角度识别的方法识别到人体的动作(自定义) 一、mediapipe的安装 二、使用mediapipe检测关键点 1、mediapipe的介绍 2、使用mediapipe检测人体 (0)检测前的准备工作 (1)检测图片 (2)检测视频 三、使用mediapipe-BlazePose检测自定义简单行为 1、原理介绍 2、实现过程 学习目标 1、可以识别到人体姿态关键点 2、可以通过角度识别的方法识别到人体的动作(自定义)

源码地址:🚀🚀🚀🚀

一、mediapipe的安装

其实这部分很简单,直接在windows命令行的环境下

pip install mediepipe

就可以啦

二、使用mediapipe检测关键点 1、mediapipe的介绍

Mediapipe是一个用于构建机器学习管道的框架,用户处理视频、音频等时间序列数据。这个跨平台框架适用于桌面/服务器、Android、ios和各类嵌入式设备。 目前mediapipe包含16个solutions,分别为

人脸检测 Face Mesh 虹膜 手 姿态 人体 人物分割 头发分割 目标检测 Box Tracking instant Motion Tracking 3D目标检测 特征匹配 AutoFlip MediaSequence YouTuBe_8M

![在这里插入图片描述](https://i3.wp.com/i3.wp.com/i3.wp.com/img-blog.csdnimg.cn/1fbcd4d624b14681995fdc90882f2006.png

总的来说,mediapipe是一个很好的库,可以解决我们处理ML项目中面临的大部分麻烦,而且很适合做行为识别方向的小伙伴练手使用。

2、使用mediapipe检测人体

这里仅使用mediapipe关于人体识别的方法(solution),谷歌官方将这种人体姿态识别的方法叫做Blazepose。

(0)检测前的准备工作 '''导入一些基本的库''' import cv2 import mediapipe as mp import time from tqdm import tqdm import numpy as np from PIL import Image, ImageFont, ImageDraw # ------------------------------------------------ # mediapipe的初始化 # 这一步是必须的,因为要使用到以下定义的几个类 # ------------------------------------------------ mp_pose = mp.solutions.pose mp_drawing = mp.solutions.drawing_utils pose = mp_pose.Pose(static_image_mode=True) (1)检测图片 def process_frame(img): start_time = time.time() h, w = img.shape[0], img.shape[1] # 高和宽 # 调整字体 tl = round(0.005 * (img.shape[0] + img.shape[1]) / 2) + 1 tf = max(tl-1, 1) # BRG-->RGB img_RGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 将RGB图像输入模型,获取 关键点 预测结果 results = pose.process(img_RGB) keypoints = ['' for i in range(33)] if results.pose_landmarks: mp_drawing.draw_landmarks(img, results.pose_landmarks, mp_pose.POSE_CONNECTIONS) for i in range(33): cx = int(results.pose_landmarks.landmark[i].x * w) cy = int(results.pose_landmarks.landmark[i].y * h) keypoints[i] = (cx, cy) # 得到最终的33个关键点 else: print("NO PERSON") struction = "NO PERSON" img = cv2.putText(img, struction, (25, 100), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (255, 255, 0), 6) end_time = time.time() process_time = end_time - start_time # 图片关键点预测时间 fps = 1 / process_time # 帧率 colors = [[random.randint(0,255) for _ in range(3)] for _ in range(33)] radius = [random.randint(8,15) for _ in range(33)] for i in range(33): cx, cy = keypoints[i] #if i in range(33): img = cv2.circle(img, (cx, cy), radius[i], colors[i], -1) '''str_pose = get_pos(keypoints) #获取姿态 cv2.putText(img, "POSE-{}".format(str_pose), (12, 100), cv2.FONT_HERSHEY_TRIPLEX, tl / 3, (255, 0, 0), thickness=tf)''' cv2.putText(img, "FPS-{}".format(str(int(fps))), (12, 100), cv2.FONT_HERSHEY_SIMPLEX, tl/3, (255, 255, 0),thickness=tf) return img

如果需要执行代码,则在文末的主函数中使用

if __name__ == '__main__': # 读取图片 img0 = cv2.imread("./data/outImage--20.jpg") # 因为有中文路径,所以加上此行 image = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), -1) img = image.copy() # 检测关键点,得到的image是检测过后的图片 image = process_frame(img) # 使用matplotlib画图 fig, axes = plt.subplots(nrows=1, ncols=2) axes[0].imshow(img0[:,:,::-1]) axes[0].set_title("原图") axes[1].imshow(image[:,:,::-1]) axes[1].set_title("检测并可视化后的图片") plt.rcParams["font.sans-serif"] = ['SimHei'] plt.rcParams["axes.unicode_minus"] = False plt.show() fig.savefig("./data/out.png")

最后附上检测效果。

(2)检测视频

任何不涉及3D卷积的机器视觉方法,检测视频其实就是检测图片。因为视频是由多帧图片融合得来的。 比如说一个30帧的视频,那么它的每一秒钟,就是由30张图片叠加而成。 将这些分割出的图片分别进行检测,最后将检测的图片进行融合,得到的就是检测后的视频。 有了这个依据,我们就可以把图片检测过程写成一个函数,在视频的每一帧中调用这个函数就可以啦 一般使用opencv库将视频分解为图片帧的形式,示例代码如下:

def video2image(videoPath="./video/demo1.mp4", image_dir="./image"): '''videoPath是视频路径, image_dir是图片保存的文件夹路径''' cap = cv2.VideoCapture(videoPath) frame_count = 0 while(cap.isOpened()): success,frame = cap.read() if not success: break frame_count += 1 print("视频总帧数:", frame_count) cap.release() cap = cv2.VideoCapture(videoPath) count = 0 with tqdm(total=frame_count-1) as pbar: try: while(cap.isOpened()): success, frame = cap.read() if not success: break #处理帧 try: if count % 20 == 0: cv2.imwrite("{}/outImage--{}.jpg".format(image_dir, count), frame) except: print("error") pass if success == True: pbar.update(1) count+=1 except: print("中途中断") pass cv2.destroyAllWindows() cap.release() print("视频已经处理结束,进行下一步操作!!!")

那么落实到本文想要实现的功能上,就可以在视频分解出的帧后面加上图片检测函数。 代码如下所示:

def process_video(video_path="./Data.mp4"): video_flag = False cap = cv2.VideoCapture(video_path) out_path = "./out_Data.mp4" print("视频开始处理……") frame_count = 0 while (cap.isOpened()): success, frame = cap.read() frame_count += 1 if not success: break cap.release() print("总帧数 = ", frame_count) cap = cv2.VideoCapture(video_path) if video_flag == False: frame_size = cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT) #处理图像的尺寸。 fourcc = cv2.VideoWriter_fourcc(*'mp4v') #保存视频文件的格式为mp4 fps = cap.get(cv2.CAP_PROP_FPS) out = cv2.VideoWriter(out_path, fourcc, fps, (int(frame_size[0]),int(frame_size[1])), ) #输出图像的句柄 with tqdm(total=frame_count-1) as pbar: try: while cap.isOpened(): success, frame = cap.read() if success: pbar.update(1) frame = process_frame(frame) # frame就是视频截取的帧,process_frame表示对其检测。 cv2.namedWindow("frame", cv2.WINDOW_NORMAL) cv2.imshow("frame", frame) out.write(frame) if cv2.waitKey(1) == 27: break else: break except: print("中途中断") pass cap.release() cv2.destroyAllWindows() out.release() print("视频已保存至", out_path)

有了视频的代码,那么就可以在主函数中对其进行调用,可视化效果就不展示了。

三、使用mediapipe-BlazePose检测自定义简单行为 1、原理介绍

将Mediapipe用于行为检测是比较复杂的一件事;如果这样做,那么行为检测的精度就完全取决于Mediapipe关键点的检测精度。 于是可以根据下图中人的关节夹角来对人的位姿进行检测。 如举手的时候,大臂与水平方向夹角是一定大于0度的。 叉腰的时候,双手垂下,大臂与小臂的夹角大于60度小于120度 那么这样就可以完成一些基本动作的分类。 我这里只列出几种比较简单的。 (1)举双手(2)举左手(3)举右手(4)叉腰(5)比三角形 先看一下效果图

2、实现过程

首先要知道,由坐标求得矢量的公式,其实就是两个坐标相减。 那么求两个矢量之间的夹角公式: 请添加图片描述 那么到代码中就是:

v1 = (x1, y1) - (x2, y2) v2 = (x0, y0) - (x2, y2) def get_angle(v1, v2): angle = np.dot(v1, v2) / (np.sqrt(np.sum(v1 * v1)) * np.sqrt(np.sum(v2 * v2))) angle = np.arccos(angle) / 3.14 * 180 cross = v2[0] * v1[1] - v2[1] * v1[0] if cross < 0: angle = - angle return angle

这样就可以得到两个矢量的夹角。 之后,就可以通过夹角对行为进行判断,这里的规则是

举双手 左手矢量小于0右手矢量夹角大于0 举左手 左手矢量小于0右手矢量小于0 举右手 左手矢量大于0右手矢量大于0 比三角形 举双手的同时,大臂与小臂的夹角小于120度 正常 左手矢量大于0右手矢量夹角小于0 叉腰 正常情况下,左手肘夹角小于120度,右手肘夹角也小于0

给出的代码示例如下:

def get_pos(keypoints): str_pose = "" # 计算左臂与水平方向的夹角 keypoints = np.array(keypoints) v1 = keypoints[12] - keypoints[11] v2 = keypoints[13] - keypoints[11] angle_left_arm = get_angle(v1, v2) #计算右臂与水平方向的夹角 v1 = keypoints[11] - keypoints[12] v2 = keypoints[14] - keypoints[12] angle_right_arm = get_angle(v1, v2) #计算左肘的夹角 v1 = keypoints[11] - keypoints[13] v2 = keypoints[15] - keypoints[13] angle_left_elow = get_angle(v1, v2) # 计算右肘的夹角 v1 = keypoints[12] - keypoints[14] v2 = keypoints[16] - keypoints[14] angle_right_elow = get_angle(v1, v2) if angle_left_arm0: str_pose = "RIGHT_UP" elif angle_left_arm0: str_pose = "ALL_HANDS_UP" if abs(angle_left_elow)


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3