计算机视觉——基于YOLOV8 的人体姿态估计训练与推理

news2025/4/15 22:04:21

概述

自 Ultralytics 发布 YOLOV5 之后,YOLO 的应用方向和使用方式变得更加多样化且简单易用。从图像分类、目标检测、图像分割、目标跟踪到关键点检测,YOLO 几乎涵盖了计算机视觉的各个领域,似乎已经成为计算机视觉领域的“万能工具”。

YOLOV8 姿态估计

人体姿态估计(Human Pose Estimation,简称 HPE)是计算机视觉中的一个重要任务,它旨在检测图像或视频中人体的关键点位置,如头部、四肢和躯干等部位的坐标。YOLO 官方针对 HPE 的模型会在名称后加上 “-pose”,例如 YOLOv8n-pose。目前提供的 HPE 预训练模型是基于 COCO 数据集的 17 个关键点训练而成,具体如下图所示:

COCO 关键点

COCO 数据集的关键点分布如下:

  • 头部和面部:鼻子、左眼、右眼、左耳、右耳,共 5 个关键点。
  • 上肢:左肩、右肩、左肘、右肘、左腕、右腕,共 6 个关键点。
  • 下肢:左髋、右髋、左膝、右膝、左踝、右踝,共 6 个关键点。
  • 躯干:左髋和右髋连接到肩膀,形成躯干的轮廓。

目前 YOLOV8 提供的最大尺寸模型为 YOLOV8X-p6,其输入图像尺寸为 1280×1280,mAP(平均精度)较高,但参数量比 YOLOV8 大了近 30 倍,计算量增加了 118 倍。这种模型虽然精度高,但在实际应用中需要权衡计算资源和实时性。

训练自己的 HPE 模型

Ultralytics 将姿态估计的训练过程封装得非常简单,使得用户可以轻松地训练自己的 HPE 模型。如果需要训练自己的 HPE 模型,可以参考 COCO 数据集中关键点的标注方法,并添加自己的标注图像。COCO 数据集的 17 个关键点标注规则如下:

  • 单数编号:表示身体的左侧部位(如左肩、左肘等)。
  • 双数编号:表示身体的右侧部位(如右肩、右肘等)。

训练示例代码

以下是使用 Ultralytics 提供的 YOLOV8 进行姿态估计模型训练的示例代码:

from ultralytics import YOLO

# 三种训练方式
# 训练一个全新的 YOLOV8N HPE 模型
model = YOLO('yolov8n-pose.yaml')

# 载入预训练模型进行训练(推荐方式)
model = YOLO('yolov8n-pose.pt')

# 与上一种方式相同,先加载配置文件再加载预训练权重
model = YOLO('yolov8n-pose.yaml').load('yolov8n-pose.pt')

# 开始训练
model.train(data='coco8-pose.yaml', epochs=100, imgsz=640)

在训练过程中,需要指定数据集的配置文件(如 coco8-pose.yaml),其中包含数据集的路径、类别信息等。epochs 参数表示训练的轮数,imgsz 参数表示输入图像的尺寸。

直接使用预训练模型进行推理

YOLOV8 官方发布的预训练模型已经能够提供非常不错的目标检测和姿态估计效果。以下是如何直接使用这些预训练模型进行推理的示例。

官方推理示例

from ultralytics import YOLO

# 加载模型
model = YOLO('yolov8n-pose.pt')  # 加载官方预训练模型
# model = YOLO('path/to/best.pt')  # 加载自定义训练的模型

# 使用模型进行推理
results = model('https://ultralytics.com/images/bus.jpg')  # 对图像进行推理

获取关键点的详细信息

如果需要获取推理结果中各个关键点的详细信息,可以参考以下代码:

