• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

3D人体骨架检测mediapipe

武飞扬头像
何荣基
帮助1

m

在本教程中,我们将学习如何使用python中的mediapipe库进行实时3D骨架检测。

首先,我们得用pip下载下来我们需要用到的模组:

pip install mediapipe

这个工具不仅得到了谷歌的支持,而且Mediapipe中的模型也被积极地用于谷歌产品中。因此,这个模组,超级牛皮。

现在,MediaPipe的姿势检测是高保真(高质量)和低延迟(超快)的最先进的解决方案,用于在低端设备(即手机,笔记本电脑等)的实时视频源中检测一个人的33个3D地标。

pip install opencv-python

Opencv-python简称cv2, 是一个超级牛皮的模组(比mediapipe还牛皮),他可以打开你的摄像头,并且还能回去每一帧的图像并显示出来(详情请见opencv的教程),关键是,cv2还有C 和Java版的。

pip install numpy

Numpy, 为矩阵计算而生,是一个专门计算矩阵的模组,cv2会用到它。

pip install vpython

大家应该不是那么的熟悉这个模组,用来在3D中布点的。但是因为简洁且迅速的更新速度,让我选择了这个模组(主要是因为害怕会掉帧)

P.S python需要定在python 3.0 以上

接下来,就是骨架预测的操作。

首先,导入所有我们需要的模组:
 

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *

然后来了解一下mediapipe里骨架预测模块的初始化:
 

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    mp_pose = mp.solutions.pose #从mediapipe里面获取pose
  5.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化

Static_image_mode -这是一个布尔值,如果设置为False,检测器只在需要时调用,在第一帧或当跟踪器丢失跟踪时。如果设置为True,则对每个输入图像调用人员检测器。当你处理一堆不相关的图像而不是视频时,你应该把这个设为True。默认值为False。

Min_detection_confidence—考虑骨架检测模型的预测正确性所需的最小检测置信范围(0.0,1.0)。默认值为0.5。这意味着如果一个检测器的预测置信度大于或等于50%,则被认为是阳性的。

Min_tracking_confidence -这是骨架关节点跟踪模型为了有效跟踪地标的姿态,需要考虑的最小跟踪置信度([0.0,1.0])。如果置信度小于设定值,则在下一帧/图像中再次调用检测器,因此增加其值会增加稳定性,但也会造成延迟。默认值为0.5。

Model_complexity—骨架检测模型的复杂性。由于有三种不同的模型可供选择,可能的值为0、1或2。值越高,结果越准确,但代价是延迟越长。缺省值为1。

Smooth_landmarks -这是一个布尔值,如果设置为True,将过滤不同帧的骨架关节点以减少噪音。只有当static_image_mode也设置为False时,这才有效。默认值为True。

mp_drawing = mp.solutions.drawing_utils

mp_drawing 是为了可视化关节点于它们之间的关系初始化的

然后,咱们来搞一下摄像头的初始化:

  1.  
    cam = cv2.VideoCapture(0) #开启摄像头
  2.  
    while True:
  3.  
    _, frame = cam.read() #获取每一帧
  4.  
    cv2.imshow('real time', frame) #显示每一帧
  5.  
    if cv2.waitKey(1) == ord(q): #检查是否按下q键
  6.  
    break
  7.  
    cam.release() #关掉摄像头
  8.  
    cv2.destroyAllWindows() #关掉窗口
  9.  

到现在为止,你的代码应该是这样的:

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    mp_pose = mp.solutions.pose #从mediapipe里面获取pose
  5.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
  6.  
    mp_drawing = mp.solutions.drawing_utils
  7.  
    cam = cv2.VideoCapture(0) #开启摄像头
  8.  
    while True:
  9.  
    _, frame = cam.read() #获取每一帧
  10.  
    cv2.imshow('real time', frame) #显示每一帧
  11.  
    if cv2.waitKey(1) == ord(q): #检查是否按下q键
  12.  
    break
  13.  
    cam.release() #关掉摄像头
  14.  
    cv2.destroyAllWindows() #关掉窗口
  15.  
