大家好,我是南木。最近后台收到很多零基础读者的留言:“想入门交通AI,但觉得要学复杂的深度学习和计算机视觉,门槛太高?”“路口闯红灯检测看起来很高级,普通人能自己做出来吗?”“学了YOLO和OpenCV的基础,却不知道怎么结合起来做实际项目?”

其实交通AI入门没那么难,闯红灯检测系统就是零基础最友好的实战项目——它的核心逻辑清晰(“识别车辆+判断红灯+检测越线”三步),技术栈成熟(YOLOv8做目标检测+OpenCV做图像处理),而且不用专业硬件(普通电脑+USB摄像头就能跑通)。

这篇文章以“城市路口闯红灯检测”为目标,从“工具准备→数据集搭建→模型训练→核心逻辑实现→实时检测部署”全流程拆解,每个步骤都附“零基础可复制的代码+图文操作指南+避坑说明”。不用懂复杂理论,跟着敲代码、调参数,2周就能做出能实时检测闯红灯的系统。

正文开始之前 这里给大家整理了一份适合零基础入门的学习资料包 同学需要系统课程学习的同学 可扫下方二维码交流
在这里插入图片描述
在这里插入图片描述

一、先搞懂:闯红灯检测的核心逻辑,其实很简单

很多人觉得闯红灯检测“高大上”,其实它的本质是“用AI和图像处理技术模拟交警的判断逻辑”——交警在路口判断“是否闯红灯”,看的是“红灯时有没有车辆越过停止线”,AI系统也是一样,核心就3步:识别车辆→判断红绿灯状态→检测车辆是否越线

1. 闯红灯检测的“3步核心逻辑”(普通人也能看懂)

用一张图就能说清闯红灯检测的完整流程,零基础也能秒懂:

  1. 第一步:识别车辆(YOLOv8负责)
    从路口视频中“抓出”所有车辆(轿车、货车、摩托车等),定位它们的位置(用检测框标记)。
  2. 第二步:判断红绿灯状态(OpenCV+YOLOv8结合)
    聚焦路口红绿灯区域,判断当前是否为“红灯”(可通过两种方式实现:OpenCV颜色识别适合简单场景,YOLOv8检测适合复杂路口)。
  3. 第三步:检测车辆是否越线(OpenCV负责)
    预先在视频中标记“停止线”位置,判断红灯状态下,是否有车辆的前轮/车身越过停止线——满足“红灯+车辆越线”,即判定为“闯红灯”。

简单说:红灯亮时,车辆过线=闯红灯,这就是系统的核心判断依据。

2. 为什么选YOLOv8+OpenCV?零基础友好度拉满

闯红灯检测的技术组合有很多,但YOLOv8+OpenCV是零基础的最优选择,原因有3个:

  • YOLOv8:目标检测“天花板”,开箱即用
    不用手动写神经网络,一行代码就能调用模型检测车辆、红绿灯,对零基础极其友好。而且速度快(普通CPU能跑15FPS,GPU能跑100FPS)、精度高(车辆检测准确率≥95%),完全满足实时检测需求。
  • OpenCV:图像处理“瑞士军刀”,功能全且简单
    处理视频帧、标记停止线、识别红绿灯颜色、绘制检测结果……这些闯红灯检测必需的功能,OpenCV都有现成的API,几行代码就能实现,不用自己造轮子。
  • 两者结合:互补性强,开发效率高
    YOLOv8负责“识别目标”(车辆、红绿灯),OpenCV负责“图像预处理+逻辑判断”(调亮度、画停止线、算越线),分工明确,零基础能快速上手组合开发。

3. 实战目标与环境说明(普通人能落地)

不用专业设备,普通电脑就能完成所有开发,具体目标和环境如下:

  • 实战目标:开发一个“路口闯红灯检测系统”,能处理视频文件和USB摄像头实时流,输出“是否闯红灯”的判断结果,并在画面上标记车辆、红绿灯、停止线和检测结果。
  • 硬件要求:普通电脑(CPU即可,有GPU更好,训练速度能快10倍)、USB摄像头(可选,用于实时检测)。
  • 软件环境:Python 3.9(兼容性最好)、YOLOv8(目标检测)、OpenCV 4.8(图像处理)、LabelImg(数据标注)。

二、Day1:基础准备——3小时搞定工具与核心概念

今天的目标是:搭建开发环境、理解核心数据格式、掌握YOLOv8和OpenCV的基础用法,为后续实战打基础。

