SeaDronesSee数据集在YOLOV8上的部署
- SeaDronesSee数据集为无人机拍摄的海洋救援相关的数据集。目标框有’ignored’, ‘swimmer’, ‘boat’, ‘jetski’, ‘life_saving_appliances’, 'buoy’六个类别。以下内容为为实现该数据集在yoloV8上的部署,进行的预处理与运行测试。
我的GitHub链接:SeaDronesSee-dataset-on-YOLOV8
数据来源:SeaDronesSee
一、目录初始结构
.
├── ./data
│ ├── ./data/images
│ │ ├── ./data/images/train
│ │ │ ├── ./data/images/train/0.jpg
│ │ │ ├── ./data/images/train/1.jpg
│ │ │ └── ...
│ │ ├── ./data/images/val
│ │ │ ├── ./data/images/val/0.jpg
│ │ │ ├── ./data/images/val/1.jpg
│ │ │ └── ...
│ │ ├── ./data/images/test
│ │ │ ├── ./data/images/test/0.jpg
│ │ │ ├── ./data/images/test/1.jpg
│ │ │ └── ...
│ ├── ./data/annotations
│ │ ├── ./data/annotations/instances_train.json
│ │ └── ./data/annotations/instances_val.json
│ ├── ./data/SeaDronesSee.yaml
│ └── ./data/data_process.py
————————————————
二、数据预处理
- 目标:将annotations中的标注信息清洗转换为我们想要的数据
- 将解压后的Compressed Version中的images和annotations粘贴到data中
需要SeaDronesSee数据集压缩包的请私信我
- 运行data_process.py。将会生成三个txt文件和一个labels文件夹
# data_process.py的内容:
import os
from tqdm import tqdm
from PIL import Image
import json
def generate_txt_file(folder_path, txt_file_path):
print("正在处理文件夹:", folder_path)
with open(txt_file_path, 'w') as txt_file:
file_list = os.listdir(folder_path)
for file_name in file_list:
if file_name.endswith('.jpg') or file_name.endswith('.png'):
txt_file.write('data/images/' + file_name + '\n')
print("已生成文件:", txt_file_path)
def JSONtoTXT(mode,datapath):
# 若没有,创建labels文件夹
if not os.path.exists('labels'):
os.mkdir('labels')
with open(datapath, 'r') as file:
data = json.load(file)
print("正在处理:" + datapath)
annotations = data['annotations']
for annotation in tqdm(annotations):
category_id = annotation['category_id'] # 读取JSON中的类别标签
# 下面的if语句可删
if category_id == 0: # 如果category_id为ignore,则跳过当前注释信息
print(str(annotation['image_id']) + ".jpg的标签为ignore")
continue
# 读取JSON中的图片id,并根据路径找到对应图片,获取图片的宽和高
image_id = annotation['image_id']
file_path = os.path.join('images/', mode + '/' + str(image_id) + '.jpg')
with Image.open(file_path) as img:
width, height = img.size
# 读取JSON中框的[x,y,宽,高]
bbox = annotation['bbox']
# 归一化处理:
# 目标框中心点x轴相对于图片x轴的比例 = (目标框x位置 + 目标框宽度 / 2) / 图片宽度
x = (int(bbox[0]) + int(bbox[2]) / 2) / int(width)
# 目标框中心点y轴相对于图片y轴的比例 = (目标框y位置 + 目标框高度 / 2) / 图片高度
y = (int(bbox[1]) + int(bbox[3]) / 2) / int(height)
# 目标框宽度相对于图片宽度的比例 = 目标框宽度 / 图片宽度
w = int(bbox[2]) / int(width)
# 目标框高度相对于图片高度的比例 = 目标框高度 / 图片高度
h = int(bbox[3]) / int(height)
# 最后所需的数据内容
content = f"{category_id} {x} {y} {w} {h}"
file_name = image_id
file_path = f'labels/{file_name}.txt'
# 写入labels文件夹
if os.path.exists(file_path):
with open(file_path, 'a') as file:
file.write('\n' + content)
else:
with open(file_path, 'w') as file:
file.write(content)
"""
一:根据images下的三个文件夹,生成对应的txt。内容为各图片路径========================
"""
# 文件夹路径
train_folder = 'images/train'
val_folder = 'images/val'
test_folder = 'images/test'
# 生成txt文件
generate_txt_file(train_folder, 'train2.txt')
generate_txt_file(val_folder, 'val2.txt')
generate_txt_file(test_folder, 'test2.txt')
print("文件处理完成。")
"""
二:根据JSON转txt=============================================================
"""
# JSON文件数据清洗转TXT
JSONtoTXT('train', 'annotations/instances_train.json')
JSONtoTXT('val', 'annotations/instances_val.json')
print("处理完成")
- 最后,把images/test、train、val中的所有图片移动到images下
- 注意! 在autodl上,SeaDronesSee.yaml中的txt路径要这样写才能找到,如果不行的话需要再调试一下
train: ../../data/train.txt val: ../../data/val.txt test: ../../data/test.txt
yolov8最终会读取的东西:images下的所有jpg、labels下的所有txt、SeaDronesSee.yaml、train.txt、val.txt、test.txt
- 训练开始前所必须的目录结构:
.
├── ./data
│ ├── ./data/images
│ │ ├── ./data/images/1.jpg
│ │ ├── ./data/images/2.jpg
│ │ ├── ./data/images/3.jpg
│ │ ├── ...
│ ├── ./data/labels
│ │ ├── ./data/labels/1.txt
│ │ ├── ./data/labels/2.txt
│ │ ├── ./data/labels/3.txt
│ │ ├── ...
│ ├── ./data/SeaDronesSee.yaml
│ ├── ./data/train.txt
│ ├── ./data/val.txt
│ └── ./data/test.txt
————————————————
- 附:SeaDronesSee.yaml内容
train: ../../data/train.txt
val: ../../data/val.txt
test: ../../data/test.txt
# number of classes
nc: 6
# class names
names: ['ignore', 'swimmer', 'boat', 'jetski', 'life_saving_appliances', 'buoy']
三、快速开始
- 模型训练(只进行了快速试验,若换成yolov8s.pt epochs=100,效果会更好些)
yolo task=detect mode=train model=yolov8n.pt data=data/SeaDronesSee.yaml batch=32 epochs=20 imgsz=640 workers=16 device=0
- 模型验证(注意!运行前请查看并替换上面train生成的文件夹名称‘runs/detect/train1’)
yolo task=detect mode=val model=runs/detect/train1/weights/best.pt data=data/SeaDronesSee.yaml device=0
- 模型预测(source换为需要预测的文件目录)
yolo task=detect mode=predict model=runs/detect/train1/weights/best.pt source=data/images device=0
- 所有的运行结果会保存在/runs/detect/目录下
四、文件解释
最终目标:实现yaml对三个txt的读取。实现labels与images的所需格式
-
data_process.py:
- 根据images中不同文件夹和图片名称,生成对应的train、val、test.txt三个文件。内容为图片路径
- 清洗两个JSON文件中的必要性数据,并进行归一化处理(输出格式为:目标框类别 目标框中心点x轴相对于图片x轴的比例 目标框…y轴的比例 目标框宽度相对于图片宽度的比例 目标框长度…的比例)
- 生成(图片id.txt)到labels文件夹中
-
SeaDronesSee.yaml:让yolo命令读取到必要信息
-
注意:'ignored’标签在标注图片中没有出现
五、结果展示
- 原图示例
- 结果展示
六、致谢
感谢 YOLOv8教程系列 优质的方法指导
感谢超级好用的GPT3.5的超级好用的回答