Mediapipe-姿态估计实例

Mediapipe简介

Mediapipe 是由 Google Research 开发的一款开源框架,旨在帮助开发者轻松地构建、测试和部署复杂的多模态、多任务的机器学习模型。它特别擅长于实时处理和分析音频、视频等多媒体数据。以下是 Mediapipe 的一些关键特点和组件:

关键特点

  1. 多平台支持:Mediapipe 支持在多个平台上运行,包括桌面、移动设备和网页。这使得开发者可以轻松地将模型部署到不同的平台上。

  2. 高效的实时处理:Mediapipe 具有高度优化的性能,能够在资源受限的设备上进行实时处理。这使其特别适合于移动设备和嵌入式系统。

  3. 模块化设计:Mediapipe 使用图表(graph)来组织和连接不同的处理模块。这种设计使得开发者可以灵活地组合和复用不同的处理组件。

  4. 丰富的预构建解决方案:Mediapipe 提供了许多预构建的解决方案,如人脸检测、手部追踪、姿态估计等,开发者可以直接使用这些解决方案来快速构建应用。

主要组件

  1. 图表(Graph):Mediapipe 的核心是其图表结构,图表定义了数据流和处理模块的连接方式。每个图表由一系列节点(nodes)和边(edges)组成,节点表示具体的处理模块,边表示数据在节点之间的流动。

  2. 节点(Nodes):节点是图表的基本单元,表示具体的处理操作。Mediapipe 提供了许多内置的节点,如数据输入输出节点、图像处理节点、机器学习推理节点等。

  3. 数据包(Packets):数据包是图表中传输的数据单元,节点之间通过发送和接收数据包来通信。数据包可以包含各种类型的数据,如图像帧、音频信号、检测结果等。

  4. 计算机视觉解决方案:Mediapipe 提供了许多预构建的计算机视觉解决方案,这些解决方案已经高度优化,能够在实时应用中使用。常见的解决方案包括人脸检测、手部追踪、姿态估计、对象检测等。

常见使用场景

  1. 姿态估计(Pose Estimation):Mediapipe 可以实时检测和追踪人体的关键点(如肩膀、肘部、膝盖等),并估计人体的姿态。这对于体育训练、动作捕捉、增强现实等应用非常有用。

  2. 手部追踪(Hand Tracking):Mediapipe 能够检测和追踪手部的关键点,提供手势识别和手部动作分析的能力。这在手势控制、虚拟现实、手写输入等应用中有广泛的应用。

  3. 人脸检测(Face Detection):Mediapipe 提供了高效的人脸检测和关键点追踪功能,可以用于面部识别、表情分析、虚拟化妆等场景。

  4. 对象检测(Object Detection):Mediapipe 还提供了实时的对象检测解决方案,可以用于监控、无人驾驶、智能家居等领域。

示例代码

以下是一个使用 Mediapipe 进行姿态估计的简单示例:

import cv2
import mediapipe as mp

# Initialize mediapipe pose class.
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()

# Initialize mediapipe drawing class, useful for annotation.
mp_drawing = mp.solutions.drawing_utils

# Load the video file or start webcam capture.
cap = cv2.VideoCapture(0)  # Use 0 for webcam, or provide video file path

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

    # Convert the BGR image to RGB.
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Process the image and detect the pose.
    result = pose.process(image_rgb)

    # Draw the pose annotation on the image.
    if result.pose_landmarks:
        mp_drawing.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)

    # Display the frame with pose landmarks.
    cv2.imshow('Pose Estimation', frame)

    # Break the loop if 'q' is pressed.
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

# Release the video capture object and close display window.
cap.release()
cv2.destroyAllWindows()

这段代码使用 Mediapipe 的姿态估计功能,读取视频流并实时绘制人体的关键点。你可以使用摄像头实时捕捉人体姿态,也可以处理预录制的视频文件。

实例1-读取视频流并进行骨骼点绘制:

import cv2
import mediapipe as mp

# Initialize mediapipe pose class.
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()

# Initialize mediapipe drawing class, useful for annotation.
mp_drawing = mp.solutions.drawing_utils

