智慧交通系列(一)-十字路口车辆闯红灯检测告警抓拍系统(附含数据+源码+模型)

智慧交通系列-车辆闯红灯检测告警抓拍系统

基于深度定制的智能交通行业应用。
在保留原项目目标检测 / 姿态估计 / 图像分割三大 AI 能力的基础上,新增了车辆闯红灯检测、告警、抓拍留证等业务功能。

GUI运行界面

未闯红灯截图

在这里插入图片描述

闯红灯截图

在这里插入图片描述


目录


1. 项目简介

本项目以智慧交通行业中的"车辆闯红灯自动检测"为业务主线,将 YOLO 系列目标检测与
多目标跟踪(ByteTrack / DeepSort)作为底层能力,配套 Qt 图形界面,可对接:

  • 本地图片 / 视频文件
  • USB 摄像头 / 内置摄像头(设备编号)
  • RTSP 网络视频流

系统运行时一边对画面中的车辆与交通信号灯做实时检测 / 跟踪,一边在用户预先框定的
“闯红灯区域” 内做业务判定,命中即触发告警(屏幕角标 + 事件日志 + 抓拍图片留证)。

适用场景:智能交通路口卡口、校园 / 单位出入口违规检测演示、AI 教学示例项目。


2. 主要功能

2.1 AI 基础能力

