ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于YOLOv5与OpenCV的红绿灯识别系统:从训练到部署全流程解析

2026/9/4 0:45:04 拓冰建站 浏览量
基于YOLOv5与OpenCV的红绿灯识别系统:从训练到部署全流程解析 简介本资源是一套基于YOLOv5与OpenCV实现的道路红绿灯智能识别检测系统面向计算机视觉初学者、智能交通项目开发者及AI模型部署实践者解决真实场景下多类别交通灯红灯、绿灯、黄灯、交通灯的端到端检测与识别问题。压缩包共79个文件含17个Python源码含train.py、detect.py、test.py等核心脚本、17个YAML配置文件含数据集路径、超参设置、3个PyTorch模型文件.pt、7张可视化图像含训练批次图、预测结果图、PR曲线图等以及Dockerfile、Shell脚本和详细使用说明文档整体大小为41.68MB。目前已有1483人学习下载。资源提供完整可运行工程不仅包含训练好的yolov5s.pt模型还附带200轮迭代的loss下降曲线、Recall/Precision/mAP等关键评估指标曲线图以及数据集标注规范与推理演示逻辑便于读者快速复现、调优或迁移至嵌入式/边缘设备部署。1. 项目概述从零到一构建一个能“看懂”红绿灯的AI系统最近在整理过往项目时翻出了一个挺有意思的“老伙计”——一个基于YOLOv5和OpenCV的道路红绿灯识别检测系统。这个项目最初是为了一个智能小车或辅助驾驶的Demo而开发的核心目标很简单让程序能像人眼一样实时识别出画面中的红绿灯并准确判断其当前状态红灯、绿灯、黄灯。听起来像是计算机视觉的入门级应用但真正动手做起来从环境搭建、数据准备、模型训练到最后的集成部署每一步都藏着不少细节和“坑”。这个打包好的源码模型文件评估指标曲线使用说明.zip可以说是一个完整的项目交付物。它不仅仅是一堆代码更是一个从理论到实践、从模型训练到应用落地的完整闭环。对于想入门目标检测特别是想用YOLOv5解决一个具体、有实用价值的视觉任务的朋友来说这个项目是个非常好的学习样本和起点。今天我就以这个项目为蓝本拆解一下如何从零开始构建并理解这样一个红绿灯识别系统。我们会聊到YOLOv5的训练调优、OpenCV的工程化集成以及如何解读那些评估曲线来真正了解你的模型“学”得怎么样。2. 核心组件拆解YOLOv5与OpenCV如何各司其职要理解这个系统首先得弄清楚YOLOv5和OpenCV在这个项目中分别扮演什么角色。它们俩一个主“识别”一个主“处理”分工明确协同工作。2.1 YOLOv5负责“是什么”和“在哪里”YOLOv5You Only Look Once version 5是这个系统的“大脑”承担着目标检测的核心任务。它的工作流程可以简单理解为特征提取输入一张图片通过其内部的卷积神经网络CNN骨干网络如CSPDarknet提取出图片的多层次特征。预测生成在提取的特征图上模型会在预设的众多锚框Anchor Boxes基础上预测每个框内包含物体的概率置信度、物体的类别红、绿、黄灯以及框的精确位置中心点坐标和宽高。后处理通过非极大值抑制NMS等算法剔除掉重叠的、低置信度的冗余预测框最终输出我们看到的那些画在图片上的检测框和标签。在这个红绿灯识别项目中YOLOv5模型需要被训练来识别三类目标red_lightgreen_lightyellow_light。这意味着你的数据集里每一张包含红绿灯的图片都需要用标注工具如LabelImg精确地框出红绿灯的位置并打上正确的类别标签。模型通过学习成千上万张这样的标注图片最终学会在陌生的图片或视频流中找到并分类红绿灯。注意红绿灯识别有一个特殊性即“状态”识别。我们并不是识别“红绿灯”这个物体本身而是识别其发光部分的状态。因此在标注和模型理解上它更像是一个细粒度的分类问题。有时为了更鲁棒可能会将红灯、绿灯、黄灯视为同一个大类“traffic_light”下的不同状态但在YOLO中直接作为三个独立类别处理是更常见的做法。2.2 OpenCV负责“怎么看”和“怎么用”OpenCVOpen Source Computer Vision Library则是系统的“眼睛”和“手”。它主要负责前后端的图像处理与系统集成图像预处理与后处理读取与解码从摄像头、视频文件或图片流中读取图像数据。尺寸变换将原始图像缩放至YOLOv5模型要求的输入尺寸如640x640。颜色空间转换例如从BGROpenCV默认转换为RGBYOLOv5常用或进行灰度化、直方图均衡化cv2.equalizeHist等操作以增强特定场景下的图像质量。网络热词中提到的opencv equalizehist就是用于提升图像对比度的一种方法在光照不均时可能有用。结果可视化利用cv2.rectanglecv2.putText等函数将YOLOv5预测出的边界框和类别标签绘制到原始图像上给人直观的反馈。推理流程集成在Python中OpenCV的dnn模块虽然可以直接加载ONNX格式的YOLO模型进行推理但更常见的做法是使用YOLOv5官方提供的torch.hub或自定义加载方式获得模型然后用OpenCV来处理输入和输出。两者结合紧密。性能与部署OpenCV在C/Python端的接口成熟且部分函数经过高度优化能有效处理视频流的实时读取和显示是构建实时检测系统前端的理想选择。简而言之YOLOv5是内核的检测算法模型OpenCV是使这个模型能够对接真实世界图像流并展示结果的工程框架。一个提供智能一个提供接口和能力。3. 环境搭建与依赖部署避开初学者的第一个坑拿到源码包后第一步就是搭建能让它跑起来的环境。这一步看似简单却劝退了无数新手。我们结合热词中高频出现的yolov5安装步骤、opencv安装、ModuleNotFoundError等问题梳理一个稳健的搭建流程。3.1 Python与PyTorch环境配置YOLOv5基于PyTorch因此一个独立的Python虚拟环境是管理依赖的最佳实践。# 1. 创建并激活虚拟环境以conda为例venv同理 conda create -n traffic_light_det python3.8 # 推荐3.8兼容性好 conda activate traffic_light_det # 2. 安装PyTorch核心版本必须匹配 # 前往PyTorch官网https://pytorch.org/get-started/locally/根据你的CUDA版本选择命令。 # 例如对于CUDA 11.3的用户 pip install torch1.12.1cu113 torchvision0.13.1cu113 torchaudio0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113 # 如果没有GPU或CUDA则安装CPU版本 # pip install torch torchvision torchaudio关键点PyTorch版本与CUDA版本如有的严格对应是避免后续各种诡异错误的基石。很多ImportError或运行时错误都源于此。3.2 安装YOLOv5与OpenCV在虚拟环境中安装项目所需的包。通常源码包内会有一个requirements.txt文件。# 3. 进入项目根目录 cd path/to/your/project # 4. 安装YOLOv5相关依赖如果项目自带requirements.txt pip install -r requirements.txt # 典型的requirements.txt会包含matplotlib, numpy, opencv-python, Pillow, PyYAML, scipy, tqdm, tensorboard, pandas, seaborn等。 # 5. 如果项目没有requirements.txt或需要单独安装 # 安装YOLOv5通常通过克隆官方仓库或pip安装 # 方式一推荐便于查看源码克隆官方repo git clone https://github.com/ultralytics/yolov5.git # 将项目源码中的自定义文件如data配置文件、utils修改合并到克隆的仓库中。 # 方式二直接pip安装作为库使用 pip install yolov5 # 注意这安装的是ultralytics发布的封装版本接口可能略有不同。 # 6. 安装OpenCV pip install opencv-python4.5.5.64 # 指定一个稳定版本避免兼容性问题 # 如果需要更多功能如contrib模块可以安装 opencv-contrib-python常见坑点ModuleNotFoundError: No module named opencv这个错误通常是因为包名不对。正确的安装包名是opencv-python导入时使用import cv2。确保你安装的是opencv-python而不是opencv。版本冲突requirements.txt中的版本可能过时或与你的环境冲突。如果安装失败可以尝试先安装核心包torch, torchvision, opencv-python, numpy再逐个安装其他依赖或适当放宽版本限制如将改为。权限问题在Linux或Mac上如果使用系统Python可能需要sudo但更推荐在虚拟环境中操作。3.3 验证安装与模型文件准备安装完成后进行快速验证。# test_import.py import torch import cv2 print(fPyTorch version: {torch.__version__}) print(fCUDA available: {torch.cuda.is_available()}) print(fOpenCV version: {cv2.__version__}) # 尝试导入YOLOv5相关模块根据你的项目结构 # 例如如果你的代码中使用了 models 和 utils try: from models.common import DetectMultiBackend from utils.general import check_img_size, non_max_suppression print(YOLOv5 modules imported successfully.) except ImportError as e: print(fImport error: {e})接下来处理模型文件。你的zip包中应该包含训练好的权重文件通常是.ptPyTorch格式。将其放在项目指定的目录下例如./weights/。在代码中你会看到类似这样的加载语句model torch.hub.load(ultralytics/yolov5, custom, pathweights/best.pt, force_reloadTrue) # 或者使用 DetectMultiBackend # model DetectMultiBackend(weights/best.pt, devicedevice)确保路径正确并且权重文件与代码期望的模型结构YOLOv5s, YOLOv5m等匹配。4. 数据准备与模型训练打造系统的“火眼金睛”如果你的项目包中只包含了训练好的模型和推理代码但你想了解这个模型是如何诞生的或者想用自己的数据微调那么理解训练过程至关重要。热词中yolov5训练自己的数据集是很多人的需求。4.1 红绿灯数据集构建与标注公开的红绿灯数据集相对较少质量参差不齐。构建自己的数据集通常涉及数据收集从网上公开数据集如BDD100K、TT100K、行车记录仪视频、仿真环境如CARLA或实地拍摄中获取图片。需要覆盖多种场景白天/夜晚、晴天/雨天、近景/远景、不同国家的灯型。数据标注使用工具LabelImg、CVAT、Roboflow进行标注。标注格式需为YOLO格式每个图片对应一个.txt文件每行内容为class_id x_center y_center width_height坐标均为归一化值。关键细节框要紧贴发光区域而不是整个灯壳。对于箭头灯通常按颜色分类如green_left,red_straight这取决于你的需求粒度。数据集划分按比例如8:1:1划分为训练集train、验证集val和测试集test。目录结构通常如下dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ └── labels/ ├── train/ ├── val/ └── test/4.2 YOLOv5模型训练与超参数调优YOLOv5提供了非常便捷的训练脚本。你需要准备一个数据配置文件.yaml和一个模型配置文件.yaml。数据配置文件(data/traffic_light.yaml)path: ../dataset # 数据集根目录 train: images/train val: images/val test: images/test nc: 3 # 类别数红、绿、黄 names: [red_light, green_light, yellow_light]启动训练python train.py --img 640 --batch 16 --epochs 100 --data data/traffic_light.yaml --cfg models/yolov5s.yaml --weights yolov5s.pt --name traffic_light_exp--img 640: 输入图像尺寸。越大精度可能越高但消耗显存越多速度越慢。--batch 16: 批次大小。根据GPU显存调整。--epochs 100: 训练轮数。需要根据损失曲线早停避免过拟合。--weights yolov5s.pt: 加载预训练权重从YOLOv5官方下载这是提升收敛速度和最终性能的关键即迁移学习。--name traffic_light_exp: 实验名称所有输出权重、日志、图表会保存在runs/train/traffic_light_exp下。超参数调优热词中提到了yolov5超参数。除了命令行参数更精细的超参数在data/hyps/hyp.scratch-low.yaml等文件中。你可以调整学习率lr0、动量momentum、权重衰减weight_decay、数据增强参数如hsv_h,hsv_s,hsv_v用于色域增强这对红绿灯识别很重要等。对于红绿灯识别可以适当增强色彩抖动和模糊以模拟不同天气和运动模糊。训练过程监控训练开始后你可以使用TensorBoard来实时监控各项指标tensorboard --logdir runs/train在浏览器中打开localhost:6006你可以看到损失曲线、精度、召回率、mAP等指标的变化这是调整超参数、判断模型是否收敛的重要依据。5. 评估指标深度解读你的模型真的“靠谱”吗训练完成后项目包中提供的“评估指标曲线”不是摆设它们是衡量模型性能的“体检报告”。学会看这些图你才能客观评价模型的好坏而不是仅凭几张测试图片的感觉。5.1 核心评估指标Precision, Recall, mAP在runs/train/exp目录下的results.png和相关文本文件中你会看到以下关键指标精确率Precision模型预测为正的样本中真正为正的比例。高Precision意味着模型“不乱报”它说那是红绿灯就很有可能是。召回率Recall所有真实的正样本中被模型正确预测出来的比例。高Recall意味着模型“不漏报”路上的红绿灯基本都能被找到。平均精度mAP这是目标检测中最核心的综合指标。它计算的是在不同置信度阈值下Precision-Recall曲线下的面积AP然后对所有类别取平均。mAP0.5指的是IoU交并比阈值为0.5时的mAPmAP0.5:0.95则表示在IoU阈值从0.5到0.95步长0.05区间内的平均mAP更为严格。对于红绿灯识别高Precision至关重要误将其他红色/绿色物体如尾灯、广告牌识别为红绿灯在驾驶场景中可能导致灾难性后果。因此我们通常愿意牺牲一点Recall也要保证极高的Precision。关注各类别AP不仅要看整体的mAP还要看red_lightgreen_lightyellow_light各自的AP。黄灯样本通常较少其AP可能偏低需要特别关注。5.2 关键曲线图解析损失曲线Loss Curves包含train/box_loss,train/obj_loss,train/cls_loss以及对应的验证集损失。理想情况是训练损失和验证损失都平稳下降并最终收敛。如果验证损失在后期上升而训练损失持续下降则是典型的过拟合需要增加数据增强、使用早停Early Stopping或减少模型复杂度。性能指标曲线results.png通常包含Precision、Recall、mAP0.5、mAP0.5:0.5随训练轮次Epoch变化的曲线。这些曲线应随着训练逐渐上升并趋于平稳。观察它们可以帮助你确定最佳的模型检查点不一定在最后一个Epoch。混淆矩阵Confusion Matrix在验证集上评估后生成。它展示了模型在各个类别间的混淆情况。理想情况下对角线正确分类的值应该最高。你可以通过它发现模型容易将哪两类混淆例如是否在某些光照下把红灯误认为黄灯。PR曲线Precision-Recall Curve每个类别都有一条曲线。曲线越靠近右上角高Precision高Recall说明该类别性能越好。曲线下的面积就是AP。通过PR曲线你可以根据应用需求选择合适的置信度阈值。如果需要高Precision就把阈值调高但Recall会相应降低。实操心得不要只盯着最高的mAP数值。将模型在极端测试集如夜间、强光逆光、雨雪天、小目标密集上的表现与这些曲线结合分析。有时一个mAP稍低但PR曲线更“胖”在高压区域仍有较高Recall的模型在实际应用中可能更鲁棒。6. 系统集成与工程化实战让模型“跑”起来训练出好模型只是第一步将其集成到一个稳定、可用的系统中才是工程价值的体现。你的源码包应该已经包含了这部分核心代码我们来解析其关键环节。6.1 推理流程代码剖析一个典型的红绿灯检测推理脚本detect.py或inference.py会包含以下步骤import cv2 import torch import numpy as np from models.common import DetectMultiBackend from utils.general import non_max_suppression, scale_boxes from utils.augmentations import letterbox class TrafficLightDetector: def __init__(self, weights_path, devicecuda:0, img_size640): self.device torch.device(device if torch.cuda.is_available() else cpu) # 加载模型 self.model DetectMultiBackend(weights_path, deviceself.device) self.stride, self.names, self.pt self.model.stride, self.model.names, self.model.pt self.img_size img_size print(fLoaded model from {weights_path} on {self.device}) def preprocess(self, img0): 将原始BGR图像预处理为模型输入张量 # 使用letterbox进行自适应缩放保持长宽比 img letterbox(img0, self.img_size, strideself.stride, autoself.pt)[0] # 转换颜色通道 BGR - RGB并调整维度 HWC - CHW img img.transpose((2, 0, 1))[::-1] # BGR to RGB, HWC to CHW img np.ascontiguousarray(img) img torch.from_numpy(img).to(self.device) img img.float() # uint8 to fp16/32 img / 255.0 # 归一化 0 - 255 to 0.0 - 1.0 if img.ndimension() 3: img img.unsqueeze(0) # 增加批次维度 return img, img0 def detect(self, img0): 执行检测 img, orig_img self.preprocess(img0) # 前向推理 pred self.model(img, augmentFalse, visualizeFalse) # NMS后处理 pred non_max_suppression(pred, conf_thres0.25, iou_thres0.45, classesNone, agnosticFalse, max_det1000) detections [] for i, det in enumerate(pred): # 每张图片的检测结果 if len(det): # 将检测框坐标缩放回原始图像尺寸 det[:, :4] scale_boxes(img.shape[2:], det[:, :4], orig_img.shape).round() for *xyxy, conf, cls in reversed(det): label f{self.names[int(cls)]} {conf:.2f} detections.append({ bbox: [int(x) for x in xyxy], label: self.names[int(cls)], confidence: float(conf) }) return detections def draw_detections(self, img0, detections): 在图像上绘制检测结果 for det in detections: x1, y1, x2, y2 det[bbox] label det[label] conf det[confidence] # 根据标签选择颜色 color {red_light: (0, 0, 255), green_light: (0, 255, 0), yellow_light: (0, 255, 255)}.get(label, (255, 255, 255)) cv2.rectangle(img0, (x1, y1), (x2, y2), color, 2) cv2.putText(img0, f{label} {conf:.2f}, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2) return img0 # 使用示例 if __name__ __main__: detector TrafficLightDetector(weights/best.pt) cap cv2.VideoCapture(test_video.mp4) # 或 0 表示摄像头 while cap.isOpened(): ret, frame cap.read() if not ret: break dets detector.detect(frame) frame_with_box detector.draw_detections(frame.copy(), dets) cv2.imshow(Traffic Light Detection, frame_with_box) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()6.2 工程优化与注意事项性能优化硬件加速确保PyTorch使用了GPUtorch.cuda.is_available()为True。对于边缘设备如热词中的RK3568、RV1106需要将模型转换为ONNX、TensorRT或特定平台的格式如RKNN并进行量化、剪枝等优化。推理批处理如果处理图片流可以累积多帧进行一次批处理推理能显著提升GPU利用率。OpenCV优化cv2.VideoCapture读取视频时可以考虑跳帧frame skipping或在子线程中读取避免I/O阻塞主线程。逻辑后处理状态过滤红绿灯有状态机。例如从红灯直接跳转到绿灯是可能的但从绿灯直接跳转到红灯不经黄灯在某些交通规则下不合理。可以加入简单的时序逻辑过滤掉不可能的瞬时跳变。区域兴趣ROI在固定场景如前置摄像头视角可以预设一个图像上部的ROI只在该区域进行检测减少计算量避免误检。置信度阈值调整根据评估阶段的PR曲线在实际应用中调整conf_thres。为了安全红绿灯检测的置信度阈值可以设得高一些如0.6以上以追求更高的Precision。鲁棒性增强多帧投票对连续视频帧的检测结果进行投票或加权平均可以稳定输出避免单帧误检或抖动。异常处理增加对图像读取失败、模型加载失败、推理异常等的处理逻辑保证系统长时间运行的稳定性。7. 常见问题排查与进阶思考即使有了完整的代码和模型在实际运行中也可能遇到各种问题。结合热词中的高频错误这里总结几个典型场景。7.1 环境与依赖问题ImportError: No module named cv2或ModuleNotFoundError: No module named opencv原因OpenCV未安装或安装的包名不正确。解决确认安装命令是pip install opencv-python并且安装在当前使用的Python环境中。在IDE中运行时注意切换正确的解释器。CUDA out of memory原因GPU显存不足。解决减小推理时的--img-size或批次大小--batch-size。在训练时可以尝试使用更小的模型如yolov5s而非yolov5l或使用梯度累积来模拟更大的批次。模型加载失败或推理结果异常原因权重文件损坏、模型结构不匹配、预处理/后处理代码与模型版本不兼容。解决确保使用的权重文件是配套的。YOLOv5不同版本v6.0 v6.1 v7.0的代码和模型可能有细微差别。尽量使用项目原配的代码和权重。可以先用一张简单图片测试看是否有任何输出。7.2 模型性能问题检测不到小目标红绿灯分析红绿灯在远处时可能只占几个像素属于小目标检测难题。对策数据层面在数据集中增加更多包含小尺寸红绿灯的图片。模型层面使用更密集的检测头如YOLOv5的P5模型本身就比P3更适合小目标或者尝试专门优化小目标的模型结构。减小下采样倍数如将--img-size从640增大到1280但会大幅增加计算量。训练层面使用更小的锚框Anchor聚类修改模型配置文件中的anchors参数使其更匹配你数据集中红绿灯的宽高比。误检率高将其他物体识别为红绿灯分析数据集中负样本不含红绿灯的图片不足或正样本的多样性不够。对策增加负样本在训练集中加入大量不含任何红绿灯的道路场景图片并确保其标签文件为空。数据增强加强色彩、亮度和模糊方面的增强让模型更关注形状和语义而非单纯的颜色。后处理提高置信度阈值conf_thres。黄灯识别效果差分析黄灯数据量通常远少于红灯和绿灯导致模型对黄灯特征学习不充分。对策数据重采样对黄灯样本进行过采样复制、增强。损失函数加权在分类损失中给黄灯类别更高的权重。二阶段处理先检测“交通灯”大类再对检测区域进行高分辨率的颜色分类来判断状态。7.3 部署与落地思考这个项目作为一个Demo为我们打开了视觉感知的一扇门。但要将其转化为一个产品级系统还需要考虑更多多传感器融合单纯依靠视觉在极端天气大雾、暴雨或强光下会失效。考虑与高精地图提供红绿灯位置先验或车联网V2X信号进行融合。嵌入式部署参考热词中的rv1106搭建yolov5模型、yolov5在rk3568上将模型部署到算力有限的嵌入式设备是更大的挑战。需要涉及模型量化INT8、剪枝、编译优化TVM, TensorRT等一系列技术。系统安全与合规如同热词中提到的“AI智能体安全合规自动化检测系统”任何应用于实际驾驶辅助或自动驾驶的感知模块都必须经过严格的功能安全如ISO 26262和预期功能安全SOTIF验证确保其失效模式可控。回过头看这个红绿灯识别项目它麻雀虽小五脏俱全。从数据准备、模型训练、评估优化到工程集成它完整地走完了一个目标检测应用的生命周期。通过亲手实践并深入理解其中的每一个环节你获得的不仅仅是运行一个Demo的成就感更是解决一类实际计算机视觉问题的系统性能力。本文还有配套的精品资源点击获取