学新通

 现在,我们将使用函数 mp.solutions.pose.Pose().process() 将图像传递到姿势检测机器学习管道。但是管道需要RGB颜色格式的输入图像,因此首先我们必须使用函数cv2.cvtColor()将示例图像从BGR转换为RGB格式,因为OpenCVBGR格式(而不是RGB)读取图像:

 results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB))

执行姿势检测后,我们将获得三十三个地标的列表,这些地标代表图像中突出人物的身体关节位置。每个地标都有:

  • x – 它是按图像宽度归一化为 [0.0, 1.0] 的地标 x 坐标。
  • y:它是按图像高度归一化为 [0.0, 1.0] 的地标 y 坐标。
  • z:它是归一化为与 x 大致相同的比例的地标 z 坐标。它表示以臀部中点为原点的地标深度,因此 z 的值越小,地标离相机越近。
  • 可见性:它是一个范围为 [0.0, 1.0] 的值,表示地标在图像中可见(未遮挡)的可能性。在决定是否要显示特定关节时,这是一个有用的变量,因为它可能在图像中被遮挡或部分可见。

但是,我们现在只需要x,y和z。

接下来,我们需要显示它们的位置,并画上线:
 

mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS)

运行一下,你的代码应该是这样的:
 

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    mp_pose = mp.solutions.pose #从mediapipe里面获取pose
  5.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
  6.  
    mp_drawing = mp.solutions.drawing_utils
  7.  
    cam = cv2.VideoCapture(0) #开启摄像头
  8.  
    while True:
  9.  
    _, frame = cam.read() #获取每一帧
  10.  
  11.  
    results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
  12.  
     
  13.  
     
  14.  
    mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
  15.  
     
  16.  
  17.  
    cv2.imshow('real time', frame) #显示每一帧
  18.  
    if cv2.waitKey(1) == ord(q): #检查是否按下q键
  19.  
    break
  20.  
    cam.release() #关掉摄像头
  21.  
    cv2.destroyAllWindows() #关掉窗口
  22.  
  23.  
     
  24.  
学新通

现在,一大半已经搞完了,现在只需要搞定在3D中的显示。

  1.  
    points = []
  2.  
     
  3.  
    c = []
  4.  
    for x in range(33):
  5.  
    points.append(sphere(radius=5, pos=vector(0, -50, 0)))
  6.  
    c.append(curve(retain=2, radius=4))

sphere 是用来布点的。

curve 是用来连接各个点的。

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    mp_pose = mp.solutions.pose #从mediapipe里面获取pose
  5.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
  6.  
  7.  
    points = []
  8.  
     
  9.  
    c = []
  10.  
    for x in range(33):
  11.  
    points.append(sphere(radius=5, pos=vector(0, -50, 0)))
  12.  
    c.append(curve(retain=2, radius=4))
  13.  
     
  14.  
  15.  
    mp_drawing = mp.solutions.drawing_utils
  16.  
    cam = cv2.VideoCapture(0) #开启摄像头
  17.  
    while True:
  18.  
    _, frame = cam.read() #获取每一帧
  19.  
  20.  
    results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
  21.  
     
  22.  
     
  23.  
    mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
  24.  
     
  25.  
  26.  
    cv2.imshow('real time', frame) #显示每一帧
  27.  
    if cv2.waitKey(1) == ord(q): #检查是否按下q键
  28.  
    break
  29.  
    cam.release() #关掉摄像头
  30.  
    cv2.destroyAllWindows() #关掉窗口
  31.  
  32.  
     
  33.  
  34.  
     
  35.  
学新通

P.S 后面的操作开始变得骚了,因此我每次操作都会放上一个完整的代码。