1. 第一步:10分钟搭建开发环境(避坑版)

零基础最容易踩“版本冲突”的坑,这里给出经过验证的版本组合,复制命令就能安装成功:

步骤1:安装Python环境(推荐Anaconda,管理环境更方便)
  1. 下载Anaconda:Anaconda官网,选择“Python 3.9”版本(别选最新版,避免兼容性问题);
  2. 安装Anaconda:双击安装包,一路默认下一步,最后勾选“Add Anaconda to my PATH environment variable”(方便命令行调用);
  3. 打开“Anaconda Prompt”(Windows)或“终端”(Mac/Linux),创建并激活专属环境:
    # 创建名为traffic-ai的环境,Python 3.9
    conda create -n traffic-ai python=3.9
    # 激活环境(每次开发前都要执行)
    conda activate traffic-ai
    
步骤2:安装核心库(YOLOv8+OpenCV+标注工具)

在激活的“traffic-ai”环境中,输入以下命令安装核心库,国内用户建议用清华镜像源(速度快10倍):

# 安装YOLOv8官方库(固定版本,避免更新出问题)
pip install ultralytics==8.0.200 -i https://pypi.tuna.tsinghua.edu.cn/simple

# 安装OpenCV(图像处理核心)
pip install opencv-python==4.8.0.74 -i https://pypi.tuna.tsinghua.edu.cn/simple

# 安装数据标注工具(LabelImg,用于标注车辆和红绿灯)
pip install labelImg==1.8.6 -i https://pypi.tuna.tsinghua.edu.cn/simple

# 安装其他辅助库(可视化、数据处理)
pip install matplotlib==3.7.1 pandas==1.5.3 -i https://pypi.tuna.tsinghua.edu.cn/simple
步骤3:验证环境是否安装成功

运行以下代码,若能正常输出YOLOv8和OpenCV的版本信息,说明环境没问题:

# 验证YOLOv8
from ultralytics import YOLO
print("YOLOv8版本:", YOLO.__version__)

# 验证OpenCV
import cv2
print("OpenCV版本:", cv2.__version__)

# 测试YOLOv8基础检测
model = YOLO("yolov8n.pt")  # 加载YOLOv8-nano模型(最小、最快)
results = model("https://ultralytics.com/images/bus.jpg")  # 检测示例图片
print("YOLOv8检测成功,检测到目标数:", len(results[0].boxes))

2. 第二步:30分钟理解核心概念(避免后续 confusion)

零基础开发的最大障碍是“概念不清”,这里提前讲清3个核心概念,后续代码一看就懂:

概念1:YOLOv8的目标检测格式(标注和训练必懂)

YOLOv8检测目标时,输出的结果包含“类别、置信度、检测框坐标”,格式如下:

  • 类别(cls):目标的类型,如“car”(车辆)、“traffic light”(红绿灯);
  • 置信度(conf):模型对检测结果的信任程度(0~1),值越高越可靠,通常设≥0.3才认为有效;
  • 检测框坐标(xyxy):目标在图片中的位置,格式为“左上x、左上y、右下x、右下y”(单位:像素)。

例如:检测到一辆车,输出可能是“cls=2(car)、conf=0.92、xyxy=[100, 200, 300, 400]”,表示“在图片的(100,200)到(300,400)位置,有一辆车,置信度92%”。

概念2:OpenCV的视频帧处理(实时检测基础)

视频是“连续的图片序列”,OpenCV处理视频的核心是“逐帧读取→处理→显示”:

  • 读取视频:用cv2.VideoCapture()打开视频文件或摄像头;
  • 逐帧处理:用cap.read()循环读取每一帧图片(称为“frame”);
  • 显示结果:用cv2.imshow()显示处理后的帧;
  • 保存视频:用cv2.VideoWriter()保存检测后的视频。

简单说,实时检测就是“每秒处理30帧图片,每帧都判断是否有闯红灯行为”。

概念3:闯红灯的“越线判断”逻辑(核心业务规则)

判断车辆是否越线,本质是“判断车辆检测框与停止线是否有重叠”,简化逻辑如下:

  1. 标记停止线:在图片中用两个点定义停止线(如line_start=(100, 500)line_end=(800, 500),表示一条横向的停止线);
  2. 获取车辆底部坐标:车辆检测框的“右下y”坐标(接近地面的位置);
  3. 判断越线:若车辆的“右下y”>停止线的“y坐标”(即车辆底部超过停止线),且当前是红灯,则判定为“闯红灯”。