# 定义关键点索引与名称的对应关系
dic_points = {
    0: 'nose', 1: 'left_eye', 2: 'right_eye', 3: 'left_ear', 4: 'right_ear',
    5: 'left_shoulder', 6: 'right_shoulder', 7: 'left_elbow', 8: 'right_elbow',
    9: 'left_wrist', 10: 'right_wrist', 11: 'left_hip', 12: 'right_hip',
    13: 'left_knee', 14: 'right_knee', 15: 'left_ankle', 16: 'right_ankle'
}

# 加载模型并进行推理
model = YOLO('yolov8n-pose.pt')
results = model('path/to/image.jpg')

# 遍历检测结果
for r in results:
    boxes = r.boxes  # 获取边界框
    kps = r.keypoints  # 获取关键点

    # 遍历每个检测到的人体实例
    for p in kps:
        list_p = p.data.tolist()  # 将关键点数据转换为列表

        # 遍历每个关键点
        for i, point in enumerate(list_p):
            # 打印关键点的索引和坐标
            print(f"Keypoint {i} ({dic_points[i]}): ({int(point[0])}, {int(point[1])})")

关键点的可视化

为了更直观地展示姿态估计的结果,可以通过绘制关键点和连接线来可视化人体姿态。以下是一些示例代码,展示如何绘制头部、躯干、上肢、下肢和脊椎的关键点。

头部关键点

头部的关键点包括双耳、眼睛和鼻子,共 5 个点。以下代码展示了如何绘制这些关键点及其连接线:

import cv2
import numpy as np

def draw_head(img, list_p):
    # 绘制耳朵、眼睛和鼻子的关键点
    for p in list_p[:5]:
        cv2.circle(img, (int(p[0]), int(p[1])), 8, (0, 255, 0), -1)

    # 绘制眼睛之间的连接线
    start = (int(list_p[1][0]), int(list_p[1][1]))
    end = (int(list_p[2][0]), int(list_p[2][1]))
    cv2.line(img, start, end, (0, 0, 255), 2)

    # 绘制鼻子到眼睛中点的连接线
    start = (int((list_p[1][0] + list_p[2][0]) / 2), int((list_p[1][1] + list_p[2][1]) / 2))
    end = (int(list_p[0][0]), int(list_p[0][1]))
    cv2.line(img, start, end, (0, 0, 255), 2)

    # 绘制耳朵之间的连接线
    start = (int(list_p[3][0]), int(list_p[3][1]))
    end = (int(list_p[4][0]), int(list_p[4][1]))
    cv2.line(img, start, end, (0, 0, 255), 2)

    return img

躯干关键点

躯干的关键点包括肩膀和臀部,共 4 个点。以下代码展示了如何绘制这些关键点及其连接线:

def draw_body(img, list_p):
    points = []
    # 绘制肩膀和臀部的关键点
    for p in [list_p[5], list_p[6], list_p[11], list_p[12]]:
        cv2.circle(img, (int(p[0]), int(p[1])), 12, (0, 255, 0), -1)
        point = (int(p[0]), int(p[1]))
        points.append(point)

    # 将关键点连接成多边形
    points = np.array(points)
    points =
 points.reshape((-1, 1, 2))
    isClosed = True
    color = (0, 0, 255)
    thickness = 3
    img = cv2.polylines(img, [points], isClosed, color, thickness)

    return img

上肢关键点

上肢的关键点包括肩膀、手肘和手腕,共 6 个点。以下代码展示了如何绘制这些关键点及其连接线:

def draw_upper(img, list_p):
    # 绘制左上肢的关键点和连接线
    for i, p in enumerate([list_p[5], list_p[7], list_p[9]]):
        cv2.circle(img, (int(p[0]), int(p[1])), 8, (0, 255, 0), -1)
    lines = [(5, 7), (7, 9)]
    for n in lines:
        start = (int(list_p[n[0]][0]), int(list_p[n[0]][1]))
        end = (int(list_p[n[1]][0]), int(list_p[n[1]][1]))
        cv2.line(img, start, end, (0, 0, 255), 3)

    # 绘制右上肢的关键点和连接线
    for i, p in enumerate([list_p[6], list_p[8], list_p[10]]):
        cv2.circle(img, (int(p[0]), int(p[1])), 8, (0, 255, 0), -1)
    lines = [(6, 8), (8, 10)]
    for n in lines:
        start = (int(list_p[n[0]][0]), int(list_p[n[0]][1]))
        end = (int(list_p[n[1]][0]), int(list_p[n[1]][1]))
        cv2.line(img, start, end, (0, 0, 255), 3)

    return img