# Load the video file.
cap = cv2.VideoCapture('D:/basketball.mp4')

# Check if the video is opened successfully.
if not cap.isOpened():
    print("Error: Could not open video.")
    exit()

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        print("Reached the end of the video.")
        break

    # Convert the BGR image to RGB.
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Process the image and detect the pose.
    result = pose.process(image_rgb)

    # Draw the pose annotation on the image.
    if result.pose_landmarks:
        mp_drawing.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)

    # Display the frame with pose landmarks.
    cv2.imshow('Pose Estimation', frame)

    # Break the loop if 'q' is pressed.
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

# Release the video capture object and close display window.
cap.release()
cv2.destroyAllWindows()

效果如下:
在这里插入图片描述

实例2-读取视频流中姿态估计与3D绘制:

代码如下:

import cv2
import mediapipe as mp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib.animation import FuncAnimation

# Initialize mediapipe pose class.
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()

# Initialize mediapipe drawing class, useful for annotation.
mp_drawing = mp.solutions.drawing_utils

# Load the video file.
cap = cv2.VideoCapture('D:/basketball.mp4')

# Check if the video is opened successfully.
if not cap.isOpened():
    print("Error: Could not open video.")
    exit()

fig = plt.figure(figsize=(10, 5))
ax2d = fig.add_subplot(121)
ax3d = fig.add_subplot(122, projection='3d')

def update(frame_number):
    ret, frame = cap.read()
    if not ret:
        print("Reached the end of the video.")
        return

    # Convert the BGR image to RGB.
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Process the image and detect the pose.
    result = pose.process(image_rgb)

    # Clear the previous plots
    ax2d.clear()
    ax3d.clear()

    # Draw the pose annotation on the image.
    if result.pose_landmarks:
        mp_drawing.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)

        # Extract the landmark points.
        landmarks = result.pose_landmarks.landmark
        xs = [landmark.x for landmark in landmarks]
        ys = [landmark.y for landmark in landmarks]
        zs = [landmark.z for landmark in landmarks]

        # Plot 2D image
        ax2d.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
        ax2d.set_title('Pose Estimation')
        ax2d.axis('off')

        # Plot 3D landmarks
        ax3d.scatter(xs, ys, zs, c='blue', marker='o')
        ax3d.set_xlim([0, 1])
        ax3d.set_ylim([0, 1])
        ax3d.set_zlim([-1, 1])
        ax3d.set_xlabel('X')
        ax3d.set_ylabel('Y')
        ax3d.set_zlabel('Z')
        ax3d.set_title('3D Pose Landmarks')

ani = FuncAnimation(fig, update, interval=10)

plt.show()

cap.release()
cv2.destroyAllWindows()

效果如下:
在这里插入图片描述
为了将三维骨骼点连接起来,可以使用 mpl_toolkits.mplot3d.art3d.Line3DCollection 来绘制骨骼连接。你需要定义这些连接的点对,并在三维图中使用它们来绘制线条。以下是更新后的代码:

import cv2
import mediapipe as mp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Line3DCollection
import numpy as np
from matplotlib.animation import FuncAnimation

# Initialize mediapipe pose class.
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()

# Initialize mediapipe drawing class, useful for annotation.
mp_drawing = mp.solutions.drawing_utils

# Load the video file.
cap = cv2.VideoCapture('D:/basketball.mp4')

# Check if the video is opened successfully.
if not cap.isOpened():
    print("Error: Could not open video.")
    exit()

fig = plt.figure(figsize=(10, 5))
ax2d = fig.add_subplot(121)
ax3d = fig.add_subplot(122, projection='3d')