3. 第三步:1小时掌握YOLOv8+OpenCV基础操作

学会“用YOLOv8检测目标”和“用OpenCV处理图片/视频”,就能完成实战的基础操作:

基础操作1:用YOLOv8检测单张图片(车辆识别示例)
from ultralytics import YOLO
import cv2

# 1. 加载YOLOv8-nano模型(预训练模型,已能检测80类目标,含car、traffic light)
model = YOLO("yolov8n.pt")

# 2. 检测单张图片(替换为你的图片路径)
img_path = "test_car.jpg"
results = model(img_path, conf=0.3)  # conf=0.3:只保留置信度≥30%的结果

# 3. 提取检测结果(只保留“车辆”类别,YOLOv8中car的cls=2)
car_results = [box for box in results[0].boxes if int(box.cls) == 2]

# 4. 在图片上绘制检测框
img = cv2.imread(img_path)
for box in car_results:
    # 获取检测框坐标(转换为整数)
    x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
    # 绘制红色检测框(厚度2)
    cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
    # 绘制置信度标签
    conf = round(box.conf[0].item(), 2)
    cv2.putText(img, f"Car {conf}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)

# 5. 保存并显示结果
cv2.imwrite("car_detection_result.jpg", img)
cv2.imshow("Car Detection", img)
cv2.waitKey(0)  # 按任意键关闭窗口
cv2.destroyAllWindows()

print(f"检测完成,共发现{len(car_results)}辆汽车,结果已保存为car_detection_result.jpg")
基础操作2:用OpenCV读取视频并标记停止线
import cv2

# 1. 打开视频文件(替换为你的视频路径,0表示USB摄像头)
cap = cv2.VideoCapture("test_video.mp4")

# 2. 定义停止线位置(根据视频画面调整,这里是示例坐标)
line_start = (150, 450)  # 停止线起点(x, y)
line_end = (750, 450)    # 停止线终点(x, y)

# 3. 循环读取视频帧
while cap.isOpened():
    # 读取一帧
    ret, frame = cap.read()
    if not ret:
        break  # 视频读取完毕,退出循环
    
    # 4. 在帧上绘制停止线(蓝色,厚度3)
    cv2.line(frame, line_start, line_end, (255, 0, 0), 3)
    # 绘制停止线标签
    cv2.putText(frame, "Stop Line", (line_start[0]+10, line_start[1]-10), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 2)
    
    # 5. 显示帧
    cv2.imshow("Video with Stop Line", frame)
    
    # 按q键退出
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 6. 释放资源
cap.release()
cv2.destroyAllWindows()

三、Day2:实战开发——闯红灯检测系统核心模块实现

今天是实战核心,分“数据集准备→模型训练→核心逻辑实现”三部分,搭建起系统的“骨架”。

1. 第一步:2小时准备数据集(标注车辆和红绿灯)

YOLOv8的预训练模型能检测“车辆”,但对“红绿灯状态”(红/黄/绿)的识别不够精准,需要自己标注数据集训练专门的模型。

步骤1:采集数据(零基础方案)

不用自己拍路口视频,直接用公开数据集或从网上下载路口视频,截取帧作为图片数据:

  • 数据量:100张图片足够(50张含红灯,30张含绿灯,20张含黄灯);
  • 数据要求:图片分辨率统一为640×640(训练快),包含不同角度、不同光线的红绿灯(如晴天、阴天、夜间)。
步骤2:标注数据(用LabelImg,点鼠标就行)

LabelImg是零基础友好的标注工具,全程不用写代码,步骤如下:

  1. 启动LabelImg:在“traffic-ai”环境中输入命令labelImg,打开工具;
  2. 配置标注
    • 点击“Open Dir”,选择图片文件夹;
    • 点击“Change Save Dir”,选择标注文件保存文件夹;
    • 点击“View”,勾选“Auto Save mode”(自动保存);
  3. 定义类别:点击左侧“Create RectBox”(或按W),框选红绿灯区域,输入类别名称(必须英文):
    • red_light(红灯)
    • green_light(绿灯)
    • yellow_light(黄灯)
  4. 标注规则
    • 框选红绿灯的发光区域(只框红灯/绿灯/黄灯部分,不要框整个灯壳);
    • 每张图片只标注当前亮的灯(如红灯亮就标red_light,不标其他灯)。
步骤3:整理数据集(YOLOv8格式)

按YOLOv8要求整理数据集文件夹结构(必须严格遵守,否则模型找不到数据):

traffic_light_dataset/  # 数据集根目录
├─ train/               # 训练集(80张图)
│  ├─ images/           # 训练图片
│  └─ labels/           # 训练标注文件(.txt格式)
└─ val/                 # 验证集(20张图)
   ├─ images/           # 验证图片
   └─ labels/           # 验证标注文件(.txt格式)

将标注好的80张图和对应的.txt文件放入train文件夹,20张放入val文件夹。

步骤4:创建配置文件(告诉YOLOv8“学什么”)

创建traffic_light_data.yaml文件(用记事本即可),定义数据集路径和类别,内容如下(替换为你的数据集绝对路径):

# 训练集和验证集路径(必须是绝对路径,如C:/Users/Admin/traffic_light_dataset/train/images)
train: C:/Users/Admin/traffic_light_dataset/train/images
val: C:/Users/Admin/traffic_light_dataset/val/images

# 类别数和类别名称
nc: 3
names: ["red_light", "green_light", "yellow_light"]  # 顺序对应类别ID 0、1、2

2. 第二步:1小时训练红绿灯检测模型(YOLOv8实战)

用标注好的数据集训练专门的红绿灯状态识别模型,代码简单到只有几行:

from ultralytics import YOLO
import torch

# 1. 检查GPU是否可用(有GPU训练快10倍,无GPU也能跑,只是慢一点)
print(f"GPU可用:{torch.cuda.is_available()}")
device = 0 if torch.cuda.is_available() else "cpu"

# 2. 加载YOLOv8-nano模型(从头训练红绿灯检测)
model = YOLO("yolov8n.pt")

# 3. 训练模型
train_results = model.train(
    data="traffic_light_data.yaml",  # 配置文件路径
    epochs=50,                      # 训练轮次(50轮足够收敛)
    batch=8,                        # 批次大小(6G显存设8,4G设4,2G设2)
    imgsz=640,                      # 输入图片尺寸
    device=device,                  # 训练设备
    name="traffic_light_model",     # 模型名称(保存到runs/detect/traffic_light_model)
    pretrained=True,                # 用预训练权重加速训练
    optimizer="Adam",               # 优化器(适合小数据集)
    lr0=0.001,                      # 初始学习率
    val=True                        # 训练时同步验证
)

# 4. 输出训练结果
print("\n训练完成!关键指标:")
print(f"验证集mAP50:{train_results.results_dict['metrics/mAP50']:.4f}")  # 准确率指标,≥0.85为合格
print(f"最佳模型路径:runs/detect/traffic_light_model/weights/best.pt")
训练结果解读(零基础也能看懂)

训练时会打印每轮的损失和准确率,重点看mAP50(平均精度):

  • 若mAP50≥0.85:模型合格,能准确识别红绿灯状态;
  • 若mAP50<0.85:增加训练轮次(如改epochs=80),或补充标注更多图片(尤其是识别不准的场景)。
测试模型效果(验证是否能正确识别红绿灯)
from ultralytics import YOLO
import cv2

# 1. 加载训练好的最佳模型
model = YOLO("runs/detect/traffic_light_model/weights/best.pt")

# 2. 测试单张红绿灯图片(替换为你的测试图路径)
test_img_path = "test_red_light.jpg"
results = model(test_img_path, conf=0.5)  # 置信度设0.5,减少误检

# 3. 绘制检测结果
img = cv2.imread(test_img_path)
for box in results[0].boxes:
    x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
    cls_id = int(box.cls[0])
    conf = round(box.conf[0].item(), 2)
    # 定义颜色:红=红灯,绿=绿灯,黄=黄灯
    color = (0,0,255) if cls_id==0 else (0,255,0) if cls_id==1 else (0,255,255)
    # 绘制检测框和标签
    cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)
    label = f"{model.names[cls_id]} {conf}"
    cv2.putText(img, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)

