【保姆级教程】YOLOv8_Pose多类别关键点检测,姿态识别:训练自己的数据集

news2024/11/15 11:04:52

Yolov8官方给出的是单类别的人体姿态关键点检测,本文将记录如果实现训练自己的多类别的关键点检测。

一、YOLOV8环境准备

1.1 下载安装最新的YOLOv8代码

 仓库地址: https://github.com/ultralytics/ultralytics

1.2 配置环境

  pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple

二、数据准备

2.1 安装labelme标注软件

pip install labelme

2.1.2 打开roLabelImg软件

使用Anaconda Prompt启动labeme标注工具

在这里插入图片描述

2.2 标注自己的数据

在这里插入图片描述

2.3 数据转换

2.3.1 运行下面代码,将xml标签格式转为txt标签格式

关键点数量对齐

在这里插入图片描述

# 将labelme标注的json文件转为yolo格式
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
import glob
import json
import tqdm
# 物体类别

class_list = ["motorbike","car","cone"]
# 关键点的顺序
keypoint_list = ["11", "22", "33", "44","55", "66", "77", "88", "99"]
def json_to_yolo(img_data ,json_data):
    h ,w = img_data.shape[:2]
    # 步骤:
    # 1. 找出所有的矩形,记录下矩形的坐标,以及对应group_id
    # 2. 遍历所有的head和tail,记下点的坐标,以及对应group_id,加入到对应的矩形中
    # 3. 转为yolo格式
    rectangles = {}
    # 遍历初始化
    for shape in json_data["shapes"]:
        label = shape["label"] # pen, head, tail
        group_id = shape["group_id"] # 0, 1, 2, ...
        points = shape["points"] # x,y coordinates
        shape_type = shape["shape_type"]

        # 只处理矩形,读矩形
        if shape_type == "rectangle":
            if group_id not in rectangles:
                rectangles[group_id] = {
                "label": label,
                "rect": points[0] + points[1],  # Rectangle [x1, y1, x2, y2]
                "keypoints_list": []
        }
    # 遍历更新,将点加入对应group_id的矩形中,读关键点,根据group_id匹配
    for keypoint in keypoint_list:
        for shape in json_data["shapes"]:
            label = shape["label"]
            group_id = shape["group_id"]
            points = shape["points"]
            # 如果匹配到了对应的keypoint
            if label == keypoint:
                rectangles[group_id]["keypoints_list"].append(points[0])
            #else:
             #   rectangles[group_id]["keypoints_list"].append([0,0])

    # 转为yolo格式
    yolo_list = []
    for id, rectangle in rectangles.items():
        result_list  = []
        if rectangle['label'] not in class_list:
            continue
        label_id = class_list.index(rectangle["label"])
        # x1,y1,x2,y2
        x1 ,y1 ,x2 ,y2 = rectangle["rect"]
        # center_x, center_y, width, height
        center_x = (x1 +x2 ) /2
        center_y = (y1 +y2 ) /2
        width = abs(x1 -x2)
        height = abs(y1 -y2)
        # normalize
        center_x /= w
        center_y /= h
        width /= w
        height /= h

        # 保留6位小数
        center_x = round(center_x, 6)
        center_y = round(center_y, 6)
        width = round(width, 6)
        height = round(height, 6)

        # 添加 label_id, center_x, center_y, width, height
        result_list = [label_id, center_x, center_y, width, height]

        # 添加 p1_x, p1_y, p1_v, p2_x, p2_y, p2_v
        for point in rectangle["keypoints_list"]:
            x ,y = point
            x ,y = int(x), int(y)
            x /= w
            y /= h
            # 保留6位小数
            x = round(x, 6)
            y = round(y, 6)
            result_list.extend([x ,y ,2])
        if len(rectangle["keypoints_list"]) == 4:
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])

        if len(rectangle["keypoints_list"]) == 2:
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
            result_list.extend([0, 0, 0])
        
        yolo_list.append(result_list)
    return yolo_list
