yolov8 keypoint detection + tracking learning record

最前面的说明

这里keypoint 没有带上connection 直接检测关键点的

keypoint detection  

标注

 CVAT​​​​​

(该工具 需要手动补充visible) 按照cvat 绿色字体 先走一遍关键点检测流程    标注直接按照coco annotator进行标注      结尾 coco annotator标注过程

步骤:

Project—create a new project—Name-Add label—submit&open—create a new task

Name—Submit&continue—打开创建的task—点击Job—开始标注

确定点数—shape——keypoints & bbox(除了关键点还需要绘制bbox)——格式导出 xml文件

标注导出格式:coco keypoint 1.0(但不起作用)还是选择用CVAT for images1.1 再转换格式

     (转换代码在github中 CVAT_to_cocoKeypoints.py 更改xml 及需要输出的路径即可)

补充:coco key point格式: classnum + bbox(yolo)+   points [ x y v(visible flag) ]

注:cvat 不支持 关键点是否可见 即 v没有 (我选择 手动在txt中里面添加 2 全部都可见

  (需要使用另外的标注工具  coco annotator)

直接运行会出现如下报错      labels require 29 columns each (1 + 4 + 8*3) 但实际上cvat只有xy

文件结构

yolov8根目录    F:\want-fish\pose-detection-keypoints-estimation-yolov8-origin

            data/images/train  val     data/labels/train  val    按照比例划分train  val文件夹

class.names NAMES文件   按照自己的关键点修改class.names文件

config.yaml 修改地址 关键点数量 类别名称  filp_idx

train.py  修改train.py  epochs

到官网  在根目录下下载yolov8n.pt  yolov8n-pose.pt

代码

GitHub代码地址

  • config.yaml 

        其中 keypoints 的 flip_idx参数解释:当图像水平翻转时,索引该如何翻转

    同一个图片 数据增强-水平翻转 涉及到右耳变左耳   因此该参数列表 将涉及到左右的进行互换,其余保持不动

(我的数据集只考虑一边的话 是不需要区分左右的 默认左右一致)[0,1,2,3,4,5,6,7]

  •  train.py 
from ultralytics import YOLO

model = YOLO('yolo8n-pose.pt')

model.train(data='config.yaml', epochs=500 ,imgsz=540, device=0)

说明

训练完毕,查看损失函数图像,重点关注与姿势相关的损失函数     损失函数模型可以优化吗 最近有新的pose网络和损失函数吗

  • inference.py 
from ultralytics import YOLO
import cv2


model_path = '/media/veracrypt2/computer_vision/47_pose_detection_yolov8/code/runs/pose/train9/weights/last.pt'

image_path = './samples/wolf.jpg'
img = cv2.imread(image_path)

model = YOLO(model_path)

results = model(image_path)[0]

for result in results:
    for keypoint_indx, keypoint in enumerate(result.keypoints.tolist()):
        cv2.putText(img, str(keypoint_indx), (int(keypoint[0]), int(keypoint[1])),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

cv2.imshow('img', img)
cv2.waitKey(0)
视频中作者的图
结果图(300epochs)使用yolo终端predict

inference.py出现了一点报错

由于生成了两个错误的bbox框 且两个框的keypoints的位置大概一致,暂时将inference.py的代码改为如下,直接去掉最外面的for 循环 只取第一维的结果   后续使用自己的数据集 再将for循环加上

from ultralytics import YOLO
import cv2


model_path = 'F:/want-fish/pose-detection-keypoints-estimation-yolov8-origin/runs/pose/train22/weights/last.pt'

image_path = './samples_data/cow.jpg'
img = cv2.imread(image_path)

model = YOLO(model_path)

results = model(image_path)[0]

for keypoint_indx, keypoint in enumerate(results.keypoints.xy.tolist()[0]):
    cv2.putText(img, str(keypoint_indx), (int(keypoint[0]), int(keypoint[1])),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

cv2.imshow('img', img)
cv2.waitKey(0)

暂时得到下图:  (列表维度 真的不熟练 5555555555)

加上外圈for循环: (results.keypoints.balabala  不应该放在内层result里面)

for result in results.keypoints.xy.tolist():
    for keypoint_indx, keypoint in enumerate(result):

me:prompt利用yolo终端进行predict     bbox预测有问题(查看原视频评论区发现作者标注文件中的bbox有点问题)

yolo task=pose mode=predict source='./samples_data/cow.jpg' model='F:/want-fish/pose-detection-keypoints-estimation-yolov8-origin/runs/pose/train22/weights/last.pt'
keypoints测试效果说明

原up的四足动物 数据集 train 8000多 val 1000多  关键点还算比较清楚

me: 训练了2次 两个数据集 每个数据集中只有一个类别  图像数量:54(40+14)   73(59+13)

       还是偏了一点点 ,所以还需要补充大量的数据集进行标注(卑微.jpg)

tracking

测试代码 

说明:该代码使用cv2窗口查看测试结果;

me: Roboflow标注 +  prompt终端

        训练:

yolo task=detect mode=train model=yolov8n.pt data=datasets/data.yaml batch=16 epochs=5000 imgsz=640 device=0

        测试:使用训练后的detect模型进行测试并保存视频追踪文件

yolo track model=F:\want-fish\ultralytics-main\runs\detect\train3\weights\best.pt source='2030fish.mp4' save=True

GitHub代码地址

from ultralytics import YOLO
import cv2


# load yolov8 model
model = YOLO('yolov8n.pt')

# load video
video_path = './test.mp4'
cap = cv2.VideoCapture(video_path)

ret = True
# read frames
while ret:
    ret, frame = cap.read() 

    if ret:

        # detect objects
        # track objects
        results = model.track(frame, persist=True)

        # plot results
        # cv2.rectangle
        # cv2.putText
        frame_ = results[0].plot() # 因为我们只在1帧中进行追踪

        # visualize
        cv2.imshow('frame', frame_)
        if cv2.waitKey(25) & 0xFF == ord('q'):  #等待25ms 按q退出
            break
  • read方法 返回一个布尔值 且返回一个新帧
    • ret, frame = cap.read()    #  到视频最后一帧时,ret返回值False frame返回值None 
  • yolov8使用一句话同时进行detect & track
  • model.track(frame, persist=True) 
    • 启用目标持久性意味着目标追踪器会尝试在连续的帧中持续追踪目标,即使在某些帧中目标被遮挡或移出视野。这对于处理短暂的遮挡或目标出现/消失的情况非常有用。

  • 两种绘图方式  cv2.rectangle  cv2.putText
                           frame_ = results[0].plot() 

Keypoint pose 训练

本地4060

补充说明:GPU 几乎0% 

         但实际上GPU还是有在使用的

         我设置device=‘0’  (device=0同) 但是任务管理器查看的gpu & nvidia-smi 如下

搜了半天:Pytorch使用cuda后,任务管理器GPU的利用率还是为0?

        其中的法一  将任务管理器-性能-GPU的3D 换成CUDA进行查看  别的帖子说设置要重启电脑 暂时无法确认   (图形设置——更改默认图形设置——关闭 硬件加速gpu计划)

       其中法二 我的Volatile GPU-Util显示80% 表明GPU还是在用的  瞬时再查看 可以到100%

中断后继续训练
yolo task=pose mode=train model=F:\want-fish\pose-detection-keypoints-estimation-yolov8-origin\runs\pose\train\weights\last.pt data=config.yaml epochs=100 batch=16 save=True resume=True

Google Colab+ Drive 云端训练    (还没有尝试)

Drive上传数据

其他标注工具说明:

1.labelme   

无法标注关键点是否可见,默认为1.00000,后续将其全部更改为2.00000

2.coco annotator

安装

补充上一行中原up没有说到的:

  • 到网页里图片集都scan出来之后,点击一张图像进入标注页面
  • 开始标注时没有+号 显示No categories have been enabled for this image.  要在datasets的添加默认类别

  • 一个图像文件夹export coco 导出一个json文件 用以下代码转换为coco keypoint的格式(注意txt中的坐标需要normalize  有个憨憨一开始没有注意到)
    import json
    import os
    
    def json_to_yolo(json_path, output_folder, image_folder):
        with open(json_path, 'r') as json_file:
            data = json.load(json_file)
    
        for image_info in data['images']:
            image_id = image_info['id']
            annotations = [anno for anno in data['annotations'] if anno['image_id'] == image_id]
            if annotations:
                image_name = image_info['file_name']
                image_path = os.path.join(image_folder, image_name)
                image_width, image_height = get_image_size(image_path)
                
                txt_content = coco_to_yolo(annotations, image_width, image_height)
                txt_path = os.path.join(output_folder, f"{os.path.splitext(image_name)[0]}.txt")
    
                with open(txt_path, 'w') as txt_file:
                    txt_file.write(txt_content)
    
    def get_image_size(image_path):
        # 使用 OpenCV 获取图像的宽度和高度
        import cv2
        image = cv2.imread(image_path)
        return image.shape[1], image.shape[0]
    
    def coco_to_yolo(annotations, image_width, image_height):
        txt_content = ""
        for annotation in annotations:
            category_id = annotation['category_id'] - 1  # 将类别 ID 减去 1
            bbox = annotation['bbox']
    
            # Convert COCO format bbox to YOLO format
            yolo_bbox = coco_bbox_to_yolo(bbox, image_width, image_height)
    
            keypoints = annotation['keypoints']
            keypoints_normalized = normalize_keypoints(keypoints, image_width, image_height)
    
            # Create YOLO format txt content
            txt_content += f"{category_id} {' '.join(map(str, yolo_bbox))} {' '.join(map(str, keypoints_normalized))}\n"
    
        return txt_content
    
    def coco_bbox_to_yolo(bbox, image_width, image_height):
        x, y, width, height = bbox
        center_x = x + width / 2
        center_y = y + height / 2
    
        yolo_x = center_x / image_width
        yolo_y = center_y / image_height
        yolo_width = width / image_width
        yolo_height = height / image_height
    
        return yolo_x, yolo_y, yolo_width, yolo_height
    
    def normalize_keypoints(keypoints, image_width, image_height):
        normalized_keypoints = []
    
        for i in range(0, len(keypoints), 3):
            x = keypoints[i]
            y = keypoints[i + 1]
            v = keypoints[i + 2]
    
            normalized_x = x / image_width
            normalized_y = y / image_height
    
            normalized_keypoints.extend([normalized_x, normalized_y, v])
    
        return normalized_keypoints
    
    json_path = "E:\\下载\\fish01-1.json"  # 替换为你的JSON文件路径
    output_folder = "E:\\桌面\\labels"  # 替换为你要保存TXT文件的文件夹路径
    image_folder = "F:\\want-fish\\coco-annotator\\datasets\\fish01"  # 替换为你的图像文件夹路径
        
    
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)
    
    json_to_yolo(json_path, output_folder, image_folder)

PS  最后的最后:1 tracking部分 没有用github中的代码 直接 终端 yolo

                        2 google drive自己跑的时候 有报错 好像还要搞一下环境  没做

  • 26
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值