# 4. 保存并显示结果
cv2.imwrite("traffic_light_test_result.jpg", img)
cv2.imshow("Traffic Light Detection", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
print("红绿灯检测测试完成,结果已保存!")

3. 第三步:2小时实现闯红灯检测核心逻辑(YOLOv8+OpenCV结合)

将“车辆检测”“红绿灯识别”“越线判断”结合,实现完整的闯红灯检测逻辑,这是系统的核心代码:

核心代码:闯红灯检测系统(支持视频文件)
from ultralytics import YOLO
import cv2
import numpy as np

class RedLightDetectionSystem:
    def __init__(self, car_model_path="yolov8n.pt", light_model_path="runs/detect/traffic_light_model/weights/best.pt"):
        """
        初始化闯红灯检测系统
        car_model_path:车辆检测模型路径(用YOLOv8预训练模型即可)
        light_model_path:红绿灯检测模型路径(自己训练的)
        """
        # 加载模型
        self.car_model = YOLO(car_model_path)
        self.light_model = YOLO(light_model_path)
        
        # 定义停止线位置(根据你的视频画面调整!这是示例坐标)
        self.stop_line_start = (180, 480)  # 停止线起点
        self.stop_line_end = (720, 480)    # 停止线终点
        self.stop_line_y = 480             # 停止线的y坐标(用于越线判断)
        
        # 定义颜色
        self.RED = (0, 0, 255)       # 红色:闯红灯、红灯
        self.GREEN = (0, 255, 0)     # 绿色:绿灯、正常
        self.BLUE = (255, 0, 0)      # 蓝色:停止线
        self.YELLOW = (0, 255, 255)   # 黄色:黄灯
    
    def get_traffic_light_state(self, frame):
        """
        判断红绿灯状态
        return:0=红灯,1=绿灯,2=黄灯,-1=未检测到
        """
        results = self.light_model(frame, conf=0.5)
        if len(results[0].boxes) == 0:
            return -1  # 未检测到红绿灯
        # 取置信度最高的红绿灯结果
        best_box = max(results[0].boxes, key=lambda x: x.conf)
        return int(best_box.cls[0])
    
    def detect_cars(self, frame):
        """
        检测车辆,只返回车辆的检测框坐标
        return:车辆检测框列表(每个元素为[x1, y1, x2, y2])
        """
        results = self.car_model(frame, conf=0.3)
        # 只保留“车辆”类别(YOLOv8预训练模型中car的cls=2)
        car_boxes = []
        for box in results[0].boxes:
            if int(box.cls) == 2:
                x1, y1, x2, y2 = map(int, box.xyxy[0].tolist())
                car_boxes.append([x1, y1, x2, y2])
        return car_boxes
    
    def is_car_over_line(self, car_box):
        """
        判断车辆是否越过停止线
        car_box:车辆检测框[x1, y1, x2, y2]
        return:True=越线,False=未越线
        """
        car_bottom_y = car_box[3]  # 车辆底部y坐标(右下y)
        # 若车辆底部y > 停止线y,判定为越线
        return car_bottom_y > self.stop_line_y
    
    def process_frame(self, frame):
        """
        处理单帧画面,返回带检测结果的帧和闯红灯判断
        """
        # 1. 复制原帧(避免修改原图)
        frame_with_result = frame.copy()
        
        # 2. 绘制停止线
        cv2.line(frame_with_result, self.stop_line_start, self.stop_line_end, self.BLUE, 3)
        cv2.putText(frame_with_result, "Stop Line", (self.stop_line_start[0]+10, self.stop_line_start[1]-10),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.8, self.BLUE, 2)
        
        # 3. 判断红绿灯状态
        light_state = self.get_traffic_light_state(frame)
        light_text = ""
        light_color = self.BLUE
        if light_state == 0:
            light_text = "Red Light"
            light_color = self.RED
        elif light_state == 1:
            light_text = "Green Light"
            light_color = self.GREEN
        elif light_state == 2:
            light_text = "Yellow Light"
            light_color = self.YELLOW
        else:
            light_text = "No Light Detected"
        # 绘制红绿灯状态
        cv2.putText(frame_with_result, f"Light: {light_text}", (20, 40),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, light_color, 2)
        
        # 4. 检测车辆
        car_boxes = self.detect_cars(frame)
        red_light_violation = False  # 是否闯红灯
        
        # 5. 判断每辆车是否闯红灯
        for car_box in car_boxes:
            x1, y1, x2, y2 = car_box
            # 判断是否越线
            over_line = self.is_car_over_line(car_box)
            # 闯红灯条件:红灯 + 车辆越线
            if light_state == 0 and over_line:
                red_light_violation = True
                # 绘制红色检测框(表示闯红灯)
                cv2.rectangle(frame_with_result, (x1, y1), (x2, y2), self.RED, 3)
                cv2.putText(frame_with_result, "RED LIGHT VIOLATION!", (x1, y1-10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.7, self.RED, 2)
            else:
                # 绘制绿色检测框(正常)
                cv2.rectangle(frame_with_result, (x1, y1), (x2, y2), self.GREEN, 2)
                cv2.putText(frame_with_result, "Car", (x1, y1-10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.6, self.GREEN, 2)
        
        # 6. 绘制闯红灯警告
        if red_light_violation:
            cv2.putText(frame_with_result, "WARNING: RED LIGHT VIOLATION!", (20, 80),
                        cv2.FONT_HERSHEY_SIMPLEX, 1, self.RED, 3)
            # 播放报警声(Windows系统,Mac/Linux需修改)
            import winsound
            winsound.Beep(1000, 500)  # 1000Hz,持续500ms
        
        return frame_with_result, red_light_violation
    
    def process_video(self, input_video_path, output_video_path="output_video.mp4"):
        """
        处理视频文件,保存检测结果
        """
        # 打开输入视频
        cap = cv2.VideoCapture(input_video_path)
        if not cap.isOpened():
            print("无法打开输入视频!")
            return
        
        # 获取视频参数(帧率、分辨率)
        fps = int(cap.get(cv2.CAP_PROP_FPS))
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        
        # 创建视频写入器(保存输出视频)
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        out = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
        
        print(f"开始处理视频,输出路径:{output_video_path}")
        frame_count = 0
        
        # 循环处理每一帧
        while cap.isOpened():
            ret, frame = cap.read()
            if not ret:
                break
            
            # 处理帧
            frame_with_result, _ = self.process_frame(frame)
            
            # 写入输出视频
            out.write(frame_with_result)
            
            # 显示处理结果
            cv2.imshow("Red Light Detection", frame_with_result)
            
            # 按q键退出
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
            
            frame_count += 1
            if frame_count % 100 == 0:
                print(f"已处理 {frame_count} 帧")
        
        # 释放资源
        cap.release()
        out.release()
        cv2.destroyAllWindows()
        print(f"视频处理完成!输出文件:{output_video_path}")

# 测试系统:处理视频文件
if __name__ == "__main__":
    # 初始化系统
    system = RedLightDetectionSystem()
    # 处理视频(替换为你的测试视频路径)
    system.process_video(input_video_path="test_intersection_video.mp4", output_video_path="red_light_detection_output.mp4")

四、Day3:优化与部署——让系统更实用(零基础可落地)

今天的目标是:优化系统性能(解决速度慢、误检率高的问题),并部署为“实时检测工具”,支持USB摄像头实时检测。

1. 第一步:1小时优化系统性能(解决3个常见问题)

零基础开发的系统可能存在“检测慢、误检多、红绿灯识别不准”的问题,3个优化技巧就能解决:

优化1:提升检测速度(让系统更流畅)
  • 用轻量化模型:将yolov8n.pt(nano)换成yolov8s.pt(small)会提升精度,但速度会下降;若追求速度,坚持用nano模型,足够满足基础需求;
  • 降低输入分辨率:在model.train()model()调用时,将imgsz从640改为480,检测速度能提升30%(精度损失很小);
  • 减少不必要的检测:红绿灯通常在画面的固定区域(如上方),可只对“红绿灯区域”进行检测,减少计算量,代码如下:
    # 只检测画面上方1/3区域的红绿灯(示例)
    def get_traffic_light_state(self, frame):
        h, w = frame.shape[:2]
        # 截取画面上方1/3区域(红绿灯通常在这里)
        light_roi = frame[0:h//3, 0:w]
        results = self.light_model(light_roi, conf=0.5)
        # 后续逻辑不变...
    
优化2:降低误检率(减少“假阳性”)
  • 提高置信度阈值:车辆检测的conf从0.3提到0.4,红绿灯检测的conf从0.5提到0.6,过滤低置信度的误检结果;
  • 多帧验证:闯红灯判断不依赖“单帧”,而是“连续3帧都满足红灯+越线”才判定为违规,避免因单帧模糊导致的误判,代码如下:
    # 在RedLightDetectionSystem中添加多帧验证逻辑
    def __init__(self):
        # 新增:多帧验证计数器
        self.violation_frame_count = 0
        self.violation_threshold = 3  # 连续3帧才判定为违规
    
    def process_frame(self, frame):
        # ... 原有逻辑 ...
        # 闯红灯判断改为多帧验证
        if light_state == 0 and over_line:
            self.violation_frame_count += 1
            if self.violation_frame_count >= self.violation_threshold:
                red_light_violation = True
                self.violation_frame_count = 0  # 重置计数器
        else:
            self.violation_frame_count = 0  # 不满足条件,重置计数器
        # ... 原有逻辑 ...
    
优化3:提升红绿灯识别鲁棒性(适应复杂光线)
  • 图像预处理:用OpenCV增强画面的对比度和亮度,让红绿灯在阴天、夜间更清晰,代码如下:
    def preprocess_frame(self, frame):
        """图像预处理,增强红绿灯识别效果"""
        # 转灰度图
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 自适应直方图均衡化,增强对比度
        clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
        enhanced = clahe.apply(gray)
        # 转回BGR格式
        return cv2.cvtColor(enhanced, cv2.COLOR_GRAY2BGR)
    
    # 在get_traffic_light_state中调用预处理
    def get_traffic_light_state(self, frame):
        frame_preprocessed = self.preprocess_frame(frame)
        results = self.light_model(frame_preprocessed, conf=0.5)
        # ... 后续逻辑不变 ...
    

2. 第二步:1小时部署实时检测(USB摄像头实战)

修改系统代码,支持USB摄像头实时检测,实现“对着路口就能实时判断闯红灯”:

# 在RedLightDetectionSystem类中添加实时检测方法
def realtime_detection(self, camera_index=0):
    """
    实时检测(USB摄像头)
    camera_index:摄像头索引,0表示默认摄像头,1表示外接摄像头
    """
    # 打开摄像头
    cap = cv2.VideoCapture(camera_index)
    # 设置摄像头分辨率(根据摄像头性能调整)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
    
    if not cap.isOpened():
        print("无法打开摄像头!")
        return
    
    print("开始实时检测,按q键退出...")
    
    # 循环读取摄像头帧
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        
        # 水平翻转帧(镜像效果,操作更直观)
        frame = cv2.flip(frame, 1)
        
        # 处理帧
        frame_with_result, _ = self.process_frame(frame)
        
        # 显示结果
        cv2.imshow("Realtime Red Light Detection", frame_with_result)
        
        # 按q键退出
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    
    # 释放资源
    cap.release()
    cv2.destroyAllWindows()
    print("实时检测结束!")

# 测试实时检测
if __name__ == "__main__":
    system = RedLightDetectionSystem()
    # 启动实时检测(摄像头索引0)
    system.realtime_detection(camera_index=0)
实时检测使用指南(零基础也会用)
  1. 连接USB摄像头到电脑;
  2. 运行代码,摄像头会自动启动;
  3. 将摄像头对准路口(确保能看到红绿灯和停止线);
  4. 当红灯亮时,若有车辆越过停止线,系统会显示“RED LIGHT VIOLATION!”并发出报警声;
  5. 按“q”键关闭系统。

3. 第三步:1小时打包成exe文件(不用装Python也能运行)

用PyInstaller将代码打包成exe文件,发给没有Python环境的人也能直接运行:

步骤1:安装PyInstaller
pip install pyinstaller==5.13.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
步骤2:创建打包脚本(run_detection.py

将系统代码整理成一个可执行的脚本文件,确保所有依赖都包含在内。

步骤3:执行打包命令

在“Anaconda Prompt”中进入脚本所在文件夹,输入以下命令:

pyinstaller -F -w -i traffic_icon.ico --add-data "runs;runs" run_detection.py
  • -F:打包成单个exe文件;
  • -w:隐藏命令行窗口(更友好);
  • -i traffic_icon.ico:设置系统图标(可选,文末资源包有);
  • --add-data "runs;runs":打包训练好的红绿灯模型(必须包含,否则exe无法运行)。
步骤4:运行exe文件

打包完成后,exe文件在dist文件夹中,双击即可运行,不用安装任何依赖。

五、避坑指南:零基础开发的6个致命错误(必看)

零基础开发时容易踩坑,导致系统无法运行或效果差,这6个错误一定要避开:

1. 避坑1:环境版本不匹配,代码跑不起来

  • 坑点:安装最新版的YOLOv8和OpenCV,导致API不兼容(如YOLOv8的model.train()参数变化);
  • 解决:严格按照本文给出的版本安装(YOLOv8=8.0.200、OpenCV=4.8.0.74),不要随意更新版本。

2. 避坑2:停止线坐标设置错误,越线判断失效

  • 坑点:凭感觉设置停止线坐标(如stop_line_y=100),导致车辆明明没过线却判定为越线;
  • 解决:先用OpenCV打开视频帧,找到停止线的实际y坐标:
    # 查看停止线坐标的工具代码
    import cv2
    cap = cv2.VideoCapture("test_video.mp4")
    ret, frame = cap.read()
    # 显示帧,点击鼠标获取坐标
    def get_mouse_pos(event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            print(f"鼠标点击坐标:x={x}, y={y}")
    cv2.namedWindow("Get Stop Line Coords")
    cv2.setMouseCallback("Get Stop Line Coords", get_mouse_pos)
    while True:
        cv2.imshow("Get Stop Line Coords", frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    
    运行代码后,点击视频中的停止线,即可获取准确的y坐标。

3. 避坑3:数据集标注不规范,模型识别不准

  • 坑点:标注红绿灯时,把整个灯壳都框进去,导致模型学到的是“灯壳特征”而非“灯光特征”;
  • 解决:只框选红绿灯的“发光区域”(如红灯亮时,只框红色的灯珠部分),标注完成后随机抽查20%的图片,确保标注准确。

4. 避坑4:训练轮次不足,模型未收敛

  • 坑点:只训练10轮就停止,mAP50只有0.6,红绿灯识别准确率低;
  • 解决:至少训练50轮,当验证集的mAP50连续10轮不再提升时,再停止训练(YOLOv8会自动早停)。

5. 避坑5:摄像头分辨率过高,检测速度慢

  • 坑点:将摄像头分辨率设为1920×1080,CPU上检测速度只有5FPS,画面卡顿;
  • 解决:实时检测时将分辨率设为1280×720或更低(如640×480),平衡速度和清晰度。

6. 避坑6:未做图像预处理,复杂光线识别失效

  • 坑点:在阴天或夜间检测时,红绿灯识别准确率暴跌,甚至检测不到;
  • 解决:必须添加“自适应直方图均衡化”等预处理步骤,增强画面对比度,让红绿灯更明显。

六、学习路径:零基础2周掌握交通AI(闯红灯检测方向)

为了让零基础用户有清晰的学习节奏,整理了2周学习计划,按这个来,2周就能独立开发系统:

天数 学习内容 目标成果 耗时
Day1 环境搭建(Anaconda+YOLOv8+OpenCV) 成功运行YOLOv8和OpenCV基础代码 3小时
Day2 YOLOv8目标检测基础+OpenCV图像处理 能用YOLOv8检测车辆,用OpenCV处理图片/视频 3小时
Day3 数据集采集与标注(LabelImg) 标注100张红绿灯图片,整理成YOLO格式 2小时
Day4 训练红绿灯检测模型 训练出mAP50≥0.85的红绿灯识别模型 1小时
Day5 实现车辆检测与红绿灯识别模块 单独运行两个模块,能正确识别车辆和红绿灯 2小时
Day6 实现越线判断逻辑 能判断车辆是否越过预设的停止线 1小时
Day7 整合核心模块,实现视频文件检测 处理视频文件,输出闯红灯检测结果 2小时
Day8 优化系统性能(速度+精度) 解决检测慢、误检多的问题 2小时
Day9 部署USB摄像头实时检测 实现实时检测,能对路口进行实时判断 1小时
Day10 打包成exe文件,测试落地 生成可执行文件,零基础用户也能运行 1小时
剩余 实战优化与场景适配 针对不同路口场景调整参数,提升鲁棒性 灵活安排

交通AI的更多实战方向(入门后可拓展)

掌握闯红灯检测后,还可以拓展这些交通AI项目,难度差不多,零基础也能上手:

  • 违章停车检测:用YOLOv8检测车辆,判断是否在禁停区域停留超过规定时间;
  • 车道偏离预警:用OpenCV检测车道线,判断车辆是否偏离本车道;
  • 交通流量统计:用YOLOv8计数通过路口的车辆数量,统计早高峰流量;
  • 行人检测与预警:在斑马线处检测行人,提醒车辆减速避让。

我是南木 提供学习规划、就业指导、技术答疑和系统课程学习 感兴趣的小伙伴欢迎扫码交流
在这里插入图片描述

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