任务模型后端说明
目标检测YOLOv8 / YOLO11 / YOLO26(ultralytics .pt默认任务
姿态估计YOLO11-Pose .pt关键点 + 骨架可视化
图像分割YOLO11-Seg .pt像素级 mask 可视化

2.2 目标跟踪

  • ByteTrack:纯几何、速度快,参数已按 30FPS 场景调好。
  • DeepSort:带外观特征,遮挡恢复更稳,但推理更慢。
  • 关闭跟踪:不做时序关联,每帧独立(“0-person” 这种伪 ID 会被强制置为 -1)。

2.3 输入源

  • 本地图片:jpg / png / bmp / tif / gif / webp / heif
  • 本地视频:mp4 / avi / mov / flv / mkv / webm
  • 摄像头:本地 USB 摄像头(输入设备编号)
  • 网络流:RTSP / HTTP 视频流地址

2.4 业务能力(项目定制部分)

  • 闯红灯区域绘制:在画面上交互式画出任意多边形(最少 3 个、最多 8 个顶点),作为闯红灯判定区域。
  • 闯红灯自动判定
    • 帧内出现 red_light 类目标;
    • 帧内出现 car 类目标,且其边框中心点位于用户绘制的多边形内。
    • 满足上述两条件 → 触发告警。
  • 告警留证
    • 实时画面:闯红灯车辆边框变红 + 标签加 [违章] 前缀 + 左上角"车辆闯红灯(累计 N 辆)"半透明告警条;
    • 事件面板:实时写入事件日志(时间、类型、区域、置信度、ID、抓拍缩略图),支持点击缩略图在系统看图工具中打开;
    • 本地抓拍:原图 + 红色粗框 + 标签 + 时间戳,整帧保存到 snapshots/red_light/
  • 抓拍去重:开启跟踪时按 track_id 去重,关闭跟踪时(id=-1)按 IoU 与最近记录去重,避免重复抓拍同一辆车。

2.5 系统能力

  • GPU / CPU 自动切换;GPU 模式下默认启用 FP16 与 cuDNN benchmark。
  • 多线程流水线(采集 / 推理 / 可视化分离),互不阻塞。
  • 暂停 / 继续推理;视频可调帧间隔。
  • 事件 CSV 导出。

3. 技术栈

类别组件
GUIPyQt5(5.15.x)
深度学习PyTorch 2.0.1 + ultralytics 8.x
视觉OpenCV(opencv-python-headless)
跟踪ByteTrack、DeepSort(含 CNN 特征提取 ckpt.t7)
数值NumPy、SciPy
字体Pillow(用于中文渲染)
Python3.9 / 3.10

注意:项目默认走 ultralytics .pt 后端,相比 ONNX 部署更简单且功能一致;如需 ONNX,仓库内仍保留 yolo_detector_onnx.py 等文件可切换。


4. 目录结构

f:\project_code_all\ITS-Red-Light Detection\
├── main.py                       # 程序入口(MainWindow、信号连线、图标)
├── environment.yml               # Conda 环境定义
├── requirements.txt              # pip 依赖列表
├── 说明文档.md                   # 本文档
│
├── data/                         # 演示用素材(图片 / 视频 / UI 截图)
├── resources/                    # 自定义图标(app.ico/app.png/app.jpg)
├── snapshots/                    # 抓拍图保存目录
│   └── red_light/                # 闯红灯抓拍图(按时间戳命名)
│
├── weights/                      # 模型权重
│   ├── detection/                # 目标检测 .pt / .onnx
│   ├── pose/                     # 姿态估计 .pt / .onnx
│   ├── segmentation/             # 分割 .pt / .onnx
│   ├── classes.txt               # 当前使用的类别文件
│   └── classes-ori.txt           # 原始类别(备份)
│
├── src/
│   ├── data_type/                # 跨线程数据缓冲(LatestFrame、FrameBuffer)
│   │
│   ├── models/                   # 模型层
│   │   ├── base/                 # 基类 yolo_base.py
│   │   ├── detection/            # 目标检测(pt / onnx)
│   │   ├── pose/                 # 姿态估计
│   │   ├── segmentation/         # 图像分割
│   │   └── tracking/             # 跟踪器
│   │       ├── byte_track/       # ByteTrack(含 kalman / matching / gmc)
│   │       └── deep_sort/        # DeepSort(含 sort + deep CNN)
│   │
│   ├── qt/                       # Qt 业务层
│   │   ├── stream/               # 摄像头/AI 流
│   │   │   ├── video_capture.py  # 摄像头/视频流抓取线程
│   │   │   ├── ai_worker.py      # AI 推理 + 跟踪 + 闯红灯业务
│   │   │   ├── visualize.py      # 结果绘制线程
│   │   │   └── redlight_violation.py  # ★ 闯红灯业务核心
│   │   └── video/                # 文件处理
│   │       └── video_worker.py   # 本地文件处理线程
│   │
│   ├── ui/                       # UI 层
│   │   ├── main_window.py        # 主窗口(来自 .ui)
│   │   ├── main_window.ui        # Qt Designer 工程
│   │   ├── event_panel.py        # ★ 智能分析侧边栏(事件/统计/目标)
│   │   ├── polygon_overlay.py    # ★ 可交互多边形覆盖层
│   │   ├── apprcc.qrc            # Qt 资源文件
│   │   ├── apprcc_rc.py          # 资源 Python 模块
│   │   └── icons/                # 图标
│   │
│   └── utils/                    # 工具
│       ├── general.py            # 类别加载、图像 ID 标记等
│       ├── boxes.py              # box 工具
│       └── visualize.py          # ★ 绘制(框、关键点、告警 banner)
│
└── tests/                        # 单元测试占位

5. 安装与运行

5.1 创建环境(任选其一)

方式 A:Conda(推荐,CPU/GPU 都好用)
conda env create -f environment.yml
conda activate yolo_gui
方式 B:pip
pip install -r requirements.txt

requirements.txt 锁定的是 CUDA 11.7 + cuDNN 8.5 组合;若使用其他 CUDA 版本,请按需调整
torch / torchvision / onnxruntime-gpu 的版本。

5.2 准备模型权重

weights/detection/yolo11n.pt 等文件放到 weights/ 目录下(项目内已附带部分权重)。
如需 ONNX 模型,可使用 yolo export model=yolo11n.pt format=onnx 自行导出。

闯红灯检测要求模型类别中至少包含 carred_light。仓库默认 classes.txt
来自 COCO(无 red_light),因此 weights/classes-bk.txt 留作备份;
weights/classes-ori.txt 则是覆盖了 red_light 类的版本。模型加载时若 classes.txt
行数与 .pt 不一致会自动回退到 .pt 内置类别,请根据实际模型选好对应的 classes.txt

5.3 运行

python main.py

启动后默认界面布局:

┌───────────────────────────────────────────────────────────────────────┐
│              智慧交通系列-车辆闯红灯检测告警抓拍系统                     │
├──────────────┬────────────────────────────────────┬───────────────────┤
│  任务选择    │                                    │   智能分析         │
│  模型选择    │                                    │  ┌─────────────┐  │
│  跟踪器选择  │        实时画面 / 视频画面            │  │ 事件日志     │  │
│  置信度/IoU  │        (含多边形覆盖层)             │  │实时统计      │  │
│  帧间隔      │                                    │  │检测目标      │  │
│  输入源选择  │                                    │  └─────────────┘  │
│  区域绘制    │                                    │                   │
│  推理控制    │                                    │                   │
├──────────────┴────────────────────────────────────┴───────────────────┤
│                         检测结果表(id/class/conf/bbox)                │
└───────────────────────────────────────────────────────────────────────┘

6. 界面说明

6.1 左侧栏

  • 任务(单选):

    • 目标检测(默认)
    • 姿态估计
    • 图像分割

    当模型为 YOLOv13 时,仅支持目标检测,其它两个单选会自动禁用。

  • 模型(下拉):根据任务显示可选模型(yolo11n / yolo11s / …)。

  • 跟踪器(下拉):关闭 / ByteTrack / DeepSort。

  • 置信度 / IoU:双数值框 + 滑块双向绑定,实时同步到推理线程。

  • 帧间隔(仅文件模式生效):每 N+1 帧推理一次,用于跳帧加速。

  • 输入源(高 40px 的两个按钮):

    • 选择文件(图片 / 视频)
    • 打开摄像头(弹窗输入编号或 RTSP 地址)
  • 区域绘制

    • 开始绘制区域 / 结束绘制
    • 重置 / 清除
    • 显示 / 隐藏

6.2 中间画面

  • 上方有渐变蓝色标题栏(QToolBar 风格的浅蓝渐变 + 深蓝粗体字 + 圆角)。
  • 实时画面(摄像头 / 视频)按 QLabel 居中等比缩放绘制。
  • 闯红灯车辆边框为红色加粗 + [违章] 前缀;左上角红色半透明告警条显示累计违法车辆数。
  • 顶部覆盖的 PolygonOverlay 在"开始绘制区域"时进入编辑态,可左键加点 / 拖拽顶点 / 右键删除(最少 3 个顶点)。

6.3 右侧"智能分析"侧边栏(EventPanel

  • 事件日志:表格 5 列(时间 / 类型 / 区域 / 详情 / 抓拍缩略图),闯红灯类目自动用红色背景标出。
    缩略图支持点击 → 系统看图工具打开原图。
  • 实时统计:事件总数 / 当前检测数 / 当前跟踪数 / 实时 FPS。
  • 检测目标:当前帧所有目标的列表(#id class conf)。
  • 底部按钮:清空事件导出 CSV(UTF-8 BOM,Excel 直接可读)。

7. 核心架构

整体架构采用 Qt 的"信号-槽 + QThread"模式,把数据采集、AI 推理、结果渲染分离到不同
线程,避免单帧推理阻塞 UI。

              ┌────────────────────┐
              │   MainWindow (UI)  │
              └─────────┬──────────┘
                        │ signal/slot
   ┌────────────────────┼────────────────────┐
   ▼                    ▼                    ▼
CameraCaptureThread  AiWorkerThread   VideoVisualizationThread
   (抓帧)              (推理+跟踪)        (绘制+展示)
                        │                    ▲
                        │ violation_event     │ violation_hint
                        ▼                    │
              RedLightViolationDetector ─────┘
                        │
                        ▼
                snapshots/red_light/  ←  抓拍图落盘

(文件模式:用 FileProcessThread 合并 抓帧+推理+绘制,单线程内流水线)
  • 摄像头模式:CameraCaptureThread → AiWorkerThread → VideoVisualizationThread 三个 QThread 串行。
  • 文件模式:单 FileProcessThread 内部循环读帧 + 推理 + 绘制,开销更小。
  • 闯红灯检测器 RedLightViolationDetector 只有一个实例,由 main.py 创建后分别注入两个 worker。

8. 闯红灯检测业务详解

8.1 触发条件(每帧)

# src/qt/stream/redlight_violation.py
if (has_red_light                       # 帧中存在 red_light 类目标
    and 帧中存在 car
    and car.bbox 中心点在用户多边形内):    # 重心点 cv2.pointPolygonTest >= 0
    trigger_violation()

8.2 多边形

  • PolygonOverlay 维护,存的是归一化坐标 (0~1),因此与画面分辨率无关;
  • 窗口 resize / 多边形变化时,MainWindow._on_polygon_changed 会把新坐标同步给检测器;
  • 顶点最少 3 个,最多 8 个;少于 3 个视为无效,不触发检测。

8.3 去重

跟踪器去重策略
关闭跟踪(id=-1)用当前 bbox 与最近 max_recent=50 条记录做 IoU 比对,IoU > 0.5 视为同一辆
ByteTrack / DeepSorttrack_idviolated_track_ids 集合里查重

8.4 抓拍图

violation_id<trackid>_<时间戳>.jpg 命名,存到 snapshots/red_light/

  • 整帧(包含原 YOLO 框、告警 banner 之外 的画面,因为抓拍发生在 draw 之前)
  • 红色粗框覆盖到该车辆
  • 框顶部 RED LIGHT VIOLATION ID=3 (98.5%) 标签
  • 左上角时间戳

注:抓拍使用的是 frame(原始 BGR 帧),不包含运行时叠在画面上的 banner / 多边形。

8.5 事件推送

  • ai_worker.send_violation_event(list)MainWindow._on_violation_eventsEventPanel.add_violation_event
  • ai_worker.send_violation_hint(dict)VideoVisualizationThread.get_violation_hintdraw_results 时读出 violation_track_idsalert_message

8.6 类名约定

业务类对应 COCO 类名说明
carcar(COCO id=2)触发主体
red_light取决于模型;自定义训练时常作为新增类触发前提

若你的模型 red_light 类名不同,请修改 MainWindow.__init__ 中的:

self.violation_detector = RedLightViolationDetector(
    snapshot_dir=_snap_dir,
    car_class="car",
    red_light_class="red_light",   # ← 改成你的模型中对应类名
)

9. 多线程模型

9.1 摄像头模式

线程职责关键信号
CameraCaptureThreadcv2.VideoCapture 拉流,emit [frame_id, frame]send_frame
AiWorkerThreadYOLO 推理 + 跟踪 + 闯红灯业务send_ai_outputsend_violation_eventsend_violation_hint
VideoVisualizationThread等比缩放、绘制、emit QImagesend_displayable_framesend_ai_output

三线程通过 Qt 的 pyqtSignal 解耦,UI 线程只在最后一步 update_display_frame 设置 QLabel,
所以即使推理较慢也不会卡 UI。

9.2 文件模式

FileProcessThread 单线程内做:

  1. 读帧(OpenCV)
  2. 推理 + 跟踪
  3. 闯红灯业务
  4. 绘制(draw_results
  5. convert_cv_qt(预分配画布,避免每帧 4.6MB 内存分配)
  6. emit 给 UI
  • 暂停 / 继续使用 QMutex + QWaitCondition,不丢帧不撕裂。
  • 图片任务一次性推理完会重新自动暂停,等待下一次操作。
  • 视频任务结束保留最后一帧,不再清空画面为黑屏。

9.3 跨线程安全

  • 多边形更新走 threading.Lock
  • 检测器状态对象不暴露原始 list 给外部修改,外部只通过 update_polygon / clear / detect 交互;
  • 跟踪 ID 等值在 emit 前会被 copy.deepcopy,避免主线程渲染时被工作线程改写。

10. 模型与权重

10.1 类别文件

  • weights/classes.txt:当前默认使用(行数必须与 .pt 模型类别数一致,否则会自动回退 .pt 内置)。
  • weights/classes-ori.txt:原始(包含 red_light 类)备份。
  • weights/classes-bk.txt:更早版本。

模型加载逻辑见 src/models/detection/yolo_detector_pt.py_resolve_class_names
若训练了包含 red_light 类的专用模型,请将对应的类别文件改名为 classes.txt(或调整代码逻辑)。

10.2 已附带的权重

路径说明
weights/detection/yolo11n.ptYOLO11 nano,COCO 80 类
weights/detection/yolo11s.ptYOLO11 small
weights/pose/yolo11n-pose.onnxYOLO11 姿态(ONNX)
weights/segmentation/yolo11s-seg.onnxYOLO11 分割(ONNX)

业务场景下,建议使用专门训练了 red_light 类的交通场景模型,否则系统不会自动识别红灯。

10.3 性能开关

  • GPU 自动 FP16yolo11n 等支持 fp16 的模型在 CUDA 环境下自动启用 half=True
  • Conv+BN 融合:模型加载完成后自动调用 model.fuse()
  • cuDNN benchmark:连续等尺寸输入下会自动选最优卷积算法。
  • 画布复用FileProcessThread.convert_cv_qt 复用预分配 NumPy 数组 + 零拷贝 QImage 构造。

11. 关键文件清单

文件作用
main.py程序入口;UI 装配、信号绑定、状态机
src/qt/stream/redlight_violation.py闯红灯业务核心:判定 + 去重 + 抓拍
src/qt/stream/ai_worker.py摄像头模式下的 AI worker(推理+跟踪+闯红灯)
src/qt/stream/video_capture.py摄像头/视频流抓帧线程
src/qt/stream/visualize.py摄像头模式下的绘制线程
src/qt/video/video_worker.py文件模式下的单线程流水线
src/ui/main_window.py主窗口
src/ui/event_panel.py智能分析侧边栏(事件/统计/目标)
src/ui/polygon_overlay.py可交互多边形覆盖层(闯红灯区域绘制)
src/utils/visualize.py通用绘制(框、关键点、违章改色、告警 banner)
src/models/detection/yolo_detector_pt.py目标检测 ultralytics .pt 后端
requirements.txtpip 依赖
environment.ymlConda 环境

12. 常见问题

Q1:启动后画面没有目标识别?
确认 classes.txt 行数与所选 .pt 模型类别数一致。yolo_detector_pt.py 加载时若不一致会自动回退 .pt 内置类别并打印警告。

Q2:闯红灯检测不触发?

  • 没有画多边形 → 至少 3 个顶点。
  • 模型没有 red_light 类 → 换用包含红绿灯的专用模型。
  • 区域设置好但没出现红灯 → 检查模型是否能识别 red_light 类。
  • 控制台打印 [RED_LIGHT] 闯红灯检测器已就绪, 抓拍目录: ... 表示检测器已注入。

Q3:摄像头 / RTSP 拉不到?
Windows 下某些 USB 摄像头独占,需先关闭其它使用摄像头的程序;
RTSP 地址需包含用户名密码时建议用 rtsp://user:pass@host:port/...

Q4:抓拍图很大?
默认保存的是 cv2.imwrite 默认质量 (~95)。如需压缩可改 redlight_violation.pycv.imwrite 第三参数。

Q5:多边形顶点超出画面?
PolygonOverlay 已做边界裁剪,鼠标位置会被 clamp[0, w/h]

Q6:能否拓展其它业务(如违停、压线、车道偏离)?
可以。仿照 RedLightViolationDetector 新建一个业务类,
ai_worker.run / video_worker.run 中按相同模式调用并 emit 新的事件信号,
EventPanel 增加对应的事件类型即可。EventPanel.add_event 已经是通用接口。

Q7:抓拍目录想换位置?
修改 main.py 中:

_snap_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                         "snapshots", "red_light")

附录 A:信号一览

信号发射线程接收端用途
send_frameCameraCapturedisplay/ai单帧 BGR 数据
send_ai_outputai_worker / display / file_workerMainWindow当前帧检测结果(list of dict)
send_violation_eventai_worker / file_workerMainWindow → EventPanel新发生的闯红灯事件(含抓拍路径)
send_violation_hintai_workerVideoVisualizationThread每帧推送违章 ID + 累计告警文案
send_displayable_frameVideoVisualizationThreadMainWindow已绘制的 QImage
send_display_frameFileProcessThreadMainWindow同上(文件模式)
send_play_progressFileProcessThreadMainWindow视频播放进度(千分制)
send_thread_start_stop_flagdisplay_threadMainWindow状态机切换
send_thread_start_finish_flagfile_workerMainWindow状态机切换
polygon_changedPolygonOverlayMainWindow多边形顶点变化(归一化坐标)

附录 B:检测结果数据结构

{
    "id":          int,    # 跟踪 ID(关闭跟踪时为 -1)
    "class":       str,    # 类别名("car" / "red_light" / "person" ...)
    "confidence":  float,  # 0~1
    "bbox":        [x1, y1, x2, y2],   # 像素坐标
    "keypoints":   np.ndarray,         # 姿态任务才有
    "segmentation": np.ndarray,        # 分割任务才有
}

业务层(闯红灯检测、事件面板、多边形区域绘制)为本项目新增实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

onnx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值