1.研究背景与意义
随着城市交通的不断发展和车辆数量的不断增加,交通信号灯的识别系统变得越来越重要。交通信号灯的准确识别对于交通管理、智能交通系统以及自动驾驶等领域具有重要意义。然而,由于交通信号灯的形状、颜色和光照条件的变化,以及复杂的交通场景,交通信号灯的准确识别一直是一个具有挑战性的问题。
目前,基于深度学习的目标检测算法YOLO(You Only Look Once)已经在图像识别领域取得了显著的成果。然而,对于交通信号灯的识别,YOLO算法在准确性和实时性方面仍然存在一定的局限性。另外,OpenCV作为一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法,但是在交通信号灯识别方面的应用还比较有限。
因此,本研究旨在改进YOLO和OpenCV的交通信号灯识别系统,提高其准确性和实时性,并提供部署教程和源码,以便更多的研究人员和工程师能够使用和改进该系统。
本研究的意义主要体现在以下几个方面:
-
提高交通信号灯识别的准确性:通过改进YOLO算法,引入更多的训练数据和优化网络结构,可以提高交通信号灯识别的准确性。准确的交通信号灯识别可以为交通管理和智能交通系统提供更可靠的数据支持,从而提高交通效率和安全性。
-
提高交通信号灯识别的实时性:通过优化算法和使用高性能的硬件设备,可以提高交通信号灯识别系统的实时性。实时的交通信号灯识别可以为自动驾驶系统提供及时的决策依据,从而提高自动驾驶的安全性和可靠性。
-
提供部署教程和源码:通过提供部署教程和源码,可以帮助更多的研究人员和工程师快速理解和使用该交通信号灯识别系统。这将促进交通信号灯识别技术的传播和应用,为交通管理和智能交通系统的发展做出贡献。
总之,改进YOLO和OpenCV的交通信号灯识别系统具有重要的实际意义和应用价值。通过提高识别准确性和实时性,并提供部署教程和源码,可以推动交通信号灯识别技术的发展,为交通管理、智能交通系统和自动驾驶等领域提供更好的解决方案。
2.图片演示
3.视频演示
改进YOLO和OpenCV的交通信号灯识别系统(部署教程&源码)_哔哩哔哩_bilibili
4.BiFPN简介
在本节中,我们首先阐述了多尺度特征融合问题,然后介绍了我们提出的BiFPN的主要思想:有效的双向交叉尺度连接和加权特征融合。
4.1 问题阐述
多尺度特征融合旨在对不同分辨率下的特征进行聚合。形式上,给出了多尺度特征的列表
in = (Pin, Pin ,…)
pl代表所在层的特征,in表示输出,out表示输出
我们的目标是找到一个能有效聚合不同特征并输出新特征列表的变换
f:out = f( pin)
如下图所示:
4.2 跨尺度连接
该博客在CVPR 2017的FPN指出了不同层之间特征融合的重要性,并且以一种比较简单,Heuristic的方法把底层的特征乘两倍和浅层相加来融合。之后人们也试了各种别的融合方法,比如PANet先从底?上连,再自顶向下连回去(上图b);NAS-FPN采用神经架构搜索来搜索更好的跨尺度特征网络难拓扑,但是在搜索过程中需要花费数千个GPU小时,并且发现的网络不规则,难以解释或修改,如上图( c )所示。总之上述都是一些人工各种连接的设计,包含Conv,Sum,Concatenate,Resize,Skip Connection等候选操作。很明显使用哪些操作、操作之间的顺序是可以用NAS搜的。
通过研究这三种网络的性能和效率(如下表),我们观察到PANet比FPN和NAS-FPN具有更好的精度,但需要更多的参数和计算。
PANet效果好于FPN和NAS-FPN,计算代价也更高;
为了提高模型的效率,该论文提出了几种跨尺度连接的优化方法:
首先,我们删除那些只有一个输入边的节点。我们认为:如果一个节点只有一条输入边而没有特征融合,那么它对融合不同特征的特征网络的贡献就会更小。所以我们移除了PANet中P3,P7的中间结点,这就导致了一个简化的双向网络;
其次,我们添加一个跳跃连接,在同一尺度的输入节点到输出节点之间加一个跳跃连接,因为它们在相同层,在不增加太多计算成本的同时,融合了更多的特征。得到上图(d);
最后,与PANet仅有一个自顶向下和一个自底向上的路径不同,我们将每个双向(自顶向下和自底向上)路径看作一个特征网络层(repeated blocks),并多次重复同一层,以实现更高层次的特征融合。
第7节将讨论如何使用YOLOv5引入BIFPN。经过这些优化,我们将新的特征网络命名为双向特征金字塔网络( BiFPN )。
4.3 加权特征融合(Weighted Feature Fusion)
当融合具有不同分辨率的特征时,一种常见的方法是首先将它们调整到相同的分辨率,然后对它们进行融合。金字塔注意网络[Hanchao Li, Pengfei Xiong, Jie An, and Lingxue Wang. Pyramidattention networks.BMVC, 2018]引入全局自注意上采样来恢复像素定位,在Nas-fpn中也有进一步研究。以前的所有方法都一视同仁地对待所有输入特性。然而,我们观察到,由于不同的输入
特征具有不同的分辨率,它们通常对输出特征的贡献是不平等的。为了解天这个口热,华有建以种每个输入增加一个额外的权重,并让网络学习每个输入特性的重要性。基于这一思想,考虑了三种加权融合方法。
5.核心代码讲解
5.1 Interface.py
class YOLOv5Detector:
def __init__(self, weights, data, device='', half=False, dnn=False):
self.weights = weights
self.data = data
self.device = device
self.half = half
self.dnn = dnn
def load_model(self):
FILE = Path(__file__).resolve()
ROOT = FILE.parents[0] # YOLOv5 root directory
if str(ROOT) not in sys.path:
sys.path.append(str(ROOT)) # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
# Load model
device = self.select_device(self.device)
model = self.DetectMultiBackend(self.weights, device=device, dnn=self.dnn, data=self.data)
stride, names, pt, jit, onnx, engine = model.stride, model.names, model.pt, model.jit, model.onnx, model.engine
# Half
half &= (pt or jit or onnx or engine) and device.type != 'cpu' # FP16 supported on limited backends with CUDA
if pt or jit:
model.model.half() if half else model.model.float()
return model, stride, names, pt, jit, onnx, engine
def run(self, model, img, stride, pt, imgsz=(640, 640), conf_thres=0.25, iou_thres=0.45, max_det=1000,
device='', classes=None, agnostic_nms=False, augment=False, half=False):
cal_detect = []
device = self.select_device(device)
names = model.module.names if hasattr(model, 'module') else model.names # get class names
# Set Dataloader
im = self.letterbox(img, imgsz, stride, pt)[0]
# Convert
im = im.transpose((2, 0, 1))[::-1] # HWC to CHW, BGR to RGB
im = np.ascontiguousarray(im)
im = torch.from_numpy(im).to(device)
im = im.half() if half else im.float() # uint8 to fp16/32
im /= 255 # 0 - 255 to 0.0 - 1.0
if len(im.shape) == 3:
im = im[None] # expand for batch dim
pred = model(im, augment=augment)
pred = self.non_max_suppression(pred, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)
# Process detections
for i, det in enumerate(pred): # detections per image
if len(det):
# Rescale boxes from img_size to im0 size
det[:, :4] = self.scale_coords(im.shape[2:], det[:, :4], img.shape).round()
# Write results