我们现在需要让我们的点根据骨骼关节点的x,y,z数值改变:

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    mp_pose = mp.solutions.pose #从mediapipe里面获取pose
  5.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
  6.  
  7.  
    points = []
  8.  
     
  9.  
    c = []
  10.  
    for x in range(33):
  11.  
    points.append(sphere(radius=5, pos=vector(0, -50, 0)))
  12.  
    c.append(curve(retain=2, radius=4))
  13.  
     
  14.  
  15.  
    mp_drawing = mp.solutions.drawing_utils
  16.  
    cam = cv2.VideoCapture(0) #开启摄像头
  17.  
    while True:
  18.  
    _, frame = cam.read() #获取每一帧
  19.  
  20.  
    results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
  21.  
     
  22.  
    if results.pose_world_landmarks:
  23.  
    for i in range(11, 33):
  24.  
    if i != 18 and i!=20 and i!= 22 and i != 17 and i!=19 and i!=21:
  25.  
    points[i].pos.x = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].x * -cap.get(3)
  26.  
    points[i].pos.y = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].y * -cap.get(4)
  27.  
    points[i].pos.z = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].z * -cap.get(3)
  28.  
     
  29.  
    mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
  30.  
     
  31.  
  32.  
    cv2.imshow('real time', frame) #显示每一帧
  33.  
    if cv2.waitKey(1) == ord(q): #检查是否按下q键
  34.  
    break
  35.  
    cam.release() #关掉摄像头
  36.  
    cv2.destroyAllWindows() #关掉窗口
  37.  
  38.  
     
  39.  
  40.  
     
  41.  
  42.  
     
  43.  
学新通

再画上连接线:

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    mp_pose = mp.solutions.pose #从mediapipe里面获取pose
  5.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1) #初始化
  6.  
  7.  
    points = []
  8.  
    ids = [[12, 14, 16], [11, 13, 15], [12, 24, 26, 28, 30, 32, 28],
  9.  
    [11, 23, 25, 27, 29, 31, 27], [12, 11], [24, 23]]
  10.  
    c = []
  11.  
    for x in range(33):
  12.  
    points.append(sphere(radius=5, pos=vector(0, -50, 0)))
  13.  
    c.append(curve(retain=2, radius=4))
  14.  
     
  15.  
  16.  
    mp_drawing = mp.solutions.drawing_utils
  17.  
    cam = cv2.VideoCapture(0) #开启摄像头
  18.  
    while True:
  19.  
    _, frame = cam.read() #获取每一帧
  20.  
  21.  
    results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB)) #检查每一帧中的骨架关节点
  22.  
     
  23.  
    if results.pose_world_landmarks:
  24.  
    for i in range(11, 33):
  25.  
    if i != 18 and i!=20 and i!= 22 and i != 17 and i!=19 and i!=21:
  26.  
    points[i].pos.x = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].x * -cap.get(3)
  27.  
    points[i].pos.y = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].y * -cap.get(4)
  28.  
    points[i].pos.z = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].z * -cap.get(3)
  29.  
    for n in range(2):
  30.  
    for i in range(2):
  31.  
    c[i 2 * n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
  32.  
    vector(points[ids[n][i 1]].pos.x, points[ids[n][i 1]].pos.y,
  33.  
    points[ids[n][i 1]].pos.z), retaine=2)
  34.  
    for n in range(2, 4):
  35.  
    for i in range(6):
  36.  
    c[i 6*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
  37.  
    vector(points[ids[n][i 1]].pos.x, points[ids[n][i 1]].pos.y, points[ids[n][i 1]].pos.z), retaine = 2)
  38.  
    for n in range(4, 6):
  39.  
    for i in range(1):
  40.  
    c[i 2*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
  41.  
    vector(points[ids[n][i 1]].pos.x, points[ids[n][i 1]].pos.y, points[ids[n][i 1]].pos.z), retaine = 2)
  42.  
    mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS) #画上关节点
  43.  
     
  44.  
  45.  
    cv2.imshow('real time', frame) #显示每一帧
  46.  
    if cv2.waitKey(1) == ord(q): #检查是否按下q键
  47.  
    break
  48.  
    cam.release() #关掉摄像头
  49.  
    cv2.destroyAllWindows() #关掉窗口
  50.  
  51.  
     
  52.  
  53.  
     
  54.  
  55.  
     
  56.  
  57.  
     
  58.  
学新通