下肢关键点

下肢的关键点包括臀部、膝盖和脚踝,共 6 个点。以下代码展示了如何绘制这些关键点及其连接线:

def draw_lower(img, list_p):
    # 绘制左下肢的关键点和连接线
    for i, p in enumerate([list_p[11], list_p[13], list_p[15]]):
        cv2.circle(img, (int(p[0]), int(p[1])), 8, (0, 255, 0), -1)
    lines = [(11, 13), (13, 15)]
    for n in lines:
        start = (int(list_p[n[0]][0]), int(list_p[n[0]][1]))
        end = (int(list_p[n[1]][0]), int(list_p[n[1]][1]))
        cv2.line(img, start, end, (0, 0, 255), 3)

    # 绘制右下肢的关键点和连接线
    for i, p in enumerate([list_p[12], list_p[14], list_p[16]]):
        cv2.circle(img, (int(p[0]), int(p[1])), 8, (0, 255, 0), -1)
    lines = [(12, 14), (14, 16)]
    for n in lines:
        start = (int(list_p[n[0]][0]), int(list_p[n[0]][1]))
        end = (int(list_p[n[1]][0]), int(list_p[n[1]][1]))
        cv2.line(img, start, end, (0, 0, 255), 3)

    return img

脊椎关键点

脊椎的关键点可以通过连接鼻子、肩膀中心和臀部中心来表示。以下代码展示了如何绘制这些关键点及其连接线:

def draw_spine(img, list_p):
    # 计算肩膀中心点
    shoulder_center = ((list_p[5][0] + list_p[6][0]) / 2, (list_p[5][1] + list_p[6][1]) / 2)
    # 计算臀部中心点
    hip_center = ((list_p[11][0] + list_p[12][0]) / 2, (list_p[11][1] + list_p[12][1]) / 2)

    # 绘制关键点
    cv2.circle(img, (int(shoulder_center[0]), int(shoulder_center[1])), 12, (0, 255, 0), -1)
    cv2.circle(img, (int(hip_center[0]), int(hip_center[1])), 12, (0, 255, 0), -1)

    # 绘制连接线
    cv2.line(img, (int(list_p[0][0]), int(list_p[0][1])), (int(shoulder_center[0]), int(shoulder_center[1])), (0, 0, 255), 3)
    cv2.line(img, (int(shoulder_center[0]), int(shoulder_center[1])), (int(hip_center[0]), int(hip_center[1])), (0, 0, 255), 3)

    return img

应用场景

将所有关键点和连接线绘制在一起,可以得到完整的人体姿态估计结果,如下图所示:
在这里插入图片描述

这种姿态估计技术可以应用于多种场景,例如:

  • 人员识别:在监控视频中识别人员的行走姿态,即使面部模糊或较小,也能通过姿态特征进行识别。
  • 运动分析:分析运动员的动作,帮助教练进行技术指导。
  • 康复治疗:辅助医生评估患者的康复情况,通过姿态变化监测康复进度。

总结

通过 YOLOV8 的姿态估计功能,我们可以轻松地检测图像或视频中人体的关键点,并将其可视化。这为计算机视觉领域的多种应用提供了强大的支持。未来,我们可以进一步探索如何利用这些关键点信息来提高人员识别的准确性,或者将其应用于其他更具挑战性的任务中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙小案例---心情日记

