当前位置: 首页 > backend >正文

11.2 yolov8用自己的数据集训练语义分割模型

1.数据集的制作及处理

1.1 标定数据

        本文看了博客YOLOv8实例分割训练自己的数据集保姆级教程-CSDN博客和博客YOLOv8 训练自己的分割数据集_YOLOv8改进实战🚀-CSDN专栏,将两个博客的内容串着操作了一遍,这里作为笔记用。

1.下载安装Labelme:Labelme

下载后打开labelme.exe文件得到如下图:

2.新建label文件夹保存标签

        上图中,images是图片的文件夹,json文件是标注后存放json文件的文件夹,然后打开数据集文件进行标注。

1.2 json文件生成txt文件

        新建json2txt.py文件,修改文件路径为自己的路径。

# -*- coding: utf-8 -*-
import json
import os
import argparse
from tqdm import tqdmdef convert_label_json(json_dir, save_dir, classes):json_paths = os.listdir(json_dir)classes = classes.split(',')for json_path in tqdm(json_paths):# for json_path in json_paths:path = os.path.join(json_dir, json_path)with open(path, 'r') as load_f:json_dict = json.load(load_f)h, w = json_dict['imageHeight'], json_dict['imageWidth']# save txt pathtxt_path = os.path.join(save_dir, json_path.replace('json', 'txt'))txt_file = open(txt_path, 'w')for shape_dict in json_dict['shapes']:label = shape_dict['label']label_index = classes.index(label)points = shape_dict['points']points_nor_list = []for point in points:points_nor_list.append(point[0] / w)points_nor_list.append(point[1] / h)points_nor_list = list(map(lambda x: str(x), points_nor_list))points_nor_str = ' '.join(points_nor_list)label_str = str(label_index) + ' ' + points_nor_str + '\n'txt_file.writelines(label_str)if __name__ == "__main__":"""python json2txt_nomalize.py --json-dir my_datasets/color_rings/jsons --save-dir my_datasets/color_rings/txts --classes "cat,dogs""""parser = argparse.ArgumentParser(description='json convert to txt params')parser.add_argument('--json-dir', type=str, default='D:/AI/1.ultralytics-main/data/json', help='json path dir')parser.add_argument('--save-dir', type=str, default='D:/AI/1.ultralytics-main/data/txt', help='txt save dir')parser.add_argument('--classes', type=str, default='craw', help='classes')args = parser.parse_args()json_dir = args.json_dirsave_dir = args.save_dirclasses = args.classesconvert_label_json(json_dir, save_dir, classes)

        以上文件中,需要写入需要转换的放json文件的文件夹路径、存放转换后的txt文件的文件夹路径。

1.3数据集划分

        新建split.py,修改文件路径为自己的路径

# 将图片和标注数据按比例切分为 训练集和测试集
import shutil
import random
import os# 原始路径
image_original_path = "D:/AI/1.ultralytics-main/data/images/"
label_original_path = "D:/AI/1.ultralytics-main/data/txt/"cur_path = os.getcwd()
# cur_path = 'D:/image_denoising_test/denoise/'
# 训练集路径
train_image_path = os.path.join(cur_path, "datasets/images/train/")
train_label_path = os.path.join(cur_path, "datasets/labels/train/")# 验证集路径
val_image_path = os.path.join(cur_path, "datasets/images/val/")
val_label_path = os.path.join(cur_path, "datasets/labels/val/")# 测试集路径
test_image_path = os.path.join(cur_path, "datasets/images/test/")
test_label_path = os.path.join(cur_path, "datasets/labels/test/")# 训练集目录
list_train = os.path.join(cur_path, "datasets/train.txt")
list_val = os.path.join(cur_path, "datasets/val.txt")
list_test = os.path.join(cur_path, "datasets/test.txt")train_percent = 0.8
val_percent = 0.1
test_percent = 0.1def del_file(path):for i in os.listdir(path):file_data = path + "\\" + ios.remove(file_data)def mkdir():if not os.path.exists(train_image_path):os.makedirs(train_image_path)else:del_file(train_image_path)if not os.path.exists(train_label_path):os.makedirs(train_label_path)else:del_file(train_label_path)if not os.path.exists(val_image_path):os.makedirs(val_image_path)else:del_file(val_image_path)if not os.path.exists(val_label_path):os.makedirs(val_label_path)else:del_file(val_label_path)if not os.path.exists(test_image_path):os.makedirs(test_image_path)else:del_file(test_image_path)if not os.path.exists(test_label_path):os.makedirs(test_label_path)else:del_file(test_label_path)def clearfile():if os.path.exists(list_train):os.remove(list_train)if os.path.exists(list_val):os.remove(list_val)if os.path.exists(list_test):os.remove(list_test)def main():mkdir()clearfile()file_train = open(list_train, 'w')file_val = open(list_val, 'w')file_test = open(list_test, 'w')total_txt = os.listdir(label_original_path)num_txt = len(total_txt)list_all_txt = range(num_txt)num_train = int(num_txt * train_percent)num_val = int(num_txt * val_percent)num_test = num_txt - num_train - num_valtrain = random.sample(list_all_txt, num_train)# train从list_all_txt取出num_train个元素# 所以list_all_txt列表只剩下了这些元素val_test = [i for i in list_all_txt if not i in train]# 再从val_test取出num_val个元素,val_test剩下的元素就是testval = random.sample(val_test, num_val)print("训练集数目:{}, 验证集数目:{}, 测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))for i in list_all_txt:name = total_txt[i][:-4]srcImage = image_original_path + name + '.jpg'srcLabel = label_original_path + name + ".txt"if i in train:dst_train_Image = train_image_path + name + '.jpg'dst_train_Label = train_label_path + name + '.txt'shutil.copyfile(srcImage, dst_train_Image)shutil.copyfile(srcLabel, dst_train_Label)file_train.write(dst_train_Image + '\n')elif i in val:dst_val_Image = val_image_path + name + '.jpg'dst_val_Label = val_label_path + name + '.txt'shutil.copyfile(srcImage, dst_val_Image)shutil.copyfile(srcLabel, dst_val_Label)file_val.write(dst_val_Image + '\n')else:dst_test_Image = test_image_path + name + '.jpg'dst_test_Label = test_label_path + name + '.txt'shutil.copyfile(srcImage, dst_test_Image)shutil.copyfile(srcLabel, dst_test_Label)file_test.write(dst_test_Image + '\n')file_train.close()file_val.close()file_test.close()if __name__ == "__main__":main()

运行完后得到如下文件

849ec015ad054cbfb1d87db29a169253.png

2. yaml文件的配置

2.1 新建seg.yaml文件 ,按照下列格式创建

train: D:/AI/1.ultralytics-main/datasets/images/train  # train images (relative to 'path') 128 images
val: D:/AI/1.ultralytics-main/datasets/images/val  # val images (relative to 'path') 128 images
test: D:/AI/1.ultralytics-main/datasets/images/test # test images (optional)# whether it is coco dataset, only coco dataset should be set to True.
is_coco: False
# Classes
nc: 1  # number of classes
names: ['craw']  # class names

        注意:要按照自己的数据集的实际情况写入以上文件的路径、检测目标的数量及目标名称。

2.2 进入以下路径

        然后自己新建一个yolov8-mask.yaml文件,再将该路径下的yolov8-seg.yaml的代码复制到yolov8-mask.yaml文件里面。

3.训练模型

        配置完以上文件后,进入test文件夹下写一个train.py文件。