# 获取所有的图片
img_list = glob.glob("D:/study/cnn/yolo/yolov8-mokpt/ultralytics/data_mokpt/*.png")
for img_path in tqdm.tqdm( img_list ):

    img = cv2.imread(img_path)
    print(img_path)
    json_file = img_path.replace('png', 'json')
    with open(json_file) as json_file:
        json_data = json.load(json_file)

    yolo_list = json_to_yolo(img, json_data)
    yolo_txt_path = img_path.replace('png', 'txt')

    with open(yolo_txt_path, "w") as f:
        for yolo in yolo_list:
            for i in range(len(yolo)):
                if i == 0:
                    f.write(str(yolo[i]))
                else:
                    f.write(" " + str(yolo[i]))
            f.write("\n")
运行上面代码,就可以获得TXT格式标签文件

在这里插入图片描述

2.3.2 运行下面代码,检查txt标签转换是否正确

import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
import glob

img_path = "D:/study/cnn/yolo/yolov8-mokpt/ultralytics/data_mokpt/1.png"

plt.figure(figsize=(15, 10))
img = cv2.imread(img_path)
plt.imshow(img[:, :, ::-1])
plt.axis('off')

yolo_txt_path = img_path.replace('png', 'txt')
print(yolo_txt_path)

with open(yolo_txt_path, 'r') as f:
    lines = f.readlines()

lines = [x.strip() for x in lines]

label = np.array([x.split() for x in lines], dtype=np.float32)

# 物体类别
class_list = ["Free","Occupied","lane","stopline","zebracrossing","STR_arrow","L_arrow","R_arrow","Uturn_arrow","STR_L_arrow","STR_R_arrow","bidirwctional_arrow","three_arrow","special arrow"]


# 类别的颜色
class_color = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255, 0, 0), (0, 255, 0)]
# 关键点的顺序
keypoint_list = ["11", "22","11", "22"]
# 关键点的颜色
keypoint_color = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255, 0, 0), (0, 255, 0)]

