YOLO简介
YOLO系列是one-stage且是基于深度学习的回归方法,而R-CNN、Fast-RCNN、Faster-RCNN等是two-stage且是基于深度学习的分类方法。
YOLO的最大优点是快而准,而且识别能力强。
YOLO的使用
YOLO版本的选择
这里我们使用了YOLOv8的版本,YOLOv8在YOLOv5,在识别和训练的速度上都有了很大的提升。
YOLOv8整合在了Ultralytics项目中。
YOLOv8相关源码的下载需要在这里下载:
ultralytics: YOLOv8 🚀 Ultralytics 同步更新官方最新版 YOLOv8 (gitee.com)
下载后,我们主要是使用cfg/models目录如下:
ultralytics/cfg/models
|-- README.md
|-- rt-detr
| |-- rtdetr-l.yaml # 百度的 RT-DETR 目标检测模型(L 规格),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
| |-- rtdetr-x.yaml # 百度的 RT-DETR 目标检测模型(X 规格),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
| |-- rtdetr-resnet101.yaml # Backbone 使用 ResNet101 的 RE-DETR 目标检测模型,使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
| `-- rtdetr-resnet50.yaml # Backbone 使用 ResNet50 的 RE-DETR 目标检测模型,使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
|-- v3
| |-- yolov3.yaml # YOLOv3 目标检测模型,使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
| |-- yolov3-tiny.yaml # YOLOv3 目标检测模型(Tiny 规格),使用的后处理模块为 Detect,💡 使用的预测特征图为 P4, P5,从原来擅长“小中大”目标变为“中大”目标
| `-- yolov3-spp.yaml # 加入 SPP 的 YOLOv3 目标检测模型,使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
|-- v5
| |-- yolov5.yaml # YOLOv5 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
| `-- yolov5-p6.yaml # YOLOv5-p6 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,💡 使用的预测特征图为 P3, P4, P5, P6,加强对大目标的检测能力
|-- v6
| `-- yolov6.yaml # YOLOv6 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
|-- v8
| |-- yolov8.yaml # YOLOv8 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
| |-- yolov8-p2.yaml # YOLOv8 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的预测特征图为 P2, P3, P4, P5,增加对小目标的检测能力
| |-- yolov8-p6.yaml # YOLOv8 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5, P6,增加对大目标的检测能力
| |-- yolov8-ghost.yaml # YOLOv8 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的卷积是 GhostConv 和 C3Ghost,使用的预测特征图为 P3, P4, P5
| |-- yolov8-ghost-p2.yaml # YOLOv8 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的卷积是 GhostConv 和 C3Ghost,使用的预测特征图为 P2, P3, P4, P5,增加了对小目标的检测能力
| |-- yolov8-ghost-p6.yaml # YOLOv8 目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Detect,使用的卷积是 GhostConv 和 C3Ghost,使用的预测特征图为 P3, P4, P5, P6,增加了对大目标的检测能力
| |-- yolov8-cls.yaml # YOLOv8 分类模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Classify
| |-- yolov8-cls-resnet50.yaml # YOLOv8 分类模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Classify,使用的 Backbone 为 ResNet50
| |-- yolov8-cls-resnet101.yaml # YOLOv8 分类模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Classify,使用的 Backbone 为 ResNet101
| |-- yolov8-seg.yaml # YOLOv8 分割模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Segment,使用的预测特征图为 P3, P4, P5
| |-- yolov8-seg-p6.yaml # YOLOv8 分割模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Segment,使用的预测特征图为 P3, P4, P5, P6,增加对大目标的分割能力
| |-- yolov8-obb.yaml # YOLOv8 旋转目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 OBB,使用的预测特征图为 P3, P4, P5
| |-- yolov8-pose.yaml # YOLOv8 关键点/人体姿态估计模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Pose,使用的预测特征图为 P3, P4, P5
| |-- yolov8-pose-p6.yaml # YOLOv8 关键点/人体姿态估计模型(可选规格有:n、s、m、l、x),使用的后处理模块为 Pose,使用的预测特征图为 P3, P4, P5, P6,增加对大目标的估计能力
| |-- yolov8-rtdetr.yaml # YOLOv8 加上 RT-DETR 的目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 RTDETRDecoder,使用的预测特征图为 P3, P4, P5
| |-- yolov8-world.yaml # YOLOv8 加上 YOLO-World 的目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 WorldDetect,head 部分与 YOLOv8 差异较大,使用的预测特征图为 P3, P4, P5,❌ 不支持导出为 ONNX,mAP 低于 YOLOv8-Worldv2
| `-- yolov8-worldv2.yaml # 🌟 YOLOv8 加上 YOLO-World 的目标检测模型(可选规格有:n、s、m、l、x),使用的后处理模块为 WorldDetect,head 部分与 YOLOv8 差异较大,与 YOLOv8-World 也有一些区别,使用的预测特征图为 P3, P4, P5,✅ 支持导出为 ONNX,mAP 高于 YOLOv8-World
`-- v9
|-- yolov9c.yaml # YOLOv6 目标检测模型(规格为 C,t->s->m->c->e),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
`-- yolov9e.yaml # YOLOv6 目标检测模型(规格为 E,t->s->m->c->e),使用的后处理模块为 Detect,使用的预测特征图为 P3, P4, P5
|-- yolov9c-seg.yaml # YOLOv6 分割模型(规格为 C,t->s->m->c->e),使用的后处理模块为 Segment,使用的预测特征图为 P3, P4, P5
`-- yolov9e-seg.yaml # YOLOv6 分割模型(规格为 E,t->s->m->c->e),使用的后处理模块为 Segment,使用的预测特征图为 P3, P4, P5
Ultralytics 整合了 YOLOv6、YOLOv9、YOLOv8-World、百度的 RT-DETR。
安装
pip install ultralytics -i https://pypi.tuna.tsinghua.edu.cn/simple
模型训练
模型训练我们需要一个X-AnyLabeling,为我们标记我们要识别的目标。
我们可以给每个图片都加上标注:
全部加好后,使用labelme2yolo,可以把标记结果,转换成yolo的训练模型。
我们要把生成的文件放在datasets目录下:
我们使用yolov8.yaml进行训练,yolov8.yaml文件详解如下:
# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect
# Parameters
nc: 80 # 类别数目,nc代表"number of classes",即模型用于检测的对象类别总数。 80表示该模型配置用于检测80种不同的对象。由于默认使用COCO数据集,这里nc=80;
scales: # 模型复合缩放常数,用于定义模型的不同尺寸和复杂度。例如 'model=yolov8n.yaml' 将调用带有 'n' 缩放的 yolov8.yaml
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n概览:225层, 3157200参数, 3157184梯度, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s概览:225层, 11166560参数, 11166544梯度, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m概览:295层, 25902640参数, 25902624梯度, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l概览:365层, 43691520参数, 43691504梯度, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x概览:365层, 68229648参数, 68229632梯度, 258.5 GFLOPs
# YOLOv8.0n backbone 骨干层
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2 第0层,-1代表将上层的输出作为本层的输入。第0层的输入是640*640*3的图像。Conv代表卷积层,相应的参数:64代表输出通道数,3代表卷积核大小k,2代表stride步长。卷积后输出的特征图尺寸为320*320*64,长宽为初始图片的1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4 第1层,本层和上一层是一样的操作(128代表输出通道数,3代表卷积核大小k,2代表stride步长)。卷积后输出的特征图尺寸为160*160*128,长宽为初始图片的1/4
- [-1, 3, C2f, [128, True]] # 第2层,本层是C2f模块,3代表本层重复3次。128代表输出通道数,True表示Bottleneck有shortcut。输出的特征图尺寸为160*160*128。
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8 第3层,进行卷积操作(256代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为80*80*256(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样),特征图的长宽已经变成输入图像的1/8。
- [-1, 6, C2f, [256, True]] # 第4层,本层是C2f模块,可以参考第2层的讲解。6代表本层重复6次。256代表输出通道数,True表示Bottleneck有shortcut。经过这层之后,特征图尺寸依旧是80*80*256。
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16 第5层,进行卷积操作(512代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为40*40*512(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样),特征图的长宽已经变成输入图像的1/16。
- [-1, 6, C2f, [512, True]] # 第6层,本层是C2f模块,可以参考第2层的讲解。6代表本层重复6次。512代表输出通道数,True表示Bottleneck有shortcut。经过这层之后,特征图尺寸依旧是40*40*512。
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32 第7层,进行卷积操作(1024代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为20*20*1024(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样),特征图的长宽已经变成输入图像的1/32。
- [-1, 3, C2f, [1024, True]] #第8层,本层是C2f模块,可以参考第2层的讲解。3代表本层重复3次。1024代表输出通道数,True表示Bottleneck有shortcut。经过这层之后,特征图尺寸依旧是20*20*1024。
- [-1, 1, SPPF, [1024, 5]] # 9 第9层,本层是快速空间金字塔池化层(SPPF)。1024代表输出通道数,5代表池化核大小k。结合模块结构图和代码可以看出,最后concat得到的特征图尺寸是20*20*(512*4),经过一次Conv得到20*20*1024。
# YOLOv8.0n head 头部层
head:
- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 第10层,本层是上采样层。-1代表将上层的输出作为本层的输入。None代表上采样的size=None(输出尺寸)不指定。2代表scale_factor=2,表示输出的尺寸是输入尺寸的2倍。mode=nearest代表使用的上采样算法为最近邻插值算法。经过这层之后,特征图的长和宽变成原来的两倍,通道数不变,所以最终尺寸为40*40*1024。
- [[-1, 6], 1, Concat, [1]] # cat backbone P4 第11层,本层是concat层,[-1, 6]代表将上层和第6层的输出作为本层的输入。[1]代表concat拼接的维度是1。从上面的分析可知,上层的输出尺寸是40*40*1024,第6层的输出是40*40*512,最终本层的输出尺寸为40*40*1536。
- [-1, 3, C2f, [512]] # 12 第12层,本层是C2f模块,可以参考第2层的讲解。3代表本层重复3次。512代表输出通道数。与Backbone中C2f不同的是,此处的C2f的bottleneck模块的shortcut=False。
- [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 第13层,本层也是上采样层(参考第10层)。经过这层之后,特征图的长和宽变成原来的两倍,通道数不变,所以最终尺寸为80*80*512。
- [[-1, 4], 1, Concat, [1]] # cat backbone P3 第14层,本层是concat层,[-1, 4]代表将上层和第4层的输出作为本层的输入。[1]代表concat拼接的维度是1。从上面的分析可知,上层的输出尺寸是80*80*512,第6层的输出是80*80*256,最终本层的输出尺寸为80*80*768。
- [-1, 3, C2f, [256]] # 15 (P3/8-small) 第15层,本层是C2f模块,可以参考第2层的讲解。3代表本层重复3次。256代表输出通道数。经过这层之后,特征图尺寸变为80*80*256,特征图的长宽已经变成输入图像的1/8。
- [-1, 1, Conv, [256, 3, 2]] # 第16层,进行卷积操作(256代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为40*40*256(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样)。
- [[-1, 12], 1, Concat, [1]] # cat head P4 第17层,本层是concat层,[-1, 12]代表将上层和第12层的输出作为本层的输入。[1]代表concat拼接的维度是1。从上面的分析可知,上层的输出尺寸是40*40*256,第12层的输出是40*40*512,最终本层的输出尺寸为40*40*768。
- [-1, 3, C2f, [512]] # 18 (P4/16-medium) 第18层,本层是C2f模块,可以参考第2层的讲解。3代表本层重复3次。512代表输出通道数。经过这层之后,特征图尺寸变为40*40*512,特征图的长宽已经变成输入图像的1/16。
- [-1, 1, Conv, [512, 3, 2]] # 第19层,进行卷积操作(512代表输出通道数,3代表卷积核大小k,2代表stride步长),输出特征图尺寸为20*20*512(卷积的参数都没变,所以都是长宽变成原来的1/2,和之前一样)。
- [[-1, 9], 1, Concat, [1]] # cat head P5 第20层,本层是concat层,[-1, 9]代表将上层和第9层的输出作为本层的输入。[1]代表concat拼接的维度是1。从上面的分析可知,上层的输出尺寸是20*20*512,第9层的输出是20*20*1024,最终本层的输出尺寸为20*20*1536。
- [-1, 3, C2f, [1024]] # 21 (P5/32-large) 第21层,本层是C2f模块,可以参考第2层的讲解。3代表本层重复3次。1024代表输出通道数。经过这层之后,特征图尺寸变为20*20*1024,特征图的长宽已经变成输入图像的1/32。
- [[15, 18, 21], 1, Detect, [nc]] # Detect(P3, P4, P5) 第20层,本层是Detect层,[15, 18, 21]代表将第15、18、21层的输出(分别是80*80*256、40*40*512、20*20*1024)作为本层的输入。nc是数据集的类别数。
再增加dataset.yaml文件,用来指明训练文件的位置和数据分类
train: images/train/
val: images/val/
test: images/test/
nc: 1
names: ["laili"]
使用:
yolo task=detect mode=train model=yolov8.yaml data=dataset.yaml epochs=300 batch=1 save=true workers=0 device=0
就可以开始模型训练了,我这里使用了epoches使用了300。
训练结果放在下面的文件夹中:
从结果可以看出box_loss,训练完成后,值只有1左右,已经符合检测的能力了。
使用训练好的模型进行检测任务
yolo task=detect mode=predict model=mymodel/last.pt source=test/img.png
E:\code\test\python\yolov8>yolo task=detect mode=predict model=mymodel/best.pt source=test/img.png
Ultralytics YOLOv8.2.35 🚀 Python-3.8.19 torch-2.3.0 CUDA:0 (Quadro P2000, 5120MiB)
D:\Anaconda3\envs\cv\lib\site-packages\torch\nn\modules\conv.py:456: UserWarning: Plan failed with a cudnnException: CUDNN_BACKEND_EXECUTION_PLAN_DESCRIPTOR: cudnnFinalize Descriptor Failed cudnn_status: CUDNN_STATUS_NOT_SUPPORTED (Triggered internally at C:\cb\pytorch_1000000000000\work\aten\src\ATen\native\cudnn\Conv_v8.cpp:919.)
return F.conv2d(input, weight, bias, self.stride,
YOLOv8 summary (fused): 168 layers, 3005843 parameters, 0 gradients, 8.1 GFLOPs
image 1/1 E:\code\test\python\yolov8\test\img.png: 448x640 1 laili, 32.2ms
Speed: 2.0ms preprocess, 32.2ms inference, 2.0ms postprocess per image at shape (1, 3, 448, 640)
Results saved to runs\detect\predict4
💡 Learn more at https://docs.ultralytics.com/modes/predict
执行完成,这里提示结果保存在predict4文件夹中了,在文件中,我们找到结果图片:
这里我们让它检测小女孩的头,它成功检测出来了。
使用官方的模型进行检测
我们要在官方下载模型。
https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8n.pt
https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8s.pt
https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8m.pt
https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8l.pt
https://github.com/ultralytics/assets/releases/download/v8.2.0/yolov8x.pt
不同的后缀表示不同的模型规模,具体如下:
Model | size (pixels) | mAPval | Speed CPU ONNX | Speed A100 TensorRT | params (M) | FLOPs (B) |
640 | 37.3 | 80.4 | 0.99 | 3.2 | 8.7 | |
640 | 44.9 | 128.4 | 1.20 | 11.2 | 28.6 | |
640 | 50.2 | 234.7 | 1.83 | 25.9 | 78.9 | |
640 | 52.9 | 375.2 | 2.39 | 43.7 | 165.2 | |
640 | 53.9 | 479.1 | 3.53 | 68.2 | 257.8 |
这里我们选择n模式的,速度是最快的。
使用命令:
yolo task=detect mode=predict model=yolov8n.pt source=test/1.png
识别的结果:
结语
YOLO框架是一个优秀的CV框架,简单易用。现在清华大学在YOLO的基础上,推出了YOLOv10,比YOLOv8更加强大,以后我也会继续学习。