YOLOV10训练自己的数据集(windows版本)
此次使用的训练集来自:https://www.kaggle.com/datasets/ 口罩训练集
一共三个标签[‘without_mask’,‘with_mask’,‘mask_weared_incorrect’]
前提条件:已安装python环境,conda,显卡驱动
开发工具:Pycharm64
系统:windows11
1.下载官方代码
下载地址:yolov10
进入网址后,先点击code按钮,再点击Download ZIP,下载的文件是一个压缩包:yolov10-main.zip

2. 下载权重文件
YOLOV10N:https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10n.pt
YOLOV10S:https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10s.pt
YOLOV10M:https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10m.pt
YOLOV10B:https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10b.pt
YOLOV10L:https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10l.pt
YOLOV10X:https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10x.pt
2.1 yolov10解读

快速的看一下相关的文档,发现YOLOv10 相比YOLOv8有两个最大的改变分别是 添加了PSA层跟CIB层


去掉了NMS

废话不多说上干货
3.下载数据集
https://www.kaggle.com/datasets/
数据集使用的是VOC格式需要转换成YOLO格式


4.数据集处理


xml 转 txt
import xml.etree.ElementTree as ET
import os, cv2
import numpy as np
from os import listdir
from os.path import join
classes = []
def convert(size, box):
dw = 1. / (size[0])
dh = 1. / (size[1])
x = (box[0] + box[1]) / 2.0 - 1
y = (box[2] + box[3]) / 2.0 - 1
w = box[1] - box[0]
h = box[3] - box[2]
x = x * dw
w = w * dw
y = y * dh
h = h * dh
return (x, y, w, h)
def convert_annotation(xmlpath, xmlname):
with open(xmlpath, "r", encoding='utf-8') as in_file:
txtname = xmlname[:-4] + '.txt'
txtfile = os.path.join(txtpath, txtname)
tree = ET.parse(in_file)
root = tree.getroot()
filename = root.find('filename')
img = cv2.imdecode(np.fromfile('{}/{}.{}'.format(imgpath, xmlname[:-4], postfix), np.uint8), cv2.IMREAD_COLOR)
h, w = img.shape[:2]
res = []
for obj in root.iter('object'):
cls = obj.find('name').text
if cls not in classes:
classes.append(cls)
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
float(xmlbox.find('ymax').text))
bb = convert((w, h), b)
res.append(str(cls_id) + " " + " ".join([str(a) for a in bb]))
if len(res) != 0:
with open(txtfile, 'w+') as f:
f.write('\n'.join(res))
if __name__ == "__main__":
postfix = 'png' # 图像后缀
imgpath = r'D:\YOLO_DATASETS\MASK\images' # 图像文件路径
xmlpath = r'D:\YOLO_DATASETS\MASK\annotations' # xml文件文件路径
txtpath = r'D:\YOLO_DATASETS\MASK\test\labels' # 生成的txt文件路径
if not os.path.exists(txtpath):
os.makedirs(txtpath, exist_ok=True)
list = os.listdir(xmlpath)
error_file_list = []
for i in range(0, len(list)):
try:
path = os.path.join(xmlpath, list[i])
if ('.xml' in path) or ('.XML' in path):
convert_annotation(path, list[i])
print(f'file {list[i]} convert success.')
else:
print(f'file {list[i]} is not xml format.')
except Exception as e:
print(f'file {list[i]} convert error.')
print(f'error message:\n{e}')
error_file_list.append(list[i])
print(f'this file convert failure\n{error_file_list}')
print(f'Dataset Classes:{classes}')

5.数据集制作
把数据集根据比例拆分出:训练集,验证集,测试集
# 将图片和标注数据按比例切分为 训练集和测试集
import shutil
import random
import os
# 原始路径 D:\YOLO_DATASETS\MASK\images
image_original_path = "D:/YOLO_DATASETS/MASK/images/"
label_original_path = "D:/YOLO_DATASETS/MASK/labels/"
cur_path = os.getcwd()
# 训练集路径
train_image_path = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/images/train/")
train_label_path = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/labels/train/")
# 验证集路径
val_image_path = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/images/val/")
val_label_path = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/labels/val/")
# 测试集路径
test_image_path = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/images/test/")
test_label_path = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/labels/test/")
# 训练集目录
list_train = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/train.txt")
list_val = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/val.txt")
list_test = os.path.join(cur_path, "D:/YOLO_DATASETS/MASK/datasets/test.txt")
train_percent = 0.8
val_percent = 0.1
test_percent = 0.1
def del_file(path):
for i in os.listdir(path):
file_data = path + "\\" + i
os.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_val
train = 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剩下的元素就是test
val = 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 + '.png'
srcLabel = label_original_path + name + ".txt"
if i in train:
dst_train_Image = train_image_path + name + '.png'
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 + '.png'
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 + '.png'
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()
6. 导入代码并安装所需驱动并启动
如果环境启动不了请参考官方文档
创建环境:conda create --name yolov10 python=3.8
激活环境:conda activate yolov10
安装依赖:pip install -r requirements.txt
6.1 创建mask.yaml
train: D:\YOLO_DATASETS\MASK\datasets\images\train # train images (relative to 'path') 4 images
val: D:\YOLO_DATASETS\MASK\datasets\images\val # val images (relative to 'path') 4 images
nc: 3
# class names
names: ['without_mask','with_mask','mask_weared_incorrect']
6.2 创建训练代码
# -*- coding: utf-8 -*-
"""
@Auth : dupo
@File :trian.py
@IDE :PyCharm
"""
from ultralytics import YOLOv10
import warnings
warnings.filterwarnings('ignore')
if __name__ == '__main__':
model = YOLOv10('yolov10n.pt') # 加载预训练权重,改进或者做对比实验时候不建议打开,因为用预训练模型整体精度没有很明显的提升
model.train(data=r'mask.yaml',
imgsz=640,
epochs=50,
batch=4,
workers=0,
device='',
optimizer='SGD',
close_mosaic=10,
resume=False,
project='runs/detect',
name='exp',
single_cls=False,
cache=False,
)
6.3 安装TensorBoard查看训练情况
安装:pip install tensorboard
启动:tensorboard --logdir=E:\local_code\yolov10-main\runs\detect\exp













7. 模型检验
# -*- coding: utf-8 -*-
from ultralytics import YOLOv10
# wget https://github.com/THU-MIG/yolov10/releases/download/v1.1/yolov10{n/s/m/b/l/x}.pt
model = YOLOv10(r'E:\local_code\yolov10-main\runs\detect\exp\weights\best.pt')
model.predict(source=r'D:\YOLO_DATASETS\MASK\images\maksssksksss148.png', save=True)


魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐




所有评论(0)