在本文中,将深入探讨使用Mediapipe和OpenCV进行姿态检测的技术细节和代码实现。首先,让了解一些姿态检测在现实世界中的应用案例。
健身应用:这是姿态检测最现代的应用之一,健身行业因此得到了极大的推动。
监控摄像头:随着小偷日益狡猾,是时候制造智能摄像头,借助姿态检测技术捕捉他们的每一个动作。
滤镜:为了制作更真实、互动和现代的身体滤镜,这些滤镜被所有年龄段的人们广泛使用。
将在Jupyter笔记本中完成所有编码部分,尽管也可以在任何代码编辑器中执行相同的操作,但Jupyter笔记本更受青睐,因为它更具交互性。现在,让构建自己的姿势检测应用。
根据需求,让导入所有必要的库。
import cv2
import mediapipe as mp
import matplotlib.pyplot as plt
从这里开始第一步,即初始化姿态检测模型。这一步在创建模型方面非常常见,因为在传递任何自定义值给模型之前,首先需要提供一些强制性的模型参数,并且在这种情况下,这也将有助于后续的模型测试。
# 初始化mediapipe姿态类
mp_pose = mp.solutions.pose
# 设置图像的姿态函数 - 独立于图像的单独处理
pose_image = mp_pose.Pose(static_image_mode=True, min_detection_confidence=0.5)
# 设置视频的姿态函数 - 用于视频处理
pose_video = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.7,
min_tracking_confidence=0.7)
# 初始化mediapipe绘图类 - 用于绘制地标点
mp_drawing = mp.solutions.drawing_utils
首先,将初始化mediapipe姿态主类,即solutions.pose,用一个变量来保存该mediapipe姿态检测模型的实例。现在已经将姿态检测类的实例存储在mp_pose变量中,将使用这个变量来调用Pose方法,并将其存储在pose_image中。这样,将设置姿态估计的函数。现在让讨论Pose函数中的参数。
static_image_mode:它持有布尔值(True/False),默认情况下它被初始化为false,这意味着它将以视频格式处理给定的图像,而不会理想地处理每个图像,但当将其切换为True时,它将以理想的方式处理给定的图像,即单独处理,这是要求。
min_detection_confidence:顾名思义,这个参数将设置置信度水平的阈值,它的范围是[0.0, 1.0],即最小置信度为0,最大置信度为1,默认值为0.5,这里将阈值设置为0.5。
现在已经为图像设置了函数,将为视频流做同样的事情,将使用相同的Pose函数,并将实例存储在pose_video中。让看看它的参数。
static_image_mode:在这里,需要为视频流设置它,因此将值设置为False。
min_detection_confidence:在这里将置信度阈值设置为0.7。
min_tracking_confidence:这是跟踪级别的置信度,即它将根据提供的置信度检测是否检测到人,以便在检测后不会出现高鲁棒性问题。注意:当static_image_mode设置为True时,它将自动被忽略。
最后,将使用drawing_utils函数在图像或视频(实时流)上绘制模型从上述处理中检测到的所有地标点。
现在,已经克服了所有先决条件,开始使用Mediapipe进行姿态检测,现在将制作一个姿态检测函数,这将帮助以模块化的方式执行检测,并使整个流程更加高效。
def detectPose(image_pose, pose, draw=False, display=False):
original_image = image_pose.copy()
image_in_RGB = cv2.cvtColor(image_pose, cv2.COLOR_BGR2RGB)
resultant = pose.process(image_in_RGB)
if resultant.pose_landmarks and draw:
mp_drawing.draw_landmarks(image=original_image, landmark_list=resultant.pose_landmarks,
connections=mp_pose.POSE_CONNECTIONS,
landmark_drawing_spec=mp_drawing.DrawingSpec(color=(255,255,255),
thickness=3, circle_radius=3),
connection_drawing_spec=mp_drawing.DrawingSpec(color=(49,125,237),
thickness=2, circle_radius=2))
if display:
plt.figure(figsize=[22,22])
plt.subplot(121);plt.imshow(image_pose[:,:,::-1]);plt.title("Input Image");plt.axis('off');
plt.subplot(122);plt.imshow(original_image[:,:,::-1]);plt.title("Pose detected Image");plt.axis('off');
else:
return original_image, results
首先,将创建原始图像的副本,以便在预处理过程中不会丢失任何原始图像的内容。然后,将把Blue Green Red格式转换为Red Green Blue格式,因为在计算机视觉中它被广泛使用。现在将使用process函数处理转换后的图像格式。
是时候进行一些验证和检查了,看看图像中是否检测到了地标,如果检测到了地标,那么将使用draw_landmarks函数将它们绘制在图像上。
之前先进行了验证再绘制地标,现在将检查display参数是否允许显示结果和输入图像。如果上述条件为真,则显示原始和结果图像。否则,它将只返回输出图像和结果。
现在将测试上面创建的detectPose函数,以对样本图像执行姿态检测并显示结果。
# 从指定路径读取图像以检测姿态
image_path = 'media/sample2.jpg'
output = cv2.imread(image_path)
detectPose(output, pose_image, draw=True, display=True)
正如所看到的,结果相当令人满意,很明显Mediapipe在姿态检测方面做得很好,而detectPose()能够顺利且高效地处理整个流程。可以尝试使用不同的图像来测试这个函数,只需要改变image_path中的图像路径即可。