效果演示 代码实现 import { router, window } from kit.ArkUIEntry Component struct Index {async aboutToAppear(): Promise<void> {let w await window.getLastWindow(getContext())w.setWindowSystemBarProperties({statusBarColor: #00C6C3,statusBarContentColo…

el-tree 实现树形菜单子级取消选中后父级选中效果不变

背景 在复杂的企业级管理系统中,树形菜单是一种常见的数据展示和交互组件。传统的树形菜单通常存在以下交互局限: 子节点取消选中时,父节点会自动取消选中无法满足复杂的权限分配和数据筛选场景实际应用场景: 组织架构权限管理多层级资源分配复杂的数据筛选与展示实现需求…

Java虚拟机——JVM(Java Virtual Machine)解析一

1.JVM是什么&#xff1f; 1.1 JVM概念 Java Virtual Machine (JVM) 是JDK的核心组件之一&#xff0c;它使得 Java 程序能够在任何支持 JVM 的设备或操作系统上运行&#xff0c;而无需修改源代码 JDK是什么&#xff0c;JDK和JVM是什么关系&#xff1f;1.Java IDE(Integrated …

【源码】SpringMvc源码分析

文章目录 SpringMVC 基础回顾​核心组件源码分析​DispatcherServlet​HandlerMapping​HandlerAdapter​ViewResolver​ 请求处理流程源码解析​ 在当今的 Java Web 开发领域&#xff0c;SpringMVC 无疑是最为广泛应用的 Web 框架之一。它以其强大的功能、灵活的配置以及高度的…

tcp特点+TCP的状态转换图+time_wait详解

tcp特点TCP的状态转换图time wait详解 目录 一、tcp特点解释 1.1 面向连接 1.1.1 连接建立——三次握手 1.1.2 连接释放——四次挥手 1.2 可靠的 1.2.1 应答确认 1.2.2 超时重传 1.2.3 乱序重排 1.2.4 去重 1.2.5 滑动窗口进行流量控制 1.3 流失服务&#xff08;字节…

高支模自动化监测解决方案

1.行业现状 高大模板支撑系统在浇筑施工过程中&#xff0c;诸多重大安全风险点进行实时自动化安全监测的解决方案主要监测由于顶杆失稳、扣件失效、承压过大等引起的支撑轴力、模板沉降、相对位移、支撑体系倾斜等参数变化。系统采用无线自动组网、高频连续采样&#xff0c;实时…

OpenCV 图形API(24)图像滤波-----双边滤波函数bilateralFilter()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 应用双边滤波到图像。 该函数对输入图像应用双边滤波&#xff0c;如 http://www.dai.ed.ac.uk/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Fil…

HarmonyOS中的多线程并发机制

目录 多线程并发1. 多线程并发概述2 多线程并发模型3 TaskPool简介4 Worker简介4.1 Woker注意事项4.2 Woker基本用法示例 5. TaskPool和Worker的对比5.1 实现特点对比5.2 适用场景对比 多线程并发 1. 多线程并发概述 并发模型是用来实现不同应用场景中并发任务的编程模型&…

【随手笔记】QT避坑一(串口readyRead信号不产生)

问题描述&#xff1a; 使用QT5.15.2版本 测试串口readyRead绑定槽函数&#xff0c;接收到数据后 不能触发 试了很多网友的程序&#xff0c;他们的发布版本可以&#xff0c;但是源码我编译后就不能触发&#xff0c;判断不是代码的问题 看到有人提到QT版本的问题&#xff0c;于…

【产品】ToB产品需求分析

需求分析流程 合格产品经理 帮助用户、引导用户、分析需求、判断需求、设计方案 不能苛求用户提出合理、严谨的需求&#xff0c;这不是用户的责任和义务&#xff0c;而应该通过自己的专业能力来完成需求的采集工作 #mermaid-svg-ASu8vocank48X6FI {font-family:"trebuche…

驱动开发硬核特训 · Day 10 (理论上篇):设备模型 ≈ 运行时的适配器机制

&#x1f50d; B站相应的视屏教程&#xff1a; &#x1f4cc; 内核&#xff1a;博文视频 - 总线驱动模型实战全解析 敬请关注&#xff0c;记得标为原始粉丝。 在 Linux 驱动开发中&#xff0c;设备模型&#xff08;Device Model&#xff09;是理解驱动架构的核心。而从软件工程…

flutter 打包mac程序 dmg教程

✅ 前提条件 ✅ 你已经在 macOS 上安装了 Android Studio Flutter SDK。 ✅ Flutter 支持 macOS 构建。 运行下面命令确认是否支持&#xff1a; Plain Text bash 复制编辑 flutter doctor ---## &#x1f9f1; 第一步&#xff1a;启用 macOS 支持如果是新项目&#xff0c;…

【数据结构与算法】——堆(补充)

前言 上一篇文章讲解了堆的概念和堆排序&#xff0c;本文是对堆的内容补充 主要包括&#xff1a;堆排序的时间复杂度、TOP 这里写目录标题 前言正文堆排序的时间复杂度TOP-K 正文 堆排序的时间复杂度 前文提到&#xff0c;利用堆的思想完成的堆排序的代码如下&#xff08;包…

atypica.AI:用「语言模型」为「主观世界」建模

人们不是在处理概率&#xff0c;而是在处理故事。 —— 丹尼尔卡尼曼 People dont choose between things, they choose between descriptions of things. —— Daniel Kahneman 商业研究是一门理解人类决策的学问。人并不只是根据纯粹理性做决策&#xff0c;而是受到叙事、情…

LLaMA-Factory双卡4090微调DeepSeek-R1-Distill-Qwen-14B医学领域

unsloth单卡4090微调DeepSeek-R1-Distill-Qwen-14B医学领域后&#xff0c;跑通一下多卡微调。 1&#xff0c;准备2卡RTX 4090 2&#xff0c;准备数据集 医学领域 pip install -U huggingface_hub export HF_ENDPOINThttps://hf-mirror.com huggingface-cli download --resum…

【WPF】自定义控件:ShellEditControl-同列单元格编辑支持文本框、下拉框和弹窗

需要实现表格同一列&#xff0c;单元格可以使用文本框直接输入编辑、下拉框选择和弹窗&#xff0c;文本框只能输入数字&#xff0c;弹窗中的数据是若干位的二进制值。 本文提供了两种实现单元格编辑状态下&#xff0c;不同编辑控件的方法&#xff1a; 1、DataTrigger控制控件的…

Seq2Seq - GRU补充讲解

nn.GRU 是 PyTorch 中实现门控循环单元&#xff08;Gated Recurrent Unit, GRU&#xff09;的模块。GRU 是一种循环神经网络&#xff08;RNN&#xff09;的变体&#xff0c;用于处理序列数据&#xff0c;能够更好地捕捉长距离依赖关系。 ⭐重点掌握输入输出部分输入张量&#…

从零开始学Python游戏编程19-游戏循环模式1

在《从零开始学Python游戏编程18-函数3》中提到&#xff0c;可以对游戏代码进行重构&#xff0c;把某些代码写入函数中&#xff0c;主程序再调用这些函数&#xff0c;这样使得代码程序更容易理解和维护。游戏循环模式实际上也是把代码写入到若干个函数中&#xff0c;通过循环的…

Java获取终端设备信息工具类

在很多场景中需要获取到终端设备的一些硬件信息等&#xff0c;获取的字段如下&#xff1a; 返回参数 参数含义备注systemName系统名称remoteIp公网iplocalIp本地ip取IPV4macmac地址去掉地址中的"-“或”:"进行记录cpuSerialcpu序列号hardSerial硬盘序列号drive盘符…

【Linux网络与网络编程】08.传输层协议 UDP

传输层协议负责将数据从发送端传输到接收端。 一、再谈端口号 端口号标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中&#xff0c;用 "源IP"&#xff0c;"源端口号"&#xff0c;"目的 IP"&#xff0c;"目的端口号"&…