好啦!作品已完成,经过整理后就变成这样了:
 

  1.  
    import cv2
  2.  
    import mediapipe as mp
  3.  
    from vpython import *
  4.  
    #mediapipe 模型变量初始化
  5.  
    def mediapipe_varibles_init():
  6.  
    mp_pose = mp.solutions.pose
  7.  
    pose = mp_pose.Pose(static_image_mode=False, min_detection_confidence=0.5, model_complexity=1)
  8.  
    mp_drawing = mp.solutions.drawing_utils
  9.  
    return pose,mp_pose, mp_drawing
  10.  
    #vpython(三维画图)模型变量初始化
  11.  
    def vpython_variables_init():
  12.  
    points = []
  13.  
    boxs = []
  14.  
    ids = [[12, 14, 16], [11, 13, 15], [12, 24, 26, 28, 30, 32, 28],
  15.  
    [11, 23, 25, 27, 29, 31, 27], [12, 11], [24, 23]]
  16.  
    c = []
  17.  
     
  18.  
    for x in range(33):
  19.  
    points.append(sphere(radius=5, pos=vector(0, -50, 0)))
  20.  
    c.append(curve(retain=2, radius=4))
  21.  
    return points, boxs, ids, c
  22.  
    #在3D里画出骨架的函数
  23.  
    def draw_3d_pose():
  24.  
    results = pose.process(cv2.cvtColor(f, cv2.COLOR_BGR2RGB))
  25.  
    if results.pose_world_landmarks:
  26.  
    for i in range(11, 33):
  27.  
    if i != 18 and i!=20 and i!= 22 and i != 17 and i!=19 and i!=21:
  28.  
    points[i].pos.x = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].x * -cap.get(3)
  29.  
    points[i].pos.y = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].y * -cap.get(4)
  30.  
    points[i].pos.z = results.pose_world_landmarks.landmark[mp_pose.PoseLandmark(i).value].z * -cap.get(3)
  31.  
    for n in range(2):
  32.  
    for i in range(2):
  33.  
    c[i 2 * n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
  34.  
    vector(points[ids[n][i 1]].pos.x, points[ids[n][i 1]].pos.y,
  35.  
    points[ids[n][i 1]].pos.z), retaine=2)
  36.  
    for n in range(2, 4):
  37.  
    for i in range(6):
  38.  
    c[i 6*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
  39.  
    vector(points[ids[n][i 1]].pos.x, points[ids[n][i 1]].pos.y, points[ids[n][i 1]].pos.z), retaine = 2)
  40.  
    for n in range(4, 6):
  41.  
    for i in range(1):
  42.  
    c[i 2*n].append(vector(points[ids[n][i]].pos.x, points[ids[n][i]].pos.y, points[ids[n][i]].pos.z),
  43.  
    vector(points[ids[n][i 1]].pos.x, points[ids[n][i 1]].pos.y, points[ids[n][i 1]].pos.z), retaine = 2)
  44.  
    mp_drawing.draw_landmarks(image=f, landmark_list=results.pose_landmarks, connections=mp_pose.POSE_CONNECTIONS)
  45.  
    #窗口关闭函数
  46.  
    def clos_def():
  47.  
    cap.release()
  48.  
    cv2.destroyAllWindows()
  49.  
    #获取变量
  50.  
    points, boxs, ids, c = vpython_variables_init()
  51.  
    pose, mp_pose, mp_drawing = mediapipe_varibles_init()
  52.  
    #打开摄像头,0是第一个摄像头,如果想换一个摄像头请改变这个数字
  53.  
    cap = cv2.VideoCapture(0)
  54.  
    while True:
  55.  
    #获取每一帧的图像
  56.  
    _, f = cap.read()
  57.  
    #vpython里的一个函数,用来调整3D中的FPS
  58.  
    rate(150)
  59.  
    #调用在3D里画出骨架的函数
  60.  
    draw_3d_pose()
  61.  
    #在每一帧里画骨架
  62.  
    #显示每一帧
  63.  
    cv2.imshow('real_time', f)
  64.  
    #检测是否要关闭窗口
  65.  
    if cv2.waitKey(1) & 0xFF == ord('q'):
  66.  
    break
  67.  
    #调用窗口关闭函数
  68.  
    clos_def()
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfibfjh
系列文章
更多 icon
同类精品
更多 icon
继续加载