YOLOv8 目标跟踪(OTB100 数据集)

本贴最后更新于 473 天前,其中的信息可能已经渤澥桑田

前言

基于 OTB100 数据集做目标跟踪,提供评价指标

chatGPT 写的代码,难看但是能用

参考:单目标跟踪数据集 | J. Xu (xujinzh.github.io)[YOLOv8] - YOLO 数据集格式介绍和案例-CSDN 博客

数据

YOLOv8

地址

image

YOLO 数据集的格式主要包括以下几部分(注意:除扩展名外,标注文件的名称必须和图像的名称保持一致哦):

  • 图像文件: 这是数据集中的图像文件,通常是 jpg 或 png 格式。

  • 标注文件: 这是一个文本文件,包含了每张图像中目标对象的类别和位置信息

    主要包含了以下内容:

    • 每个目标对象的类别编号

    • 目标对象在图像中的中心位置 (x,y)

    • 目标对象的宽度和高度 (w,h)

      image

      1) 列 1 - 目标类别 id , 列 2 - 目标中心位置 x, 列 3 - 目标中心位置 y, 列 4 - 目标宽度 w,列 5 - 目标高度 h。

      2)x,y,w,h 是小于 1 的浮点数,因为是经过对图像进行了归一化处理得到的值,也就是目标的真实的 x,w 值除以图像的宽度,y,h 除以图像的高度。

  • 类别文件: 这是一个文本文件,包含了数据集中所有目标对象的类别信息。

    备注:一行代表一个类别,行号代表类别 id,比如 normal 是类别名称,它在第四行,那么它的类别 id 为 3(索引从 0 开始),比如上面的显示的图像的标注文件,有 2 个类别为 normal 的目标。

    image

OTB100

image

OTB 数据集是单目标跟踪最早数据集。分为 OTB-2013(51 个视频)、OTB-2015 (在 OTB-2013 上增加视频,共 98 个视频,又名 OTB-100),其中 OTB-100 前 49 个视频又名 OTB-50. 虽然 OTB-100 只有 98 个视频,但是,其中两个视频 Skating2 和 Jogging 分别针对两个目标进行标注,可分别看作 2 个视频。因此,称为 OTB-100. 其中 Skating2 在 OTB-50 中,因此 OTB-50 事实上也包含 50 个标注视频。

官方数据集下载地址:OTB Dataset | Papers With Code

类别:10(OTB-2013), 16(OTB-2015)

图像:OTB-50 (官网前 49 个视频,其中 Skating2 为 2 个);OTB-100 (TB-50 加上官网上后 49 个视频,其中 Jogging 为 2 个)

大小:1.3GB(OTB-50)、2.6GB(OTB-100)

注释:groundtruth_rect.txt 包含每一帧矩形边界框位置,注意在大多数序列中,第一行对应于第一帧,最后一行对应于最后一帧,除了序列 David(300:770), Football1(1:74), Freeman3(1:460), Freeman4(1:283). 官网上还有每个视频的标注目标属性,分为 IV(Illumination Variation), SV(Scale Variation), OCC(Occlusion), DEF(Deformation), MB(Motion Blur), FM(Fast Motion), IPR(In-Plane Rotation), OPR(Out-of-Plane Rotation), OV(Out-of-View), BC(Background Clutters), LR(Low Resolution).

预处理(chatgpt)

二者的标注文件内容基本是一致的,只需进行简单的处理

还是很麻烦的,恶心死了

提取类别

import os def extract_and_save_classes(data_dir, split, output_file): classes_set = set() split_folder = os.path.join(data_dir, split) for class_name in os.listdir(split_folder): class_folder = os.path.join(split_folder, class_name) if os.path.isdir(class_folder): classes_set.add(class_name) with open(output_file, 'w') as classes_file: for class_name in sorted(classes_set): classes_file.write(f"{class_name}\n") if __name__ == "__main__": data_dir = '/yolo_data' # Process the 'train' split train_split = 'train' train_output_file = os.path.join(data_dir, 'code', 'train', 'classes.txt') if not os.path.exists(train_output_file): os.makedirs(os.path.join(data_dir, 'code', 'train'), exist_ok=True) extract_and_save_classes(data_dir, train_split, train_output_file) # Process the 'test' split test_split = 'test' test_output_file = os.path.join(data_dir, 'code', 'test', 'classes.txt') if not os.path.exists(test_output_file): os.makedirs(os.path.join(data_dir, 'code', 'test'), exist_ok=True) extract_and_save_classes(data_dir, test_split, test_output_file)

提取图片

import os import shutil def rename_and_save_images(data_dir, split, output_folder): split_folder = os.path.join(data_dir, split) output_split_folder = os.path.join(output_folder) print(output_split_folder,split_folder) os.makedirs(output_split_folder, exist_ok=True) for class_name in os.listdir(split_folder): class_folder = os.path.join(split_folder, class_name, 'img') for img_name in os.listdir(class_folder): img_path = os.path.join(class_folder, img_name) output_img_name = f"{class_name}_{img_name}" output_img_path = os.path.join(output_split_folder, output_img_name) shutil.copy(img_path, output_img_path) if __name__ == "__main__": data_dir = '/yolo_data' # Process the 'train' split train_split = 'train' train_output_folder = os.path.join(data_dir, 'code', 'train', 'images') os.makedirs(train_output_folder, exist_ok=True) rename_and_save_images(data_dir, train_split, train_output_folder) # Process the 'test' split test_split = 'test' test_output_folder = os.path.join(data_dir, 'code', 'test', 'images') os.makedirs(test_output_folder, exist_ok=True) rename_and_save_images(data_dir, test_split, test_output_folder)

提取标注信息