# 绘制检测框
img_copy = img.copy()
h, w = img_copy.shape[:2]
for id, l in enumerate(label):
    # label_id ,center x,y and width, height
    label_id, cx, cy, bw, bh = l[0:5]
    label_text = class_list[int(label_id)]
    # rescale to image size
    cx *= w
    cy *= h
    bw *= w
    bh *= h

    # draw the bounding box
    xmin = int(cx - bw / 2)
    ymin = int(cy - bh / 2)
    xmax = int(cx + bw / 2)
    ymax = int(cy + bh / 2)
    cv2.rectangle(img_copy, (xmin, ymin), (xmax, ymax), class_color[int(label_id)], 2)
    cv2.putText(img_copy, label_text, (xmin, ymin - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, class_color[int(label_id)], 2)

# display the image
plt.figure(figsize=(15, 10))
plt.imshow(img_copy[:, :, ::-1])
plt.axis('off')
# save the image
cv2.imwrite("./tmp.png", img_copy)

img_copy = img.copy()
h, w = img_copy.shape[:2]
for id, l in enumerate(label):
    # label_id ,center x,y and width, height
    label_id, cx, cy, bw, bh = l[0:5]
    label_text = class_list[int(label_id)]
    # rescale to image size
    cx *= w
    cy *= h
    bw *= w
    bh *= h

    # draw the bounding box
    xmin = int(cx - bw / 2)
    ymin = int(cy - bh / 2)
    xmax = int(cx + bw / 2)
    ymax = int(cy + bh / 2)
    cv2.rectangle(img_copy, (xmin, ymin), (xmax, ymax), class_color[int(label_id)], 2)
    cv2.putText(img_copy, label_text, (xmin, ymin - 10), cv2.FONT_HERSHEY_SIMPLEX, 2, class_color[int(label_id)], 2)

    # draw 17 keypoints, px,py,pv,px,py,pv...
    for i in range(5, len(l), 3):
        px, py = l[i:i + 2]
        # rescale to image size
        px *= w
        py *= h
        # puttext the index
        index = int((i - 5) / 2)
        # draw the keypoints
        cv2.circle(img_copy, (int(px), int(py)), 10, (255,0,0), -1)
       # keypoint_text = "{}_{}".format(index, keypoint_list[index])
        #cv2.putText(img_copy, keypoint_text, (int(px), int(py) - 10), cv2.FONT_HERSHEY_SIMPLEX, 1,
         #           keypoint_color[int(index)], 2)

plt.figure(figsize=(15, 10))
plt.imshow(img_copy[:, :, ::-1])
plt.axis('off')
# save
cv2.imwrite('./tmp.png', img_copy)
cv2.imshow('tmp', img_copy)
cv2.waitKey(0)

可视化结果如下

在这里插入图片描述

ultralytics\ultralytics\路径下,新建data文件夹,将图片和标签按下面的结构摆放:
在这里插入图片描述

三、配置文件设置

3.1 新建multi-pose.yaml

ultralytics\ultralytics\data路径下,创建multi-pose.yaml:

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: E:/YOLO/yolov8-cone/ultralytics/data/images  # dataset root dir
train: train  # train images (relative to 'path') 210 images
val: val  # val images (relative to 'path') 53 images

# Keypoints
kpt_shape: [9, 3]  # number of keypoints, number of dims (2 for x,y or 3 for x,y,visible)
flip_idx: [0, 1, 2, 3,4,5,6,7,8,9]

# Classes
names:
  0: motorbike
  1: car
  2: cone

四、训练

4.1 下载预训练权重

在YOLOv8 github上下载预训练权重:yolov8n-pose.pt,ultralytics\ultralytics\路径下,新建weight文件夹,预训练权重放入其中。
在这里插入图片描述

4.2 训练

步骤一:修改ultralytics\ultralytics\cfg\default.yaml文件中的训练参数(根据自己的实际情况决定)
步骤二:执行下面代码:

from ultralytics import YOLO

# Load a model
model = YOLO('weights/yolov8n-pose.pt')  # load a pretrained model (recommended for training)

# Train the model
# results = model.train(data='data/animal-pose.yaml', epochs=20, imgsz=640)
results = model.train(data='data/multi-pose.yaml', epochs=100, imgsz=640)

五、验证

from ultralytics import YOLO
 
def main():
    model = YOLO(r'runs/pose/train/weights/best.pt')
    model.val(data='data/multi-pose.yaml', imgsz=1024, batch=4, workers=4)
if __name__ == '__main__':
    main()

六、推理

根据自己实际的情况,修改

# 测试图片
from ultralytics import YOLO
import cv2
import numpy as np
import sys

# 读取命令行参数
weight_path = 'E:/YOLO/yolov8-mokpt/ultralytics/runs/pose/best.pt'
media_path = "demo/bev_2_1034.png"

# 加载模型
model = YOLO(weight_path)

# 获取类别
objs_labels = model.names  # get class labels
print(objs_labels)

# 类别的颜色
class_color = [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0),(255, 0, 0), (0, 255, 0)]
# 关键点的顺序
class_list = ["motorbike","car","cone"]

# 关键点的颜色
keypoint_color = [(255, 0, 0), (0, 255, 0),(255, 0, 0), (0, 255, 0),(255, 0, 0), (0, 255, 0),(255, 0, 0), (0, 255, 0),(255, 0, 0), (0, 255, 0)]