from ultralytics import YOLOif __name__ == '__main__':# 加载模型model = YOLO(r'yolov8-mask.yaml', task="segment")  # 不使用预训练权重训练# model = YOLO(r'yolov8-seg.yaml').load("yolov8n-seg.pt")  # 使用预训练权重训练# 训练参数 ----------------------------------------------------------------------------------------------model.train(data=r'seg.yaml',epochs=300,  # (int) 训练的周期数patience=50,  # (int) 等待无明显改善以进行早期停止的周期数batch=8,  # (int) 每批次的图像数量(-1 为自动批处理)imgsz=640,  # (int) 输入图像的大小,整数或w,hsave=True,  # (bool) 保存训练检查点和预测结果save_period=-1,  # (int) 每x周期保存检查点(如果小于1则禁用)cache=False,  # (bool) True/ram、磁盘或False。使用缓存加载数据device='',  # (int | str | list, optional) 运行的设备,例如 cuda device=0 或 device=0,1,2,3 或 device=cpuworkers=8,  # (int) 数据加载的工作线程数(每个DDP进程)project='runs/train',  # (str, optional) 项目名称name='exp',  # (str, optional) 实验名称,结果保存在'project/name'目录下exist_ok=False,  # (bool) 是否覆盖现有实验pretrained=True,  # (bool | str) 是否使用预训练模型(bool),或从中加载权重的模型(str)optimizer='SGD',  # (str) 要使用的优化器,选择=[SGD,Adam,Adamax,AdamW,NAdam,RAdam,RMSProp,auto]verbose=True,  # (bool) 是否打印详细输出seed=0,  # (int) 用于可重复性的随机种子deterministic=True,  # (bool) 是否启用确定性模式single_cls=False,  # (bool) 将多类数据训练为单类rect=False,  # (bool) 如果mode='train',则进行矩形训练,如果mode='val',则进行矩形验证cos_lr=False,  # (bool) 使用余弦学习率调度器close_mosaic=0,  # (int) 在最后几个周期禁用马赛克增强resume=False,  # (bool) 从上一个检查点恢复训练amp=True,  # (bool) 自动混合精度(AMP)训练,选择=[True, False],True运行AMP检查fraction=1.0,  # (float) 要训练的数据集分数(默认为1.0,训练集中的所有图像)profile=False,  # (bool) 在训练期间为记录器启用ONNX和TensorRT速度freeze= None,  # (int | list, 可选) 在训练期间冻结前 n 层,或冻结层索引列表。# 分割overlap_mask=True,  # (bool) 训练期间是否应重叠掩码(仅适用于分割训练)mask_ratio=4,  # (int) 掩码降采样比例(仅适用于分割训练)# 分类dropout=0.0,  # (float) 使用丢弃正则化(仅适用于分类训练)# 超参数 ----------------------------------------------------------------------------------------------lr0=0.01,  # (float) 初始学习率(例如,SGD=1E-2,Adam=1E-3)lrf=0.01,  # (float) 最终学习率(lr0 * lrf)momentum=0.937,  # (float) SGD动量/Adam beta1weight_decay=0.0005,  # (float) 优化器权重衰减 5e-4warmup_epochs=3.0,  # (float) 预热周期(分数可用)warmup_momentum=0.8,  # (float) 预热初始动量warmup_bias_lr=0.1,  # (float) 预热初始偏置学习率box=7.5,  # (float) 盒损失增益cls=0.5,  # (float) 类别损失增益(与像素比例)dfl=1.5,  # (float) dfl损失增益pose=12.0,  # (float) 姿势损失增益kobj=1.0,  # (float) 关键点对象损失增益label_smoothing=0.0,  # (float) 标签平滑(分数)nbs=64,  # (int) 名义批量大小hsv_h=0.015,  # (float) 图像HSV-Hue增强(分数)hsv_s=0.7,  # (float) 图像HSV-Saturation增强(分数)hsv_v=0.4,  # (float) 图像HSV-Value增强(分数)degrees=0.0,  # (float) 图像旋转(+/- deg)translate=0.1,  # (float) 图像平移(+/- 分数)scale=0.5,  # (float) 图像缩放(+/- 增益)shear=0.0,  # (float) 图像剪切(+/- deg)perspective=0.0,  # (float) 图像透视(+/- 分数),范围为0-0.001flipud=0.0,  # (float) 图像上下翻转(概率)fliplr=0.5,  # (float) 图像左右翻转(概率)mosaic=1.0,  # (float) 图像马赛克(概率)mixup=0.0,  # (float) 图像混合(概率)copy_paste=0.0,  # (float) 分割复制-粘贴(概率))

开始训练时会打印出模型的参数量,计算量,结构信息。

训练结束后会打印出各种指标,包括 PRmAPSpeed等。

最后训练后的模型结果如下:

参数输出结果如下:

4.评估模型

评估模型时有个同学问的最多的问题就是测试集的精度怎么看,

这里因为我们没有划分测试集,所以没法看测试集的指标,但是如果你划分了测试集,

直接使用我给的脚本,将 split 设置为 test ,这样就会打印出测试集的指标。

import sys
sys.path.append("D:/AI/1.ultralytics-main/ultralytics")
from ultralytics import YOLOif __name__ == '__main__':# 加载模型model = YOLO(r'D:/AI/1.ultralytics-main/tests/runs/train/exp/weights/best.pt')  # YOLOv8n模型model.predict(source=r'D:/AI/1.ultralytics-main/datasets/images/test',save=True,  # 保存预测结果imgsz=640,  # 输入图像的大小,可以是整数或w,hconf=0.25,  # 用于检测的目标置信度阈值(默认为0.25,用于预测,0.001用于验证)iou=0.45,  # 非极大值抑制 (NMS) 的交并比 (IoU) 阈值show=False,  # 如果可能的话,显示结果project='runs/predict',  # 项目名称(可选)name='exp',  # 实验名称,结果保存在'project/name'目录下(可选)save_txt=False,  # 保存结果为 .txt 文件save_conf=True,  # 保存结果和置信度分数save_crop=False,  # 保存裁剪后的图像和结果show_labels=True,  # 在图中显示目标标签show_conf=True,  # 在图中显示目标置信度分数vid_stride=1,  # 视频帧率步长line_width=3,  # 边界框线条粗细(像素)visualize=False,  # 可视化模型特征augment=False,  # 对预测源应用图像增强agnostic_nms=False,  # 类别无关的NMSretina_masks=False,  # 使用高分辨率的分割掩码boxes=True,  # 在分割预测中显示边界框)

5.推理模型

        推理使用我给的如下脚本就可以实现了。

from ultralytics import YOLOif __name__ == '__main__':# 加载模型model = YOLO(r'D:/AI/1.ultralytics-main/tests/runs/train/exp/weights/best.pt')# 验证模型model.val(val=True,  # (bool) 在训练期间进行验证/测试data=r'seg.yaml',split='val',  # (str) 用于验证的数据集拆分,例如'val'、'test'或'train'batch=1,  # (int) 每批的图像数量(-1 为自动批处理)imgsz=640,  # 输入图像的大小,可以是整数或w,hdevice='',  # 运行的设备,例如 cuda device=0 或 device=0,1,2,3 或 device=cpuworkers=8,  # 数据加载的工作线程数(每个DDP进程)save_json=False,  # 保存结果到JSON文件save_hybrid=False,  # 保存标签的混合版本(标签 + 额外的预测)conf=0.001,  # 检测的目标置信度阈值(默认为0.25用于预测,0.001用于验证)iou=0.6,  # 非极大值抑制 (NMS) 的交并比 (IoU) 阈值project='runs/val',  # 项目名称(可选)name='exp',  # 实验名称,结果保存在'project/name'目录下(可选)max_det=300,  # 每张图像的最大检测数half=False,  # 使用半精度 (FP16)dnn=False,  # 使用OpenCV DNN进行ONNX推断plots=True,  # 在训练/验证期间保存图像)

结果如下:

6. 分割怎么改进

有同学问分割怎么改进,其实和检测任务一样的,唯一区别就是下面红框中的区别,

是用我给的改进和脚本很容易上手改进分割任务~

http://www.xdnf.cn/news/16148.html

相关文章:

  • Android Camera createCaptureSession
  • Mysql命令show processlist
  • 成品电池综合测试仪:保障电池品质与安全的核心工具|深圳鑫达能
  • 聚观早报 | 猿编程推动中美青少年AI实践;华为Pura 80数字版售价公布;iPhone 17 Air电池曝光
  • J2EE模式---组合实体模式
  • ollama无法拉取模型导致报错
  • Linux724 逻辑卷挂载;挂载点扩容;逻辑卷开机自启
  • 噪声环境下的数据驱动预测控制:提升抗测量噪声干扰能力
  • Python桌面版数独(五版)-优化选择模式触发新棋盘生成
  • Opencv C# 重叠 粘连 Overlap 轮廓分割 (不知道不知道)
  • STM32 HAL库 HAL_TIM_OC_Stop函数详细解释
  • Flink-1.19.0源码详解7-Flink集群端调度
  • RWA与DeFi(去中心化金融)的关系是什么?RWA在DeFi中扮演什么角色?
  • 使用ffmpeg转码h265后mac默认播放器不支持问题
  • 亚马逊云科技实战架构:构建可扩展、高效率、无服务器应用
  • 【25-cv-08165】纸牌游戏 UNO注册商标!!由GBC律所代理发案
  • b-up:Enzo_mi:Transformer DETR系列
  • Java 实现 C/S 架构详解:从基础到实战,彻底掌握客户端/服务端编程
  • 项目质量如何提升?
  • C++常见面试题/笔试收录(一)
  • 深入探索Amazon SQS:构建弹性微服务与无服务器应用的秘密武器
  • 模拟退火算法 (Simulated Annealing, SA)简介
  • Unity GC 系列教程第四篇:GC Alloc 优化技巧与实践(下)与 GC 调优
  • Java 垃圾回收器之CMS GC问题分析与解决
  • 嵌入式开发学习———Linux环境下数据结构学习(三)
  • 《Flutter篇第一章》基于GetX 和 Binding、Dio 实现的 Flutter UI 架构
  • 跨境支付入门~国际支付结算(风控篇)
  • 学习游戏制作记录(技能系统)7.24
  • 二、计算机网络技术——第4章:网络层
  • 《计算机“十万个为什么”》之 [特殊字符] 深浅拷贝 引用拷贝:内存世界的复制魔法 ✨