除了手势识别追踪和人脸的“面部网格”识别之外,MediaPipe还能实现“姿势侦测”(Pose,又称“姿态识别”),它将人体模型标注出0-32共33个关键点,比如6对应的是右眼外眼角(right_eye_outer)、13对应的是左肘尖(left_elbow)、30对应的是右脚跟(right_heel)等等。头部的关键点是从0到10,身体的左侧关键点是奇数从11、13直至31,右侧是偶数从12、14直至32,二者所对应的身体部位是对称标注的(如图1)。
1.对静态图像文件中的人体进行姿势侦测
首先,导入OpenCV和MediaPipe库模块:“import cv2”“import mediapipe as mp”;然后进行人体姿势侦测模型的导入——建立变量mp_pose并赋值为“mp.solutions.pose”;再建立变量mp_drawing,赋值为“mp.solutions.drawing_utils”,作用是导入绘图模块;建立姿势侦测变量pose,赋值为“mp_pose.Pose(static_image_mode=True, model_complexity=2, smooth_landmarks=True,enable_segmentation=True,min_detection_confidence=0.5,min_tracking_confidence=0.5)”,其中的参数“static_image_mode=True”作用是设置为静态图像文件的检测,参数“model_complexity=2”作用是设置为最佳的姿势侦测(值为0时速度最快但 性能较弱,值为1时速度与性能比较均衡),参数“smooth_landmarks=True”作用是将平滑关键点的检测设置为有效,参数“enable_segmentation=True”作用是将人体抠图设置为有效,参数“min_detection_confidence=0.5”和“min_tracking_confidence=0.5)”作用是分别设置侦测的置信度与追踪阈值。
接下来从图片文件中读入图像,建立变量img并赋值为“cv2.imread('test.jpg')”,其中的test.jpg即为待测试的图片文件;建立变量img_RGB,赋值为“cv2.cvtColor(img,cv2.COLOR_BGR2RGB)”,作用是将读入的图像进行色彩模式的转换,从BGR转为RGB;建立变量results,赋值为“pose.process(img_RGB)”,作用是将转换模式后的图像输入至训练模型并获取对应的姿势侦测结果;再进行可视化检测结果的描绘,通过语句“mp_drawing.draw_landmarks(img,results.pose_landmarks,mp_pose.POSE_CONNECTIONS)”来实现,其默认效果是用红色小圆点标注33个关键点,并且用白色细线进行连接;最后,通过语句“cv2.imwrite('result.jpg',img)”将添加标注效果的图像存储为result.jpg文件(如图2)。
将程序保存为“[01]Test_Single_Picture.py”,按F5运行测试,很快就生成了result.jpg文件,与之前的test.jpg同时打开进行对比查看,人物身体上的33个关键点被正确标注,同时也有若干条白色细线连接对应的关键点(如图3)。
2.关键点的分组标注及二维坐标值的解析
将“[01]Test_Single_Picture.py”复制粘贴为“[02]Three_Groups.py”,进行代码的修改,在最后一行“cv2.imwrite('result.jpg',img)”代码之前插入以下代码:
建立变量h和w,分别赋值为“img.shape[0]”和“img.shape[1]”,表示图像的高度和宽度;建立变量radius并赋值为8,用来控制关键点描绘时圆点的半径大小;同时建立head_points和left_points两个变量,均赋值为空列表“[]”,分别通过“for i in range(11):”和“for i in range(11,33):”两个循环,将头部和左侧所对应的关键点序号追加(append)至各自列表中(剩余的即为右侧关键点);在“for i in range(33):”循环中,变量cx和cy的值分别为“int(results.pose_landmarks.landmark[i].x * w)”和“int(results.pose_landmarks.landmark[i].y * h)”,即该关键点的横坐标和纵坐标值。以鼻尖为例,由于该关键点所对应的序号是0,因此通过条件“if i==0:”判定为真时将其输出:“print("鼻尖位置的二维坐标值为:(",cx,",",cy,")")”;接下来,如果满足“if i in head_points:”,说明该关键点位于头部,则通过语句“img = cv2.circle(img,(cx,cy),radius-5,(0,0,255),-1)”绘制为红色圆点;如果满足“elif i in left_points:”,说明关键点位于人体左侧,则通过语句“img = cv2.circle(img,(cx,cy),radius,(255,0,0),-1)”绘制为蓝色圆点;剩余的右侧各个关键点,通过语句“img = cv2.circle(img,(cx,cy),radius,(0,255,0),-1)”绘制为绿色圆点(如图4)。
运行测试,程序生成的图片文件result.jpg与之前相比,人体的头部11个关键点仍被标注为红色圆点,但左侧和右侧各11个关键点则分别被标注为蓝色和绿色圆点;而且在命令行处输出有提示信息:“鼻尖位置的二维坐标值为:(665, 249)”(如图5)。
3.对摄像头监控画面中的人体进行姿势侦测
仍然是在“[01]Test_Single_Picture.py”基础之上进行“[03]Test_Camera.py”代码的修改,目的是完成摄像头监控画面中的人体姿势侦测。注意在为变量pose赋值时,其中的“static_image_mode”参数必须设为“False”,表示“非静态图像模式”(即视频的动态帧画面);从变量camera的赋值到“while True:”循环体中的代码,像图像颜色模式的转换、默认姿势侦测绘制效果的实现等等,均与之前相同(如图6)。
运行测试,分别尝试在摄像头前面进行远景和各种近景的拍摄测试,全身的33个关键点能够快速实时检测到,并且以红色圆点加白色细线连接标注;侧身和正身的近景上半身若干个关键点同样也能够被检测和标注,都是实时的测试效果(如图7)。
关注“壹零社”公众号下载源代码。
热门跟贴