# 读取图片
frame = cv2.imread(media_path)
frame = cv2.resize(frame, (frame.shape[1] // 2, frame.shape[0] // 2))
# rotate
# 检测
result = list(model(frame, conf=0.3, stream=True))[0]  # inference,如果stream=False,返回的是一个列表,如果stream=True,返回的是一个生成器
boxes = result.boxes  # Boxes object for bbox outputs
boxes = boxes.cpu().numpy()  # convert to numpy array

# 遍历每个框
for box in boxes.data:
    l, t, r, b = box[:4].astype(np.int32)  # left, top, right, bottom
    conf, id = box[4:]  # confidence, class
    id = int(id)
    # 绘制框
    cv2.rectangle(frame, (l, t), (r, b), (0, 0, 255), 2)
    # 绘制类别+置信度(格式:98.1%)
    cv2.putText(frame, f"{objs_labels[id]} {conf * 100:.1f}", (l, t - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                (0, 0, 255), 1)

# 遍历keypoints
keypoints = result.keypoints  # Keypoints object for pose outputs
keypoints = keypoints.cpu().numpy()  # convert to numpy array

# draw keypoints, set first keypoint is red, second is blue
for keypoint in keypoints.data:
    for i in range(len(keypoint)):
        x, y ,_ = keypoint[i]
        x, y = int(x), int(y)
        cv2.circle(frame, (x, y), 3, (0, 255, 0), -1)
        #cv2.putText(frame, f"{keypoint_list[i]}", (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, keypoint_color[i], 2)

    if len(keypoint) >= 2:
        # draw arrow line from tail to half between head and tail
        x0, y0 ,_= keypoint[0]
        x1, y1 ,_= keypoint[1]
        x2, y2 ,_= keypoint[2]
        x3, y3 ,_= keypoint[3]
        x4, y4 ,_= keypoint[4]
        x5, y5 ,_= keypoint[5]
        x6, y6 ,_= keypoint[6]
        x7, y7 ,_= keypoint[7]
        x8, y8 ,_= keypoint[8]


        cv2.line(frame, (int(x0), int(y0)), (int(x1), int(y1)), (255, 0, 255), 1)
        cv2.line(frame, (int(x1), int(y1)), (int(x2), int(y2)), (255, 0, 255), 1)
        cv2.line(frame, (int(x2), int(y2)), (int(x3), int(y3)), (255, 0, 255), 1)
        cv2.line(frame, (int(x3), int(y3)), (int(x4), int(y4)), (255, 0, 255), 1)
        cv2.line(frame, (int(x4), int(y4)), (int(x5), int(y5)), (255, 0, 255), 1)
        cv2.line(frame, (int(x5), int(y5)), (int(x6), int(y6)), (255, 0, 255), 1)
        cv2.line(frame, (int(x6), int(y6)), (int(x7), int(y7)), (255, 0, 255), 1)
        cv2.line(frame, (int(x7), int(y7)), (int(x8), int(y8)), (255, 0, 255), 1)
        cv2.line(frame, (int(x8), int(y8)), (int(x0), int(y0)), (255, 0, 255), 1)


        #center_x, center_y = (x1 + x2) / 2, (y1 + y2) / 2
       # cv2.arrowedLine(frame, (int(x2), int(y2)), (int(center_x), int(center_y)), (255, 0, 255), 4,
        #                line_type=cv2.LINE_AA, tipLength=0.1)

# save image
cv2.imwrite("result.jpg", frame)
print("save result.jpg")

在这里插入图片描述

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

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

相关文章

Python基于深度学习的中文情感分析系统,附源码

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

文心一言赋能问卷生成,打造高效问卷调研工具

当前,各种大语言模型(LLM,Large Language Model)井喷式发展,基于LLM的应用也不断涌现。但是,当开发者基于LLM开发下游应用时,LLM直接生成的结果在格式、内容等方面都存在许多不确定因素&#xf…

unity发布安卓获取读取权限

一、Player Settings 设置 Player Settings>Player>Other Settings> Android > Write Permission > External (SDCard). 二、代码 using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Andr…

【Unity】获取游戏对象或组件的常用方法

前言 在Unity开发过程中,我们经常需要获取组件,那么在Unity里如何获取组件呢? 一、获取游戏对象 1.GameObject.Find GameObject.Find 是通过物体的名称获取对象的 所以会遍历当前整个场景,效率较低 而且只能获取激活状态的物体…

GPT实战系列-LangChain的Prompt提示模版构建

GPT实战系列-LangChain的Prompt提示模版构建 LangChain GPT实战系列-LangChain如何构建基通义千问的多工具链 GPT实战系列-构建多参数的自定义LangChain工具 GPT实战系列-通过Basetool构建自定义LangChain工具方法 GPT实战系列-一种构建LangChain自定义Tool工具的简单方法…

生成微信小程序二维码

首页 -> 统计 可以通过上面二个地方配置,生成小程序的二维码,并且在推广分析里,有详细的分析数据,

spring-boot-starter-thymeleaf加载外部html文件

在Spring MVC中,我们可以使用Thymeleaf模板引擎来实现加载外部HTML文件。 1.Thymeleaf介绍 Thymeleaf是一种现代化的服务器端Java模板引擎,用于构建漂亮、可维护且易于测试的动态Web应用程序。它适用于与Spring框架集成,并且可以与Spring M…

LLM4Decompile: Decompiling Binary Code with Large Language Models

LLM4Decompile: Decompiling Binary Code with Large Language Models 相关链接:arxiv github 关键字:反编译、大型语言模型、二进制代码、源代码、程序语义 摘要 LLM4Decompile是一种使用大型语言模型(LLMs)进行二进制代码反编译…

【QED】斐波那契游戏

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 总结 题目 题目链接🔗 斐波那契数列指的是这样一个数列:1,1,2,3,5,8,13,21,34,55&#x…

视频技术1:使用ABLMediaServer推流rtsp

ABLMediaServer定位是高性能、高稳定、开箱即用、商用级别的流媒体服务器 下边展示了如何把1个mp3作为输入源,转换为rtsp流的过程。 作用:用rtsp模拟摄像头的视频流 1、启动ABLMediaServer ABLMediaServer-2024-03-13\WinX64\ABLMediaServer.exe 配…

电话机器人语音识别用哪家更好精准度更高。

语音识别系统的选择取决于你的具体需求,包括但不限于识别精度、速度、易用性、价格等因素。以下是一些在语音识别领域表现较好的公司和产品: 科大讯飞:科大讯飞是中国最大的语音识别技术提供商之一,其语音识别技术被广泛应用于各…

Linux的背景介绍

1.Linux的发展史 Linux,一般指GNU/Linux(单独的Linux内核并不可直接使用,一般搭配GNU套件,故得此称呼),是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯本纳第克特托瓦兹&#xff08…

人生就是不断炼心的一个过程,不断continental,不断挑战,重构。

回头看,轻舟已过万重山,早上,使用VSCODE,将以前的bootstrap响应式不断引入新元素。直接全部安装插件。如下图所示。 问题,遇到了github登录问题,还有就是git命令报错,域名hosts,404,nginx等知识…

STM32实验DMA数据搬运小助手

本次实验做的是将一个数组的内容利用DMA数据搬运小助手搬运到另外一个数组中去。 最后的实验结果: 可以看到第四行的数据就都不是0了,成功搬运了过来。 DMA实现搬运的步骤其实不是很复杂,复杂的是结构体参数: 整个步骤为&#xf…

配置视图解析器

配置视图解析器: 我们在指定视图的时候路径是有重复的,重复的操作可以用视图解析器,让框架帮我们: mv.setViewName("/WEB-INF/view/show.jsp");mv.setViewName("/WEB-INF/VIEW/other.jsp"); ​​​​​​​ …

前后端分离项目部署服务器教程--实践成功

文章目录 项目介绍流程1租界云服务2通过远程软件连接服务器3部署前后端代码停止功能文件 环境配置1.安装jdk2.安装Nginx3.安装mysql数据库 花了将近一天部署前后端的项目,写一个日志记录一下,话说孰能生巧。明天把服务器恢复初始在部署一下。 项目介绍 …

五、初识Django

初识Django 五、初识Django1.安装django2.创建项目2.1第一种方式:在终端2.2第二种方式:Pycharm 3.创建app4.快速上手4.1再写一个页面4.2templates模板4.3静态文件4.3.1static目录4.3.2引用静态文件 5.模板语法案例:伪联通新闻中心6.请求和相应…

使用JAXB生成XML的Java对象

文章目录 标题使用JAXB生成XML的Java对象根据xml生成xsd文件:下载trang.jar:使用trang.jar生成xml的xsd文件: 使用JAXB的xjc生成java对象: 标题使用JAXB生成XML的Java对象 根据xml生成xsd文件: 下载trang.jar&#x…

ElasticSearch 用法

首先讲下 ES的倒排序索引 入门-倒排索引 正排索引(传统) idcontent1001my name is zhang san1002my name is li si 倒排索引 keywordidname1001, 1002zhang1001 正排索引:我想查name,这时候是模糊的查询,会循环遍历…

C++开发基础——函数模板

一,函数模板 1.基础概念 模板编程是C中泛型编程的基础。 一个模板可以是创建类或者函数的蓝图。 模板编程分两种,分别是算法抽象的模板、数据抽象的模板。算法抽象的模板以函数模板为主,数据抽象的模板以类模板为主。 基于函数模板生成的…