import os import shutil import cv2 def extract_and_save_labels(data_dir, split, output_folder, classes_file): split_folder = os.path.join(data_dir, split) os.makedirs(output_folder, exist_ok=True) with open(classes_file, 'r') as classes_file: classes = classes_file.read().splitlines() print(classes) for class_id, class_name in enumerate(classes): print(class_id,class_name) class_folder = os.path.join(split_folder, class_name) print("class_folder",class_folder) txt_files = [f for f in os.listdir(class_folder) if f.endswith('.txt')] for i in range(len(txt_files)): groundtruth_file_path = os.path.join(class_folder, txt_files[i]) print("Attempting to open:", groundtruth_file_path) with open(groundtruth_file_path, 'r') as groundtruth_file: lines = groundtruth_file.readlines() i = 0 for image_name in os.listdir(class_folder+"/img"): if not image_name.endswith(".jpg"): continue # 获取图像尺寸 image_path = os.path.join(class_folder, "img", image_name) image = cv2.imread(image_path) height, width, _ = image.shape if i< len(lines): label_values = f"{class_id} {lines[i].strip()}" i+=1 # 归一化处理 label_values = label_values.split(" ") try: normalized_values = [ int(label_values[0]), # 目标类别id float(label_values[1].split(",")[0]) / width, # 目标中心位置x float(label_values[1].split(",")[1]) / height, # 目标中心位置y float(label_values[1].split(",")[2]) / width, # 目标宽度w float(label_values[1].split(",")[3]) / height # 目标高度h ] except: normalized_values = [ int(label_values[0]), # 目标类别id float(label_values[1].split("\t")[0]) / width, # 目标中心位置x float(label_values[1].split("\t")[1]) / height, # 目标中心位置y float(label_values[1].split("\t")[2]) / width, # 目标宽度w float(label_values[1].split("\t")[3]) / height # 目标高度h ] label_line = " ".join(map(str, normalized_values)) # 构建输出文件路径 output_file_path = os.path.join(output_folder, f"{class_name}_{image_name.split('.')[0]}.txt") # 检查文件是否存在 if os.path.exists(output_file_path): # 追加数据到现有文件 with open(output_file_path, 'a') as output_file: output_file.write('\n' + label_line) else: # 创建新文件并保存 label_line 到文件 with open(output_file_path, 'w') as output_file: output_file.write(label_line) #保存label_line到/yolo_data/code/split/lables/class_name+image_name.split(".")[0]+".txt" if __name__ == "__main__": data_dir = '/yolo_data' # Process the 'train' split train_split = 'train' train_output_folder = os.path.join(data_dir, 'code', 'train', 'labels') train_classes_file = os.path.join(data_dir, 'code', 'train', 'classes.txt') os.makedirs(train_output_folder, exist_ok=True) extract_and_save_labels(data_dir, train_split, train_output_folder, train_classes_file) # Process the 'test' split test_split = 'test' test_output_folder = os.path.join(data_dir, 'code', 'test', 'labels') test_classes_file = os.path.join(data_dir, 'code', 'test', 'classes.txt') os.makedirs(test_output_folder, exist_ok=True) extract_and_save_labels(data_dir, test_split, test_output_folder, test_classes_file)

图片大小处理

import os import cv2 def resize_images(input_folder, output_folder, target_size=(416, 416)): for filename in os.listdir(input_folder): print(filename) if filename.endswith(".jpg"): # Assuming images have these extensions input_path = os.path.join(input_folder, filename) output_path = os.path.join(output_folder, filename) # Read the image image = cv2.imread(input_path) # Resize the image resized_image = cv2.resize(image, target_size) # Save the resized image cv2.imwrite(output_path, resized_image) if __name__ == "__main__": input_folder = '/yolo_data/code/test/images' output_folder = '/yolo_data/code/test/images' resize_images(input_folder, output_folder) print("ok")

训练

写一个 yaml 文件

# 数据集源路径root、训练集、验证集、测试集地址 path: /yolo_data/code/ # 数据集源路径root dir train: train # root下的训练集地址 128 images val: test # root下的验证集地址 128 images test: test # root下的验证集地址 128 images # 数据集类别信息 nc: 70 # 数据集类别数量 names: [ 'Basketball', 'Biker', 'Bird1', 'BlurBody', 'BlurCar2', 'BlurFace', 'BlurOwl', 'Board', 'Bolt', 'Box', 'Boy', 'Car1', 'Car2', 'CarDark', 'CarScale', 'ClifBar', 'Coke', 'Couple', 'Coupon', 'Crossing', 'Crowds', 'Dancer', 'David', 'David2', 'Deer', 'Diving', 'Dog', 'Doll', 'DragonBaby', 'Dudek', 'FaceOcc1', 'Fish', 'FleetFace', 'Football', 'Freeman1', 'Freeman3', 'Girl', 'Gym', 'Human2', 'Human3', 'Human4', 'Human5', 'Human6', 'Human7', 'Ironman', 'Jogging', 'Jump', 'Jumping', 'KiteSurf', 'Lemming', 'Liquor', 'Man', 'Matrix', 'Mhyang', 'MotorRolling', 'MountainBike', 'Panda', 'RedTeam', 'Rubik', 'Shaking', 'Singer1', 'Skater', 'Skater2', 'Skating1', 'Skiing', 'Soccer', 'Subway', 'Surfer', 'Suv', 'Tiger1' ]

训练

官方:训练 - Ultralytics YOLOv8 文档

from ultralytics import YOLO import cv2 # 加载模型 model = YOLO('yolov8n.pt') # 加载预训练模型(推荐用于训练) # 使用2个GPU训练模型 results = model.train(data='readme.yaml', epochs=2, imgsz=416, device=[0, 1])

结果

还没跑完,后面放结果

  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    159 引用 • 298 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...