def update(frame_number):
    ret, frame = cap.read()
    if not ret:
        print("Reached the end of the video.")
        return

    # Convert the BGR image to RGB.
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Process the image and detect the pose.
    result = pose.process(image_rgb)

    # Clear the previous plots
    ax2d.clear()
    ax3d.clear()

    # Draw the pose annotation on the image.
    if result.pose_landmarks:
        mp_drawing.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)

        # Extract the landmark points.
        landmarks = result.pose_landmarks.landmark
        xs = [landmark.x for landmark in landmarks]
        ys = [landmark.y for landmark in landmarks]
        zs = [landmark.z for landmark in landmarks]

        # Define the connections between landmarks
        connections = [
            (0, 1), (1, 2), (2, 3), (3, 7), (0, 4), (4, 5), (5, 6), (6, 8),
            (9, 10), (11, 12), (11, 13), (13, 15), (15, 17), (15, 19), (15, 21),
            (17, 19), (12, 14), (14, 16), (16, 18), (16, 20), (16, 22), (18, 20),
            (11, 23), (12, 24), (23, 24), (23, 25), (24, 26), (25, 27), (26, 28),
            (27, 29), (28, 30), (29, 31), (30, 32)
        ]

        # Create a list of 3D lines
        lines = [[(xs[start], ys[start], zs[start]), (xs[end], ys[end], zs[end])] for start, end in connections]

        # Plot 2D image
        ax2d.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
        ax2d.set_title('Pose Estimation')
        ax2d.axis('off')

        # Plot 3D landmarks and connections
        ax3d.scatter(xs, ys, zs, c='blue', marker='o')
        ax3d.add_collection3d(Line3DCollection(lines, colors='blue', linewidths=2))
        ax3d.set_xlim([0, 1])
        ax3d.set_ylim([0, 1])
        ax3d.set_zlim([-1, 1])
        ax3d.set_xlabel('X')
        ax3d.set_ylabel('Y')
        ax3d.set_zlabel('Z')
        ax3d.set_title('3D Pose Landmarks')

ani = FuncAnimation(fig, update, interval=10)

plt.show()

cap.release()
cv2.destroyAllWindows()

在这个代码中,我们定义了 connections 列表,它包含了骨骼点之间的连接对。然后我们创建了一个 lines 列表,用于存储这些连接的三维线段,并使用 ax3d.add_collection3d(Line3DCollection(lines, colors='blue', linewidths=2)) 方法将这些线段添加到三维图中。

运行这个脚本后,三维图中不仅会显示骨骼点,还会将这些点连起来,形成完整的骨骼结构。
效果如下:
在这里插入图片描述
上面的代码看似三维图的骨骼是倒立的,你可以调整三维图的坐标显示,以使得骨骼结构显示为正常的人体姿态。可以通过设置三维图的坐标轴范围和方向来调整显示效果。以下是修改后的代码,调整了坐标轴的范围和方向,以使骨骼结构正常显示:

import cv2
import mediapipe as mp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Line3DCollection
import numpy as np
from matplotlib.animation import FuncAnimation

# Initialize mediapipe pose class.
mp_pose = mp.solutions.pose
pose = mp_pose.Pose()

# Initialize mediapipe drawing class, useful for annotation.
mp_drawing = mp.solutions.drawing_utils

# Load the video file.
cap = cv2.VideoCapture('D:/basketball.mp4')

# Check if the video is opened successfully.
if not cap.isOpened():
    print("Error: Could not open video.")
    exit()

fig = plt.figure(figsize=(10, 5))
ax2d = fig.add_subplot(121)
ax3d = fig.add_subplot(122, projection='3d')

