摘要:随着计算机视觉技术的发展,目标检测算法在工业、交通、安全等领域扮演着越来越重要的角色。YOLO(You Only Look Once)系列算法以其快速准确的检测性能而广受欢迎。本文聚焦于YOLOv8在小目标检测中的改进,通过引入多尺度特征融合、注意力机制等技术
随着计算机视觉技术的发展,目标检测算法在工业、交通、安全等领域扮演着越来越重要的角色。YOLO(You Only Look Once)系列算法以其快速准确的检测性能而广受欢迎。本文聚焦于YOLOv8在小目标检测中的改进,通过引入多尺度特征融合、注意力机制等技术,显著提升了小目标的检测性能。
小目标检测是目标检测领域中的一个挑战性问题,尤其是在复杂背景和低分辨率图像中。YOLOv8作为YOLO系列的最新成员,通过一系列创新改进,如CSPNet主干网络、FPN+PAN结构、无锚点(anchor-free)检测等,提高了小目标的检测准确性和效率。
YOLOv8网络结构
YOLOv8的网络结构包括输入端、Backbone、Neck和Head四部分。Backbone负责提取特征,Neck进行特征融合,Head负责最终的目标检测。
1.Backbone
YOLOv8的Backbone采用CSPNet结构,该结构通过跨阶段部分连接(Cross Stage Partial Connections)增强了特征提取能力,特别适合小目标的特征学习。
2.Neck
Neck部分,YOLOv8采用了FPN+PAN结构,通过多尺度特征融合,增强了对小目标的检测能力。特别是在Neck的最后,增加了上采样、concatenate和C2f模块,将Backbone中丢弃的P2特征图也融合进来,进一步提升小目标的特征表示。
3.Head
Head部分,YOLOv8采用了anchor-free的检测头,通过直接预测边界框的偏移量,减少了锚点带来的限制,提高了小目标的检测精度。
小目标检测改进策略
1.多尺度特征融合
为了更好地检测小目标,YOLOv8通过FPN结构融合了不同尺度的特征图,使得网络能够同时捕捉到全局和局部信息,增强了对小目标的检测能力。
import torch
import torch.nn as nn
import torch.nn.functional as F
class FPN(nn.Module):
def __init__(self, features_channels, out_channels):
super(FPN, self).__init__
# 特征层的通道数
self.feat_channels = features_channels
# 输出层的通道数
self.out_channels = out_channels
# 给每个特征层添加一个1x1卷积层用于通道数的变换
self.reduce_layers = nn.ModuleList([nn.Conv2d(c, out_channels, 1) for c in features_channels])
# 给每个特征层上采样之后的结果添加3x3卷积层用于平滑处理
self.smooth_layers = nn.ModuleList([nn.Conv2d(out_channels, out_channels, 3, padding=1) for _ in features_channels])
def forward(self, features):
# 假设输入features是一个由底层到顶层的特征序列的元组
# 从底层特征开始处理
x0 = self.reduce_layers[0](features[0])
x1 = self.reduce_layers[1](features[1])
x2 = self.reduce_layers[2](features[2])
# 将最顶层的特征图上采样与次顶层特征图进行融合
x1 = x1 + F.interpolate(x2, scale_factor=2, mode='nearest')
# 将次顶层的特征图上采样与底层特征图进行融合
x0 = x0 + F.interpolate(x1, scale_factor=2, mode='nearest')
# 使用3x3卷积平滑处理
x0 = self.smooth_layers[0](x0)
x1 = self.smooth_layers[1](x1)
# 返回融合后的特征图
return x0, x1
# 假设输入的特征图的通道数分别是256, 512, 1024
features_channels = [256, 512, 1024]
out_channels = 256
# 创建FPN模块
fpn = FPN(features_channels, out_channels)
# 假设输入的特征图
features = (torch.rand(1, 256, 64, 64),
torch.rand(1, 512, 32, 32),
torch.rand(1, 1024, 16, 16))
# 获取融合后的特征图
x0, x1 = fpn(features)
2.注意力机制
YOLOv8引入了注意力机制,如CABM、ECA等,这些机制能够聚焦于图像中的关键区域,提高了小目标的特征表示能力。
import torch
class CABM(nn.Module):
def __init__(self, channels, reduction=16):
super(CABM, self).__init__
self.channels = channels
self.reduction = reduction
self.query_conv = nn.Conv2d(channels, channels // reduction, kernel_size=1)
self.key_conv = nn.Conv2d(channels, channels // reduction, kernel_size=1)
self.value_conv = nn.Conv2d(channels, channels, kernel_size=1)
self.gamma = nn.Parameter(torch.zeros(1))
def forward(self, x):
proj_query = self.query_conv(x).view(x.size(0), -1, x.size(2)*x.size(3)).permute(0, 2, 1)
proj_key = self.key_conv(x).view(x.size(0), -1, x.size(2)*x.size(3))
energy = torch.bmm(proj_query, proj_key)
attention = F.softmax(energy, dim=-1)
# Context-Aware Background Modulation
background = torch.mean(attention, dim=-2, keepdim=True)
modulated_attention = attention * background
proj_value = self.value_conv(x).view(x.size(0), -1, x.size(2)*x.size(3))
out = torch.bmm(proj_value, modulated_attention.permute(0, 2, 1))
out = out.view(x.size(0), x.size(1), x.size(2), x.size(3))
# Scale and add residual
out = self.gamma * out + x
return out
# Example usage
channels = 256
reduction = 16
input_tensor = torch.rand(1, channels, 32, 32) # Example input tensor
cabm = CABM(channels, reduction)
output_tensor = cabm(input_tensor)
在这个简化的CABM模块中,我们首先通过1x1卷积将输入特征图的通道数减少,然后计算query、key和value。接着,我们计算query和key之间的注意力分数,并应用softmax函数进行归一化。然后,我们通过计算注意力分数的平均值来获取背景信息,并将其与注意力分数相乘以调制注意力分数。最后,我们将调制后的注意力分数与value相乘,并通过1x1卷积将结果与输入特征图相加,得到最终的输出。
3.可变形卷积
YOLOv8还优化了可变形卷积层(DCN),这种卷积能够适应目标的形状变化,对于小目标的检测尤为有效。
以下是一段改进后的YOLOv8检测代码示例:
import cv2
from ultralytics import YOLO
# 加载YOLOv8模型
model = YOLO('yolov8n.pt')
# 打开视频文件
cap = cv2.VideoCapture('video.mp4')
# 定义感兴趣区域 (roi)
roi_top_left = (100, 400)
roi_bottom_right = (500, 800)
def is_in_roi(box, roi_top_left, roi_bottom_right):
"""
判断目标的边界框是否位于ROI内。
"""
x1, y1, x2, y2 = box
return (x1 > roi_top_left[0] and x2
y1 > roi_top_left[1] and y2
while cap.isOpened:
ret, frame = cap.read
if not ret:
break
# 对每一帧进行目标检测
results = model(frame)
# 在帧上绘制ROI
cv2.rectangle(frame, roi_top_left, roi_bottom_right, (0, 255, 0), 2)
# 区域内目标计数
count = 0
for result in results:
boxes = result.boxes.xyxy.cpu.numpy # 获取目标边界框
for box in boxes:
if is_in_roi(box, roi_top_left, roi_bottom_right):
count += 1
# 在帧上显示计数
cv2.putText(frame, f'Count: {count}', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 显示检测结果
cv2.imshow('YOLOv8 Detection', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release
cv2.destroyAllWindows
下图是运用魔乐社区来进行YOLOv8目标检测
魔乐社区中已经上传了相应的YOLOv8版本,以及它的各种已经训练过的版本,并且可以根据魔乐社区中提供的数据集下载到本地然后训练模型,或者根据自己的数据集来训练更适合自己所需的模型。
首先我们要从魔乐社区中下载模型
以此版本为例
可以根据自己的需要,从多种方式下载
使用的方法很简单,简单分为两种
(1)直接使用:我们可以直接在模型主页点击Use in openmind,由于openmind与魔乐社区的高度融合,我们可以直接在开发环境里使用对应的openmind library来加载所需要的模型,下图为示例
(2)下载到本地:此方法可以直接将模型下载到本地,只需要使用git工具即可将社区中的模型下载到本地使用以及微调
点击下载模型
可见,下载方式也很多
使用git工具下载之后,可以在下载路径中找到,然后就可以直接使用了。
体验空间
在魔乐社区中有实现模型的体验空间,用于对上述目标检测的体验,在页面内上传图片就可以自动检测出图片中物品的类别。视觉识别模型能够通过分析和处理图像数据来识别和分类各种物体。这种技术在精确度和速度上往往超越了人类的视觉限制,为工业自动化、安全监控等多个领域带来了革命性的进步。
图中上传了一张船舶的照片,自动识别出了这是一条船。
上传不同类型的船舶,同样可以识别出来。
上传一艘快艇同样可以识别出来是船的类别。
体验空间链接如下:DataFun/yolov8 | 魔乐社区
本地训练
训练所需的数据集也可以直接在魔乐社区中下载,也可以直接使用git工具下载到本地进行训练。
模型的微调可以根据上文的介绍,对卷积层,池化层以及全连接层进行增加或者改变,可以多尝试来找到最适合自己的那一个微调模型,此外,还可以根据已有的模型来进行迁移学习,冻结某些卷积层或者改变激活函数,也许可以获得更好的效果。
以下是从魔乐社区下载的预训练模型对睡眠船舶目标检测的混淆矩阵图,可见对于效果显著
下图为在测试集上的效果,置信度也较高
YOLOv8通过引入多尺度特征融合、注意力机制和可变形卷积等技术,显著提升了小目标的检测性能。未来的研究可以进一步探索更高效的特征融合方法和更强大的注意力机制,以应对日益复杂的检测场景。而在魔乐社区上,可以直接下载预训练模型和权重,方便开发者直接使用和预测,或者直接对模型进行调整和改进,以便适应更复杂的数据集。
来源:DataFunTalk