赞
踩
目录
训练自己的数据集分为4部分,先配置环境,再获取制作自己的数据集,然后修改配置训练,最后验证训练结果,附带可视化界面。yolov8训练起来较为简单,如果有其他目标检测的数据集理论上可以直接拿来用,从第3训练模型开始看,新手小白0基础建议一步一步跟着来,哪里看不懂的或者遇到哪有问题可以评论区交流或者私信问~
在训练yolov8模型前环境必须配置完成,还不会配置环境的可以看我的这篇博客
环境配置完验证之后就可以获取数据集
数据集可以使用网上公开的跟自己研究相契合的数据集,或者是搜索/拍摄自己研究所需要的图片进行标注制作成数据集,这里两种方法都详细介绍一下
可以在搜索引擎上搜索或者在公开数据集的网站上搜索关键词,使用到的公开数据集网站为kaggleKaggle: Your Machine Learning and Data Science CommunityKaggle is the world’s largest data science community with powerful tools and resources to help you achieve your data science goals.https://www.kaggle.com/比如这里做一个安全帽检测的研究,就可以在搜索框输入安全帽的英文(因为是英文网站,都需要翻译成英文后搜索)Safety helmet
搜索后就可以找到相关的内容,点击datasets筛选数据集,下载几个看一下数据集是否为目标检测的数据格式,一般文件夹为JPEGImages和Annotations包含这两个就可以使用
点开一个后点击download即可下载。
若是下载到分割数据集,即json格式的标注可以看我的这篇文章转为txthttps://blog.csdn.net/qq_67105081/article/details/138123877https://blog.csdn.net/qq_67105081/article/details/138123877
自制数据集需要先获取一定数量的目标图片,可以拍摄或者下载,图片足够之后使用标注工具Labelimg进行标注
使用Labelimg建议使用python3.10以下的环境,这里创建一个python3.8的虚拟环境,不会创建的可以去看我这篇博客点击这里
conda create -n labelimg python=3.8
这里创建完之后进入labelimg环境
conda activate labelimg
进入labelimg环境之后通过pip下载labelimg(需要关闭加速软件)
pip install labelimg -i https://pypi.tuna.tsinghua.edu.cn/simple
安装完成之后就可以使用
在使用labelimg之前,需要准备好数据集存放位置,这里推荐创建一个大文件夹为data,里面有JPEGImages、Annotations和classes.txt,其中JPEGImages文件夹里面放所有的图片,Annotations文件夹是将会用来对标签文件存放,classes.txt里存放所有的类别,每种一行
classes.txt里存放所有的类别,可以自己起名,需要是英文,如果有空格最好用下划线比如no_hat
上述工作准备好之后,在labelimg环境中cd到data目录下,如果不是在c盘需要先输入其他盘符+:
例如d: 回车之后再输入文件路径,接着输入以下命令打开labelimg
labelimg JPEGImages classes.txt
打开软件后可以看到左侧有很多按钮,open dir是选择图片文件夹,上面选过了
点击change save dir 切换到Annotations目录之中,点击save下面的图标切换到pascal voc格式
切换好之后点击软件上边的view,将 Auto Save mode(切换到下一张图会自动保存标签)和Display Labels(显示标注框和标签) 保持打开状态。
常用快捷键:
A:切换到上一张图片
D:切换到下一张图片
W:调出标注十字架
del :删除标注框
例如,按下w调出标注十字架,标注完成之后选择对应的类别,这张图全部标注完后按d下一张
所有图像标注完成后数据集即制作完成。
如何查看自己数据集格式,打开Annotations文件夹,如果看到文件后缀为.xml,则为VOC格式,如果文件后缀为.txt则为yolo格式,后缀名看不到请搜索 如何显示文件后缀名。yolov8训练需要转为yolo格式训练,转换代码如下:
- import xml.etree.ElementTree as ET
- import pickle
- import os
- from os import listdir, getcwd
- from os.path import join
-
-
- def convert(size, box):
- x_center = (box[0] + box[1]) / 2.0
- y_center = (box[2] + box[3]) / 2.0
- x = x_center / size[0]
- y = y_center / size[1]
- w = (box[1] - box[0]) / size[0]
- h = (box[3] - box[2]) / size[1]
- return (x, y, w, h)
-
-
- def convert_annotation(xml_files_path, save_txt_files_path, classes):
- xml_files = os.listdir(xml_files_path)
- print(xml_files)
- for xml_name in xml_files:
- print(xml_name)
- xml_file = os.path.join(xml_files_path, xml_name)
- out_txt_path = os.path.join(save_txt_files_path, xml_name.split('.')[0] + '.txt')
- out_txt_f = open(out_txt_path, 'w')
- tree = ET.parse(xml_file)
- root = tree.getroot()
- size = root.find('size')
- w = int(size.find('width').text)
- h = int(size.find('height').text)
-
- for obj in root.iter('object'):
- difficult = obj.find('difficult').text
- cls = obj.find('name').text
- if cls not in classes or int(difficult) == 1:
- continue
- 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))
- # b=(xmin, xmax, ymin, ymax)
- print(w, h, b)
- bb = convert((w, h), b)
- out_txt_f.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
-
-
- if __name__ == "__main__":
- # 需要转换的类别,需要一一对应
- classes1 = ['hat','nohat']
- # 2、voc格式的xml标签文件路径
- xml_files1 = r'f:\data\Annotations'
- # 3、转化为yolo格式的txt标签文件存储路径
- save_txt_files1 = r'f:\data\labels'
-
- convert_annotation(xml_files1, save_txt_files1, classes1)
需要自行将类别替换,这里顺序要记住,文件夹也对应替换
训练自己的yolov8检测模型,数据集需要划分为训练集、验证集和测试集,这里提供一个参考代码,划分比例为8:1:1,也可以按照自己的比例划分
- import os
- import shutil
- import random
-
- random.seed(0)
-
-
- def split_data(file_path,xml_path, new_file_path, train_rate, val_rate, test_rate):
- each_class_image = []
- each_class_label = []
- for image in os.listdir(file_path):
- each_class_image.append(image)
- for label in os.listdir(xml_path):
- each_class_label.append(label)
- data=list(zip(each_class_image,each_class_label))
- total = len(each_class_image)
- random.shuffle(data)
- each_class_image,each_class_label=zip(*data)
- train_images = each_class_image[0:int(train_rate * total)]
- val_images = each_class_image[int(train_rate * total):int((train_rate + val_rate) * total)]
- test_images = each_class_image[int((train_rate + val_rate) * total):]
- train_labels = each_class_label[0:int(train_rate * total)]
- val_labels = each_class_label[int(train_rate * total):int((train_rate + val_rate) * total)]
- test_labels = each_class_label[int((train_rate + val_rate) * total):]
-
- for image in train_images:
- print(image)
- old_path = file_path + '/' + image
- new_path1 = new_file_path + '/' + 'train' + '/' + 'images'
- if not os.path.exists(new_path1):
- os.makedirs(new_path1)
- new_path = new_path1 + '/' + image
- shutil.copy(old_path, new_path)
-
- for label in train_labels:
- print(label)
- old_path = xml_path + '/' + label
- new_path1 = new_file_path + '/' + 'train' + '/' + 'labels'
- if not os.path.exists(new_path1):
- os.makedirs(new_path1)
- new_path = new_path1 + '/' + label
- shutil.copy(old_path, new_path)
-
- for image in val_images:
- old_path = file_path + '/' + image
- new_path1 = new_file_path + '/' + 'val' + '/' + 'images'
- if not os.path.exists(new_path1):
- os.makedirs(new_path1)
- new_path = new_path1 + '/' + image
- shutil.copy(old_path, new_path)
-
- for label in val_labels:
- old_path = xml_path + '/' + label
- new_path1 = new_file_path + '/' + 'val' + '/' + 'labels'
- if not os.path.exists(new_path1):
- os.makedirs(new_path1)
- new_path = new_path1 + '/' + label
- shutil.copy(old_path, new_path)
-
- for image in test_images:
- old_path = file_path + '/' + image
- new_path1 = new_file_path + '/' + 'test' + '/' + 'images'
- if not os.path.exists(new_path1):
- os.makedirs(new_path1)
- new_path = new_path1 + '/' + image
- shutil.copy(old_path, new_path)
-
- for label in test_labels:
- old_path = xml_path + '/' + label
- new_path1 = new_file_path + '/' + 'test' + '/' + 'labels'
- if not os.path.exists(new_path1):
- os.makedirs(new_path1)
- new_path = new_path1 + '/' + label
- shutil.copy(old_path, new_path)
-
-
- if __name__ == '__main__':
- file_path = r"f:\data\JPEGImages"
- txt_path = r'f:\data\labels'
- new_file_path = r"f:\VOCdevkit"
- split_data(file_path,txt_path, new_file_path, train_rate=0.8, val_rate=0.1, test_rate=0.1)
划分完成之后数据集的准备工作就好了。
需要下载源码,这里选择的是yolov8 v8.1.0版本的,最新版本随时更新容易出bug
不会下载源码的可以看我的这篇博客点击这里 ,也可以点击链接获取点击链接下载(0积分下载),我这里把源码和预训练权重yolov8n.pt和yolov8s.pt一起打包上传了。
有了源码之后需要修改里面的参数,导入自己的数据集
在yolov8根目录下(也就是本文所用的ultralytics-8.1.0目录下)创建一个新的data.yaml文件,也可以是其他名字的例如hat.yaml文件,文件名可以变但是后缀需要为.yaml,内容如下
- train: f:/VOCdevkit/train/images # train images (relative to 'path') 128 images
- val: f:/VOCdevkit/val/images # val images (relative to 'path') 128 images
- test: f:/VOCdevkit/test/images
-
- nc: 2
-
- # Classes
- names: ['hat','nohat']
其他路径和类别自己替换,需要和上面数据集转换那里类别顺序一致。
这是使用官方提供的预训练权重进行训练,使用yolov8n.pt,也可以使用yolov8s.pt,模型大小n<s<m<l<x,训练时长成倍增加。
下载完成之后放入ultralytics-8.1.0根目录中,创建一个yolov8_train.py文件,内容如下
- from ultralytics import YOLO
- #多线程添加代码
- if __name__ == '__main__':
- # 加载一个模型 ,workers=8
- model = YOLO('ultralytics/cfg/models/v8/yolov8n.yaml') # 从YAML建立一个新模型
- model.load('yolov8n.pt')
-
- # # 训练模型
- results = model.train(data='data.yaml',
- epochs=100, imgsz=640, device=0, workers=8, batch=64, cache=True)
这里用哪个模型对应哪个yaml,如果使用yolov8s.pt则对应yolov8s.yaml
epochs是训练轮数,可以由少变多看训练效果,workers和batch根据电脑性能来,如果运行不起来则相应降低,最好为2的n次方
也可以使用命令行执行训练
yolo task=detect mode=train model=yolov8n.yaml pretrained=yolov8n.pt data=data.yaml epochs=300 imgsz=640 device=0 workers=8 batch=64
训练过程如图,耐心等待训练完成即可,训练完成后会生成.pt权重文件,可以用来验证训练效果。
找到之前训练的结果保存路径,创建一个yolov8_predict.py文件,内容如下
- from ultralytics import YOLO
- # 加载训练好的模型,改为自己的路径
- model = YOLO('runs/detect/train/weights/best.pt')
- # 修改为自己的图像或者文件夹的路径
- source = 'test1.jpg'
- # 运行推理,并附加参数
- model.predict(source, save=True)
运行后就会得到预测模型结果
或者使用命令行指令进行预测,权重和图片路径自己修改
yolo predict model=runs/detect/train/weights/best.pt source='test1.jpg'
可以打开对应路径下查看预测的图片效果,模型就训练好啦~
很多同学的需求是制作出一个可视化界面来展示预测的效果,这里我分享了一个简单的图片预测的界面,导入模型权重文件和图片就可以进行预测并展示,可以参考这篇文章点击这里,界面如下
这个版本功能较为简单,只有图片检测显示
写了一个进阶版,可以对图片,视频和实时摄像头进行检测并展示,界面如下。感兴趣可以私聊
可以点击按钮显示检测到的物体及个数
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。