def update(frame_number):
    ret, frame = cap.read()
    if not ret:
        print("Reached the end of the video.")
        return

    # Convert the BGR image to RGB.
    image_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # Process the image and detect the pose.
    result = pose.process(image_rgb)

    # Clear the previous plots
    ax2d.clear()
    ax3d.clear()

    # Draw the pose annotation on the image.
    if result.pose_landmarks:
        mp_drawing.draw_landmarks(frame, result.pose_landmarks, mp_pose.POSE_CONNECTIONS)

        # Extract the landmark points.
        landmarks = result.pose_landmarks.landmark
        xs = [landmark.x for landmark in landmarks]
        ys = [landmark.y for landmark in landmarks]
        zs = [-landmark.z for landmark in landmarks]  # Negate the z-axis for better visualization

        # Define the connections between landmarks
        connections = [
            (0, 1), (1, 2), (2, 3), (3, 7), (0, 4), (4, 5), (5, 6), (6, 8),
            (9, 10), (11, 12), (11, 13), (13, 15), (15, 17), (15, 19), (15, 21),
            (17, 19), (12, 14), (14, 16), (16, 18), (16, 20), (16, 22), (18, 20),
            (11, 23), (12, 24), (23, 24), (23, 25), (24, 26), (25, 27), (26, 28),
            (27, 29), (28, 30), (29, 31), (30, 32)
        ]

        # Create a list of 3D lines
        lines = [[(xs[start], ys[start], zs[start]), (xs[end], ys[end], zs[end])] for start, end in connections]

        # Plot 2D image
        ax2d.imshow(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
        ax2d.set_title('Pose Estimation')
        ax2d.axis('off')

        # Plot 3D landmarks and connections
        ax3d.scatter(xs, ys, zs, c='blue', marker='o')
        ax3d.add_collection3d(Line3DCollection(lines, colors='blue', linewidths=2))
        ax3d.set_xlim([0, 1])
        ax3d.set_ylim([1, 0])  # Flip the y-axis for better visualization
        ax3d.set_zlim([1, -1])
        ax3d.set_xlabel('X')
        ax3d.set_ylabel('Y')
        ax3d.set_zlabel('Z')
        ax3d.set_title('3D Pose Landmarks')

ani = FuncAnimation(fig, update, interval=10)

plt.show()

cap.release()
cv2.destroyAllWindows()

在这个代码中:

  1. 通过取反 zs 坐标 (zs = [-landmark.z for landmark in landmarks]),使得骨骼点的 Z 轴方向与预期一致。
  2. 通过设置 ax3d.set_ylim([1, 0]) 来翻转 Y 轴的方向,以便更符合常见的视觉习惯。

运行这个脚本后,三维图中的骨骼结构应会显示为正常的人体姿态。
显示效果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/796686.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Telegram Bot、小程序开发(一)基础入门

文章目录 一、Telegram Bot是什么?二、Telegram Bot应用场景三、机器人是如何工作的?架构getUpdates 和 webhookswebhooks要求自签名证书 四、如何创建和使用Telegram Bot?整体步骤和流程Bot 的申请过程将机器人添加到 Telegram 群组 一、Tel…

函数(实参以及形参)

实际参数(实参) 实际参数就是在调用函数时传递给函数的具体值。这些值可以是常量、变量、表达式或更复杂的数据结构。实参的值在函数被调用时传递给对应的形参,然后函数内部就可以使用这些值来执行相应的操作。 int main() {int a 0;int b …

嵌入式人工智能应用-篇外-烧写说明

1 外部接线 1.1 前期准备 需要准备的工具 ⚫ 一根 Mini USB 线 ⚫ 嵌入式人工智能教学科研平台 ⚫ 12V DC 电源 ⚫ 一台电脑 1.2 接线 12V DC 电源接入 12V IN;Mini USB 线连接 USB OTG;如果有两条 Mini USB 线,可以接入 UART2 to USB 口…

git安装使用gitlab

第一步:下载git 第二步:安装 第三步:配置sshkey 第四步:处理两台电脑的sshkey问题 第一步下载git 网址:Git点Downloads根据你的操作系统选择对应的版本,我的是Windows,所以我选择了Windows …

动手学深度学习(Pytorch版)代码实践 -注意力机制-Transformer

68Transformer 1. PositionWiseFFN 基于位置的前馈网络 原理:这是一个应用于每个位置的前馈神经网络。它使用相同的多层感知机(MLP)对序列中的每个位置独立进行变换。作用:对输入序列的每个位置独立地进行非线性变换&#xff0c…

Open-TeleVision——通过VR沉浸式感受人形机器人视野:兼备远程控制和深度感知能力

前言 7.3日,我司七月在线(集AI大模型职教、应用开发、机器人解决方案为一体的科技公司)的「大模型机器人(具身智能)线下营」群里的一学员发了《Open-TeleVision: Teleoperation with Immersive Active Visual Feedback》这篇论文的链接,我当时快速看了一…

【网络文明】关注网络安全

在这个数字化时代,互联网已成为我们生活中不可或缺的一部分,它极大地便利了我们的学习、工作、娱乐乃至日常生活。然而,随着网络空间的日益扩大,网络安全问题也日益凸显,成为了一个不可忽视的全球性挑战。认识到网络安…

C双指针滑动窗口算法

这也许是双指针技巧的最⾼境界了,如果掌握了此算法,可以解决⼀⼤类⼦字符串匹配的问题 原理 1、我们在字符串 S 中使⽤双指针中的左右指针技巧,初始化 left right 0,把索引闭区间 [left, right] 称为⼀个「窗⼝」。 2、我们先…

开发个人Ollama-Chat--6 OpenUI

开发个人Ollama-Chat–6 OpenUI Open-webui Open WebUI 是一种可扩展、功能丰富且用户友好的自托管 WebUI,旨在完全离线运行。它支持各种 LLM 运行器,包括 Ollama 和 OpenAI 兼容的 API。 功能 由于总所周知的原由,OpenAI 的接口需要密钥才…

总结单例模式的写法

一、单例模式的概念 1.1 单例模式的概念 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。就是当前进程确保一个类全局只有一个实例。 1.2 单例模式的优…

首次跑通Arduino IDE + ESP8266

感触 网络,网络,还是网络。 中文开发者往往具备更多的网络知识和能力。 文档,文档,更是文档。 在计算机领域,遇到的问题,99.999%前人已经解决过。

Lesson 50 He likes ... But he doesn‘t like ...

Lesson 50 He likes … But he doesn’t like … 词汇 tomato n. 西红柿 复数:tomatoes 同义词:ketch-up 番茄酱     dead horse 例句:冰箱里有很多西红柿。    There are some tomatoes in the fridge. potato n. 土豆 复数&#…

【公益案例展】华为云X《无尽攀登》——攀登不停,向上而行

‍ 华为云公益案例 本项目案例由华为云投递并参与数据猿与上海大数据联盟联合推出的 #榜样的力量# 《2024中国数据智能产业最具社会责任感企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 夏伯渝,中国无腿登珠峰第一人,一生43年…

Redis持久化RDB,AOF

目 录 CONFIG动态修改配置 慢查询 持久化 在上一篇主要对redis的了解入门,安装,以及基础配置,多实例的实现:redis的安装看我上一篇: Redis安装部署与使用,多实例 redis是挡在MySQL前面的,运行在内存…

Java基础-I/O流

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 字节流 定义 说明 InputStream与OutputStream示意图 说明 InputStream的常用方法 说明 OutputStrea…

虚函数__

10 文章目录 虚函数虚函数表override(不允许后续函数继承)虚析构纯虚函数 虚函数 虚函数表 override(不允许后续函数继承) 虚析构 纯虚函数

C++的deque(双端队列),priority_queue(优先级队列)

deque deque是一个容器,是双端队列,从功能上来讲,deque是一个vector和list的结合体 顺序表和链表 deque的结构和优缺点 开辟buff小数组,空间不够了,不扩容,而是开辟一个新的小数组 开辟中控数组(指针数组)指向buff小数组 将已存在的数组指针存在中控数组中间,可以使用下标访…

【ARM】CCI集成指导整理

目录 1.CCI集成流程 2.CCI功能集成指导 2.1CCI结构框图解释 Request concentrator Transaction tracker Read-data Network Write-data Network B-response Network 2.2 接口注意项 记录一下CCI500的ACE slave interface不支持的功能: 对于ACE-Lite slav…

Java项目:基于SSM框架实现的中小型企业财务管理系统【ssm+B/S架构+源码+数据库+答辩PPT+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的中小型企业财务管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单…

【分库】分库的核心原则

目录 分库的核心原则 前言 分区透明性与一致性保证 弹性伸缩性与容错性设计 数据安全与访问控制机制 分库的核心原则 前言 在设计和实施分库策略时,遵循一系列核心原则是至关重要的,以确保系统不仅能够在当前规模下高效运行,还能够随着…