【算法介绍】
实时目标检测因其低延迟特性而持续受到广泛关注,具有重要的实际应用价值[4, 17, 24, 28]。其中,YOLO系列[3, 24, 28, 29, 32, 45-47, 53, 57, 58]通过有效平衡延迟与精度,在该领域占据主导地位。尽管YOLO的改进多集中在损失函数[8, 35, 43, 44, 48, 67, 68]和标签分配[22, 23, 34, 59, 69]等方面,网络架构设计仍是核心研究方向[24, 28, 32, 57, 58]。尽管以注意力为核心的视觉变换器(ViT)架构已展现出强大的建模能力,特别是在小模型中[20, 21, 25, 50],但大多数架构设计仍聚焦于CNN,这主要受限于注意力机制的效率问题。具体而言,注意力机制面临二次计算复杂度和低效内存访问操作两大挑战(后者正是FlashAttention[13, 14]致力于解决的问题)。因此,在相似计算预算下,基于CNN的架构性能比基于注意力的架构高约3倍[38],这严重阻碍了注意力机制在追求高推理速度的YOLO系统中的应用。
本文旨在应对这些挑战,并构建以注意力为核心的YOLO框架——YOLOv12。我们提出了以下三项关键改进:
- 区域注意力模块(A²):通过简单地将特征图划分为垂直和水平区域,在保持大感受野的同时降低了注意力计算复杂度,从而提升了速度。
- 残差高效层聚合网络(R-ELAN):解决了注意力机制引入的优化难题,特别针对大规模模型。R-ELAN在原始ELAN[57]的基础上进行了两项改进:(i) 引入了采用缩放技术的块级残差设计;(ii) 重新设计了特征聚合方法。
- 架构改进:针对YOLO系统对传统注意力架构进行了调整,包括:(a) 引入FlashAttention以解决注意力内存访问问题;(b) 移除位置编码等设计以提升速度和简洁性;(c) 将MLP比例从4调整为1.2,以平衡注意力与前馈网络的计算量;(d) 减少堆叠块深度以优化训练;(e) 尽可能利用卷积操作的计算效率。
基于上述设计,我们开发了一个包含五种规模(N/S/M/L/X)的新型实时检测器家族。遵循YOLOv11[28]的实验设置(未使用额外技巧),在标准目标检测基准上的大量实验表明,YOLOv12在延迟-精度和FLOPs-精度权衡上显著优于先前模型(如图1所示)。例如:
- YOLOv12-N以40.6% mAP超越了YOLOv10-N[53](提升2.1% mAP)且速度更快,同时以相当速度超越了YOLOv11-N[28](提升1.2% mAP)。
- 相比RT-DETR-R18[66]和RT-DETRv2-R18[40],YOLOv12-S在mAP上分别提升1.5%和0.1%,延迟加快42%,计算量仅需其36%,参数量仅需其45%。
综上,YOLOv12的贡献在于:
- 通过方法论创新和架构改进,成功构建了以注意力为核心的简洁高效的YOLO框架,打破了CNN模型在YOLO系列中的主导地位。
- 在不依赖预训练等额外技术的情况下,YOLOv12以快速的推理速度和更高的检测精度实现了SOTA结果,充分展现了其巨大潜力。
【效果展示】
【测试环境】
anaconda3+python3.10
torch==2.5.1
numpy==1.26.4
cython_bbox-0.1.3-cp310-cp310-win_amd64.whl
注意一定要用源码提供cython_bbox进行安装否则会和numpy不兼容。
【视频演示】
[深度学习][python]yolov12+bytetrack+pyqt5实现目标追踪_哔哩哔哩_bilibili
【调用代码】
from Yolov12Detector import *
from ByteTackManager import *
from tracking_utils.timer import Timer
save_file = None # not None will save video
cap = cv2.VideoCapture('car.mp4')
out = None
frame_fps = int(cap.get(cv2.CAP_PROP_FPS))
# 获取视频帧宽度和高度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print("video fps={},width={},height={}".format(frame_fps, frame_width, frame_height))
if save_file:
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(save_file, fourcc, frame_fps, (frame_width, frame_height))
detector = Yolov12Detector()
tracker = BYTETracker()
frame_id = 0
timer = Timer()
while True:
ret, frame = cap.read()
frame_id += 1
if not ret:
print('read over!')
break
timer.tic()
result_list = detector.inference_image(frame)
if len(result_list)>0:
online_targets = tracker.update(result_list)
#print(online_targets)
online_tlwhs = []
online_ids = []
online_scores = []
for t in online_targets:
tlwh = t.tlwh
tid = t.track_id
vertical = tlwh[2] / tlwh[3] > 1.6
if tlwh[2] * tlwh[3] > 10 and not vertical:
online_tlwhs.append(tlwh)
online_ids.append(tid)
online_scores.append(t.score)
timer.toc()
#print(online_tlwhs)
online_im = plot_tracking(frame, online_tlwhs, online_ids, frame_id=frame_id + 1,
fps=1. / timer.average_time)
if save_file:
out.write(online_im)
cv2.imshow('frame', online_im)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if save_file:
out.release()
cap.release()
cv2.destroyAllWindows()
【参考文献】
1. blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/145725555