YOLOv5 是一个流行的目标检测模型,它在精度和速度方面都表现优异。本文将为你提供一个全面的指南,从环境配置到如何训练和使用 YOLOv5 进行目标检测。
一. 环境设置
在开始使用 YOLOv5 之前,你需要配置好 Python 环境,并安装必要的依赖项。
1.1 安装 Python 和虚拟环境
本文就不概述Python运行环境相关的配置了,咱们直接进入正文
1.2 安装 YOLOv5 和依赖项
使用 pip
安装 YOLOv5 所需的依赖项。首先,克隆 YOLOv5 仓库并进入目录:
仓库链接:GitHub - ultralytics/yolov5: YOLOv5 🚀 in PyTorch > ONNX > CoreML > TFLite
可以通过GIT克隆或者直接下载代码
下载完成,进入文件目录,安装依赖项:
pip install -U -r requirements.txt
1.3 准备相关文件进行训练
在yolov5文件夹下新建一个文件夹,这里取名为VOCData
进入后新建两个文件夹 Annotations 和 images
images:用于存放要标注的图片(jpg格式)
Annotations :用于存放标注图片后产生的内容
二. 数据准备
2.1 数据集格式
YOLOv5 支持多种数据集格式,但通常使用 VOC(XML格式) 或 YOLO(txt格式) 格式。数据集应包括图片和标签文件。标签文件通常是 .txt
格式,每行包含一个目标的类标签和边界框坐标。
此处我使用的是VOC格式,因为直接使用YOLO格式有个小小的坑,使用VOC格式可以直接避免这个问题
此时我们就需要用到labelImage了
2.2 安装labellmg
下载labelImg:
pip install labelImg
安装完成,直接运行命令启动
labelImg
主界面
页面介绍:
选择要标注的图片,框选标注区域,标注图片标签
快捷键:
W:创建区域框
A:上一张图片
D:下一站图片
2.2 标注的文件格式:
三. 划分数据集以及配置文件的修改
3.1 在VOCData目录下创建程序 split_train_val.py
并运行,内容不用修改
# coding:utf-8
import os
import random
import argparse
parser = argparse.ArgumentParser()
#xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
parser.add_argument('--xml_path', default='Annotations', type=str, help='input xml label path')
#数据集的划分,地址选择自己数据下的ImageSets/Main
parser.add_argument('--txt_path', default='ImageSets/Main', type=str, help='output txt label path')
opt = parser.parse_args()
trainval_percent = 1.0 # 训练集和验证集所占比例。 这里没有划分测试集
train_percent = 0.9 # 训练集所占比例,可自己进行调整
xmlfilepath = opt.xml_path
txtsavepath = opt.txt_path
total_xml = os.listdir(xmlfilepath)
if not os.path.exists(txtsavepath):
os.makedirs(txtsavepath)
num = len(total_xml)
list_index = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list_index, tv)
train = random.sample(trainval, tr)
file_trainval = open(txtsavepath + '/trainval.txt', 'w')
file_test = open(txtsavepath + '/test.txt', 'w')
file_train = open(txtsavepath + '/train.txt', 'w')
file_val = open(txtsavepath + '/val.txt', 'w')
for i in list_index:
name = total_xml[i][:-4] + '\n'
if i in trainval:
file_trainval.write(name)
if i in train:
file_train.write(name)
else:
file_val.write(name)
else:
file_test.write(name)
file_trainval.close()
file_train.close()
file_val.close()
file_test.close()
运行完后会在VOCData\ImagesSets\Main下生成 测试集、训练集、训练验证集和验证集
3.2 将xml格式转为yolo_txt格式
在VOCData目录下创建程序 text_to_yolo.py 并运行
开头classes部分改成你自己的类别,我这里是识别0-9个类别
文件路径切换成你自己项目文件的路径
# -*- coding: utf-8 -*-
import xml.etree.ElementTree as ET
import os
from os import getcwd
sets = ['train', 'val', 'test']
classes = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] # 改成自己的类别
abs_path = os.getcwd()
print(abs_path)
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(image_id):
in_file = open('D:\project\YOLO\Annoations\%s.xml' % (image_id), encoding='UTF-8')
out_file = open('D:/project/YOLO/yolov5/VOCData/labels/%s.txt' % (image_id), 'w')
tree = ET.parse(in_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
# 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))
b1, b2, b3, b4 = b
# 标注越界修正
if b2 > w:
b2 = w
if b4 > h:
b4 = h
b = (b1, b2, b3, b4)
bb = convert((w, h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
wd = getcwd()
for image_set in sets:
if not os.path.exists('D:/project/YOLO/yolov5/VOCData/labels/'):
os.makedirs('D:/project/YOLO/yolov5/VOCData/labels/')
image_ids = open(
'D:/project/YOLO/yolov5/VOCData/ImageSets/Main/%s.txt' % (image_set)).read().strip().split()
if not os.path.exists('D:/project/YOLO/yolov5/VOCData/dataSet_path/'):
os.makedirs('D:/project/YOLO/yolov5/VOCData/dataSet_path/')
list_file = open('dataSet_path/%s.txt' % (image_set), 'w')
for image_id in image_ids:
list_file.write('D:/project/YOLO/yolov5/VOCData/images/%s.PNG\n' % (image_id))
convert_annotation(image_id)
list_file.close()
运行完后会生成如下 labels 文件夹和 dataSet_path 文件夹
其中 labels 中为不同图像的标注文件。每个图像对应一个txt文件,文件每一行为一个目标的信息,包括class, x_center, y_center, width, height格式,这种即为 yolo_txt格式。
dataSet_path文件夹包含三个数据集的txt文件,train.txt等txt文件为划分后图像所在位置的绝对路径,如train.txt就含有所有训练集
3.3 配置文件
在 yolov5 目录下的 data 文件夹下 新建一个 myvoc.yaml文件(可以自定义命名),用记事本打开。
内容是:
训练集以及验证集(train.txt和val.txt)的路径(可以改为相对路径)
以及 目标的类别数目和类别名称。
train: D:\project\YOLO\yolov5\VOCData\dataSet_path\train.txt
val: D:\project\YOLO\yolov5\VOCData\dataSet_path\val.txt
# Classes
nc: 10
names: [ "0","1","2","3","4","5","6","7","8","9" ]
四. 模型训练
在yoloV5文件夹新建weights目录,接着输入如下训练命令:
python train.py --weights weights/yolov5s.pt --cfg models/yolov5s_num.yaml --data data/coco_num.yaml --epochs 200 --batch-size 6 --multi-scale --device 0 --workers 6
4.1 参数解释:
–weights weights/yolov5s.pt :yolov5模型放置目录
–epoch 200 :训练200次
–batch-size 6:训练6张图片后进行权重更新
–device 0:使用GPU训练。//这里device cpu为cpu训练
训练好的模型会被保存在 yolov5 目录下的 runs/train/expxx/weights下。
五. 效果展示
yolov5主目录下找到detect.py文件,打开该文件
主要是weights和source处修改:
以打开笔记本摄像头为例子:
加载训练器:找到这行并修改
parser.add_argument("--weights", nargs="+", type=str, default="weights/best.pt", help="model path or triton URL")
加载摄像头进行识别:(图片视频default修改路径就行如'test1.jpg',摄像头default为0)
parser.add_argument('--source', type=str, default=0, help='source') # file/dir/URL/glob/screen/0(webcam)
运行detect.py
效果展示: