目录
YOLOv3(You Only Look Once version 3)简介
YOLOv3 的主要特点
YOLOv3 的结构
1. 特征提取网络(Backbone)
2. 检测头(Head)
3. 输出层
YOLOv3 损失函数
YOLOv3 的优势
YOLOv3 的应用
YOLOv3 的局限性
实现思路
1. 加载模型和配置文件:
2. 视频读取:
3. 初始化跟踪器:
4. YOLOv3目标检测:
5. 目标跟踪:
6. 结果展示:
7. 资源释放:
整体代码
效果图
总结
YOLOv3(You Only Look Once version 3)简介
YOLOv3 是一种目标检测模型,它是 YOLO(You Only Look Once)系列模型的第三个版本,主要改进了之前版本的精度和速度。YOLOv3 可以在单次推理中同时识别图像中的多个目标,它通过回归问题将目标检测任务转化为一个单一的回归问题,从而实现了非常高的检测速度。YOLOv3 在速度和精度之间提供了良好的平衡,成为了工业和学术界广泛使用的目标检测模型。
YOLOv3 由 Joseph Redmon 和 Santosh Divvala 等人提出,主要的创新包括:
- 更好的多尺度检测:通过使用三个不同尺度的特征图来检测不同尺寸的目标。
- 更精确的特征提取网络:YOLOv3 使用了一个新的特征提取网络(Darknet-53),相比于之前的 YOLOv2 使用的 Darknet-19,它更深更强,能够提取更多的图像特征。
- 改进的损失函数:YOLOv3 对损失函数进行了改进,加入了对边界框位置、置信度、类别概率等因素的多方面考虑,使得模型能够更准确地进行目标检测。
YOLOv3 的主要特点
-
实时性和高效率:YOLOv3 可以实时进行目标检测,尤其适合需要实时反馈的应用场景,比如自动驾驶、监控摄像头等。
-
端到端训练和推理:YOLOv3 是一个端到端的模型,不需要额外的区域提议(region proposals)阶段。通过单一的神经网络结构,YOLOv3 可以在一次前向推理中同时完成目标的定位和分类。
-
高精度和高速度:虽然 YOLOv3 的推理速度非常快,但它并没有牺牲精度。YOLOv3 在 COCO 数据集上的表现优于许多其他实时目标检测模型(如 SSD 和 Faster R-CNN)。
-
支持多类别和多尺度检测:YOLOv3 支持大规模的类别检测(COCO 数据集中的 80 类物体),并且能够检测大小不一的目标物体,尤其是在小物体的检测上有显著提高。
-
使用 Leaky ReLU 激活函数:YOLOv3 使用了 Leaky ReLU 替代传统的 ReLU 激活函数,能够避免 ReLU 在某些情况下出现死神经元(dead neurons)问题。
-
检测层次结构:YOLOv3 使用三种不同大小的特征图来进行目标检测,从而更好地处理小物体、大物体的检测任务。其采用了类似 FPN(Feature Pyramid Networks)的结构,能够有效利用不同尺度的特征进行多尺度目标检测。
YOLOv3 的结构
YOLOv3 的整体架构分为两个主要部分:特征提取网络(Backbone) 和 检测头(Head)。
1. 特征提取网络(Backbone)
YOLOv3 使用 Darknet-53 作为其特征提取网络。Darknet-53 是一个具有 53 层的卷积神经网络,相比于 YOLOv2 使用的 Darknet-19,Darknet-53 更深且具备更强的特征提取能力。Darknet-53 由残差块组成,可以更有效地提取图像中的低级和高级特征。
2. 检测头(Head)
YOLOv3 的检测头负责从特征图中提取目标的边界框坐标、置信度以及类别信息。YOLOv3 采用了三个不同尺度的特征图来进行检测:一个用于检测大物体,一个用于中等物体,另一个用于小物体。这些特征图分别来自网络中不同深度的卷积层。
3. 输出层
YOLOv3 的输出是一个 3D 张量,包含了边界框的位置(x, y, w, h)、置信度和类别概率。输出的每个单元表示一个预测框的信息。
- 每个预测框会有 4 个坐标值(x, y, w, h),表示边界框的位置和尺寸。
- 每个框还会有一个置信度值,表示该框内包含目标的置信度。
- 最后,每个框还会包含与每个类别相关的类别概率分布。
YOLOv3 损失函数
YOLOv3 使用了一个多任务损失函数,结合了位置损失、置信度损失和类别损失:
-
位置损失(Localization Loss):该损失用于优化边界框的预测精度,通常使用均方误差(MSE)来计算。
-
置信度损失(Confidence Loss):该损失用于衡量每个预测框内是否包含目标物体,越接近 1 说明预测越准确,目标物体越确定。YOLOv3 对所有预测框都计算了置信度损失。
-
类别损失(Classification Loss):该损失用于计算每个框的类别预测误差,通常使用交叉熵损失来计算。
YOLOv3 的优势
-
实时性强:相较于许多传统的目标检测方法(如 Faster R-CNN),YOLOv3 的检测速度更快,适合实时应用。
-
精度高:YOLOv3 在大型数据集(如 COCO、PASCAL VOC)上的精度较高,尤其是在小物体检测方面有所改进。
-
多尺度检测:YOLOv3 的多尺度检测策略使得它能够在不同大小的物体上都有较好的表现。
YOLOv3 的应用
YOLOv3 被广泛应用于以下领域:
-
自动驾驶:YOLOv3 能够实时识别道路上的车辆、行人、交通标志等物体,对于自动驾驶系统的目标检测至关重要。
-
视频监控:YOLOv3 可以用来实时分析监控视频,识别入侵者、车辆或其他目标。
-
工业检测:在工业制造过程中,YOLOv3 可用于缺陷检测、零件识别等。
-
无人机目标检测:YOLOv3 适用于无人机上的实时物体识别,能够进行高效的目标追踪和监控。
YOLOv3 的局限性
尽管 YOLOv3 在速度和精度上都表现出色,但仍然存在一些局限性:
-
小物体检测问题:虽然 YOLOv3 引入了多尺度特征图来改进小物体检测,但对于极小的物体,它的检测精度仍然不如其他更精细的检测模型(如 Faster R-CNN 或 RetinaNet)。
-
精度与速度的平衡:YOLOv3 主要专注于速度,因此在极高精度的需求下,可能不如一些其他的目标检测模型。
实现思路
1. 加载模型和配置文件:
- 代码首先加载了COCO数据集中的类别名称(
coco.names
)和YOLOv3的配置文件(yolov3.cfg
)以及权重文件(yolov3.weights
)。这些文件是YOLOv3模型进行物体检测所需要的。 net = cv2.dnn.readNet()
用来加载YOLO模型,getLayerNames()
和getUnconnectedOutLayers()
获取模型的输出层名称。
2. 视频读取:
- 使用
cv2.VideoCapture()
打开一个视频文件,这里假设视频文件名为test1.mp4
,你可以更换成其他的视频文件路径。 - 每帧视频将会被读取,并传入后续的目标检测和跟踪部分。
3. 初始化跟踪器:
- 使用
cv2.TrackerCSRT_create()
创建CSRT(Channel and Spatial Reliability Tracking)跟踪器。CSRT是一个高效的多目标跟踪算法,适用于动态物体(如车辆)跟踪。 tracker.init(frame, bbox)
初始化跟踪器,bbox
是目标的边界框坐标(x, y, w, h),代表车辆在视频中的位置。
4. YOLOv3目标检测:
yolo_detection(frame)
是目标检测函数,首先将图像转换成YOLO模型所需的输入格式(blobFromImage()
)。然后,将图像传入YOLO模型进行前向传播,获得每个检测框的信息(如位置、类别、置信度)。- 根据YOLO的检测结果,代码筛选出置信度大于0.5且类别为“车”、“巴士”和“卡车”的目标,这些目标会被添加到跟踪列表中。
5. 目标跟踪:
- 初始化跟踪器后,开始对视频中的目标进行跟踪。在
while
循环中,程序不断读取视频帧并更新所有的跟踪器。 - 每次更新时,通过
tracker.update(frame)
获取新的目标位置。如果跟踪成功,更新目标的边界框,并绘制在视频帧上;如果跟踪失败,则显示“Tracking failure”提示。
6. 结果展示:
- 每一帧被处理后,将通过
cv2.imshow()
显示出来。如果按下键盘上的 'q' 键,程序会退出循环并关闭窗口。 - 绘制的跟踪框使用绿色(
(0, 255, 0)
),并在框上方显示“Vehicle ID”来标识每个目标。
7. 资源释放:
- 在程序结束时,
cap.release()
释放视频文件,cv2.destroyAllWindows()
关闭所有OpenCV的窗口。
整体代码
import cv2
import numpy as np
# 加载类别名称
with open("../needFiles/coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
# 加载YOLOv3配置文件和权重文件
net = cv2.dnn.readNet("../needFiles/yolov3.weights", "../needFiles/yolov3.cfg")
# 获取输出层名称
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
# 打开视频文件(这里假设无人机视频文件为input_video.mp4)
cap = cv2.VideoCapture("./videos/test1.mp4")
# 初始化变量
trackers = [] # 用于存储多个跟踪器
bboxes = [] # 存储所有目标的边界框
frame_count = 0
# 车辆类别的ID(以COCO数据集为例)
vehicle_classes = ['car', 'bus', 'truck'] # 需要跟踪的车辆类别
vehicle_class_ids = [2, 5, 7] # 对应的类别ID
# 使用跟踪算法
def init_tracker(frame, bbox):
# 使用CSRT跟踪器(适合动态物体)
tracker = cv2.TrackerCSRT_create()
tracker.init(frame, bbox)
return tracker
# YOLOv3检测
def yolo_detection(frame):
blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)
class_ids = []
confidences = []
boxes = []
height, width, _ = frame.shape
for out in outs:
for detection in out:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.5: # 置信度阈值
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
# 如果检测到的是车辆类别,则将目标添加到跟踪列表
if class_id in vehicle_class_ids:
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
# 使用非极大值抑制(NMS)过滤多余的框
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
return boxes, confidences, class_ids, indexes
# 选择视频中的一帧图像进行目标选择
ret, frame = cap.read()
if not ret:
print("无法读取视频文件!")
cap.release()
exit()
# 目标检测并初始化目标跟踪
boxes, confidences, class_ids, indexes = yolo_detection(frame)
for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
bbox = (x, y, w, h) # 目标框坐标
tracker = init_tracker(frame, bbox)
trackers.append(tracker)
bboxes.append(bbox)
# 跟踪目标
while True:
ret, frame = cap.read()
if not ret:
break
# 调整帧大小以适应显示器
screen_width = 800 # 设置显示器宽度
screen_height = int(frame.shape[0] * (screen_width / frame.shape[1]))
frame_resized = cv2.resize(frame, (screen_width, screen_height))
# 更新所有的跟踪器
for i, tracker in enumerate(trackers):
success, bbox = tracker.update(frame)
# 绘制跟踪框
if success:
x, y, w, h = [int(v) for v in bbox]
cv2.rectangle(frame_resized, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame_resized, f"Vehicle ID: {i+1}", (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
else:
cv2.putText(frame_resized, "Tracking failure", (100, 80), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# 显示图像
cv2.imshow("WenJGo", frame_resized)
# 按 'q' 键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
效果图
总结
YOLOv3 是一款强大的实时目标检测模型,它在精度和速度之间提供了很好的平衡。通过引入更深的网络架构、多个尺度的检测和改进的损失函数,YOLOv3 在多种应用场景中都取得了优秀的表现。对于需要快速处理并识别图像中多目标的任务,YOLOv3 是一个非常优秀的选择。但是我觉得我现在还用的不好。