新闻详情

新闻详情

首页 / 资讯中心 / 详情

基于YOLOv8的非机动车闯红灯识别系统实战解析

发布时间:2026/10/1 1:59:35来源:尧图网络
基于YOLOv8的非机动车闯红灯识别系统实战解析
简介面向计算机相关专业毕设与课程设计的YOLOv8交通路口非机动车闯红灯识别完整包将模型训练、实时检测与可视化界面集于一体可直接部署并用于同类目标检测项目。压缩包共8个文件含3个脚本、3个模型权重文件和2个说明文档整体大小约15.91MB训练脚本负责训练及指标曲线生成检测脚本完成视频识别界面脚本提供操作页面配合说明文档即可快速部署运行。资源附带完整数据集并能输出混淆矩阵、F1分数曲线、精确率-召回率曲线、标签分布图及验证集预测结果适合答辩展示与效果对比。代码经测试通过功能完整既可直接用于非机动车闯红灯识别也适合二次开发作为毕设、课设或项目演示。目前已有57人学习下载对深度学习目标检测方向的学生和开发者具有实用价值。1. 这个项目到底要解决什么非机动车闯红灯识别的实际痛点晚上值班的交警盯着十几个路口的监控画面靠截屏去认定非机动车闯红灯一晚上能挑出几十条就算高产。而路口每天实际发生的闯红灯数是这个数字的好几倍。这个标题里的项目做的就是把这件重复劳动交给YOLOv8用目标检测框出画面里的电动车和自行车再结合红绿灯状态判断它是不是在红灯相位越过停止线。适合毕设或课程设计因为它把训练模型、可视化界面、完整数据集、部署教程都打包了拿到zip后不是从头搭环境而是先跑通再替换成自己的数据。但能跑通不等于能落地我拆开讲一遍从数据到部署把说明书不会写的坑都填上。2. YOLOv8与非机动车闯红灯识别为什么这个组合能落地2.1 任务边界检测“非机动车”和判断“闯红灯”是两件事很多第一次做这个题目的人以为训练一个YOLOv8模型就能直接输出“闯红灯”三个字。实际不是。YOLOv8只能回答“画面上哪里有非机动车”它是一个目标检测器输出的是类别、置信度和边界框。而闯红灯是一个事件判断需要两个输入一是非机动车的位置二是当时的信号灯状态。常见做法是在视频的固定区域画一条虚拟停止线当检测框的底边中心点越过停止线并且信号灯处于红灯相位才判定为闯红灯。所以拿到源码包后先别急着训练先看它的闯红灯判定逻辑在哪一层。如果是用检测结果加信号灯状态写的一个独立函数那说明设计是对的如果只是用检测框数量变化推断红灯那数据一换就废。我一般会把判定逻辑单独写成一个类输入当前帧的检测结果和信号灯状态输出一个报警事件这样后面调阈值和换信号源都方便。这里要特别提醒停止线位置不是随便画在画面中央的得根据摄像头机位来标。正俯拍时停止线就是路口白线在图像里的投影侧向机位时停止线是斜的。很多项目为了省事把停止线画成竖直或水平直线导致车辆在直行车道被误判。我习惯在配置文件里定义四个点组成一个多边形检测框底边中心点落在多边形内才算“越线”这样斜向机位也能兜住。2.2 YOLOv8在精度和部署上的优势选YOLOv8而不是YOLOv5或Faster R-CNN主要看三点。第一是anchor-free设计不用手工调先验框尺寸路口场景里非机动车形态从正侧面到俯拍差别很大anchor-free在形变上更省心。第二是C2f模块在相同参数量下特征融合更充分对体积小、占比小的非机动车比如远处路口中央的电动车检出率更高。第三是生态成熟训练、导出ONNX、转TensorRT的命令都是标准化流程网上“yolov8训练自己的数据集” “处理数据集用于yolov8训练”这类教程一搜一大把遇到报错也好查。如果你用的显卡是GTX1660ti这个档次跑yolov8s在720p视频上能到30到40FPS如果只有CPU建议直接用yolov8n输入尺寸降到416否则没法实时。这也是标题里带部署教程的原因检测模型只是第一步真正花时间的是环境配置和界面集成。在ubuntu20.04上搭建yolov8环境cpu版本时不要盲目装CUDA先查显卡驱动没有N卡就直接用CPU版torch跑起来慢但能验证逻辑。很多人卡在这里一卡就是半天其实按官方文档装CPU版本只要三步。另外说一句权重下载的事。训练时会自动下载预训练权重但国内网络经常失败。常见做法是手动下载yolov8s.pt放到项目根目录再指定--weights yolov8s.pt。下载来源就是官方GitHub release不要信第三方修改过的权重。版本必须和ultralytics库匹配不然会报Unknown model之类的错这个坑在毕设季特别常见。2.3 拿到源码包第一件事先读目录结构和README打开zip后第一件事不是双击运行而是把目录结构树列出来找到关键位置训练脚本、推理脚本、界面文件、权重文件、数据集目录、部署说明。用Linux的命令unzip 基于YOLOv8的交通路口非机动车闯红灯识别.zip -d yolov8_traffic cd yolov8_traffic find . -maxdepth 2 -type f | sortfind比tree通用Windows WSL里也能用。看目录的目的是判断这个项目的运行入口是GUI还是命令行。常见结构是main.py或app.py负责可视化界面detect.py或inference.py负责纯检测weights/下放best.ptdataset/下按YOLO格式组织。先翻一遍README把依赖版本记下来特别是PyQt5、ultralytics、onnxruntime这三类版本不对会连锁报错。很多翻车都发生在这一步直接跑python main.py报ModuleNotFoundError: ultralytics其实requirements.txt就在根目录。我自己的习惯是先在项目里建一个虚拟环境用python -m venv venv再激活最后按requirements安装。不要用全局环境因为同时开好几个毕设项目依赖打架是常事。装依赖时如果卡在pyqt5这种大包上用清华源或阿里源加速几十秒就完事。跑通第一遍后再决定是否换成自己的数据继续训练。注意很多压缩包里的数据集是别人的样本直接用它训练的模型到你实际路口上不一定好使后面会说怎么换数据。3. 训练自己的闯红灯识别模型从数据集到权重3.1 数据集的组成你需要多少张图、涵盖哪些场景完整数据集一般已经标注好但替换成自己路口的数据才是真训练。先说数量如果只用“非机动车”一个类别1000张左右能训练出能用的效果要想在夜间和雨雾天不掉链子至少2000张。建议场景分布白天正常50%、夜间20%、黄昏/逆光15%、雨天/遮挡15%。如果数据集里全是固定机位的那一个路口换一个路口会漏检因为俯拍角度变了。我见过不少人拿COCO数据集里所有带person的图来凑数这不行。交通路口的非机动车是俯拍视角COCO多为平拍两者特征差距很大。正确做法是去实际路口录视频每3到5秒抽一帧挑出包含车辆的写脚本切出图片再手工清洗掉模糊帧。抽帧脚本很容易写import cv2 cap cv2.VideoCapture(cross_road.mp4) fps cap.get(cv2.CAP_PROP_FPS) frame_interval max(1, int(fps * 3)) # 每3秒一帧 idx 0 out_id 0 while True: ret, frame cap.read() if not ret: break if idx % frame_interval 0: cv2.imwrite(fraw_images/{out_id:05d}.jpg, frame) out_id 1 idx 1 cap.release()抽出来的图会有一堆重复背景用指尖上的图片去重工具或写个哈希去重脚本清理留下构图有变化的。数量宁可少而精不要堆大量相似图否则训练集内部高度重复验证集上看着mAP很高现场一换场景就崩。3.2 用LabelImg标注非机动车如果自带数据集不够或者想加自己的样本用LabelImg最省事。安装和启动pip install labelImg labelImg images/ classes.txt在标注工具里打开图片选择YOLO格式输出画框时框住车辆的完整轮廓不要只框车身。对电动车和自行车我建议统一用一个类名non_motor别拆成ebike和bike因为很多图片里两者难以区分类别越多误检越多。也有教程建议用LabelMe但产出是JSON还得转一次yolo格式多一步转换就多一个出错环节还是LabelImg直接出txt最顺。生成的是txt文件每行格式class_id x_center y_center width height坐标是相对值范围0到1。注意检查有没有负坐标或大于1的坐标后面训练会报错。我在标注时习惯把车身完整框进去包括骑行者但不要框到其他人。如果画面里行人非常多而你的目标只有非机动车建议额外加一个person类别哪怕不用于报警也要标出来这样模型能学到“什么是行人什么不是非机动车”误检率会明显下降。3.3 数据集划分与YOLOv8目录组织YOLOv8官方要求用数据yaml文件指向训练、验证图片目录。目录结构dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/所有图片和对应txt必须同名。划分脚本import os, random, shutil random.seed(42) src_images raw_images src_labels raw_labels train_img dataset/images/train val_img dataset/images/val train_lbl dataset/labels/train val_lbl dataset/labels/val names [f[:-4] for f in os.listdir(src_images) if f.endswith(.jpg)] random.shuffle(names) split int(len(names) * 0.8) for name in names[:split]: shutil.copy(f{src_images}/{name}.jpg, f{train_img}/{name}.jpg) shutil.copy(f{src_labels}/{name}.txt, f{train_lbl}/{name}.txt) for name in names[split:]: shutil.copy(f{src_images}/{name}.jpg, f{val_img}/{name}.jpg) shutil.copy(f{src_labels}/{name}.txt, f{val_lbl}/{name}.txt)随机种子固定保证每次划分一致。8:2是保守比例样本少时建议9:1验证集至少50张。注意不要有图片在训练和验证都出现否则mAP虚高。shutil.copy不改文件名但前提是原文件名始终一一对应如果有个jpg没有同名txt脚本会抛错建议加个判断跳过这种坏样本。划分完还要写dataset.yamlpath: dataset train: images/train val: images/val nc: 1 names: [non_motor]path用相对路径时以执行训练命令的当前目录为基准。如果你把dataset.yaml放在项目根目录path: dataset就行。别把train和val写成绝对路径否则换台机器又要改。3.4 训练命令与关键参数进入项目目录先装依赖pip install -r requirements.txt用ultralytics新版训练yolo train datadataset.yaml modelyolov8s.pt epochs100 batch16 imgsz640 device0如果是旧项目里的train.py常见是python train.py --data dataset.yaml --weights yolov8s.pt --epochs 100 --batch 16 --imgsz 640我一般会先跑10个epoch验证数据和模型能正常工作再拉长到100。前面数据没问题的话10个epoch就能看到loss在降。关键参数epochs100起步数据集小的话50就能收敛。batch16在GTX1660ti的6G显存上跑yolov8s没问题显存不足降到8并开启梯度累积。imgsz640是速度和精度平衡点如果摄像头拉得远框很小可以试960但训练时间变长。patience默认10超过10个epoch val loss不降就早停防止过拟合。deviceCPU写cpu但别指望一夜训练完小数据集也要几小时。预训练权重yolov8s.pt会自动从官方地址下载如果下载失败手动下载后放到当前目录。我个人喜欢用yolov8m在中等数据集上做对比但毕设交作业用s就够m训练时间翻倍精度只高1到2个点。如果你电脑是纯CPU老实选n训练时间能少一半而且跑界面时不至于卡成幻灯片。3.5 训练过程监控与loss曲线解读训练结束后看权重目录下的runs/detect/train。用tensorboard看曲线pip install tensorboard tensorboard --logdir runs/detect浏览器打开http://localhost:6006就能看到损失函数曲线图。这个标签也是很常见的长尾词yolov8画损失函数曲线图怎么做其实不用额外写代码训练日志里自动保存了。重点看train/box_loss和val/box_loss。正常情况下两者同步下降如果train loss继续降而val loss反弹就是过拟合提前停止或在data.yaml里加augment。还有一个常见问题loss降到0.02就不再降了但mAP只有0.3这通常不是训练问题而是标注质量差比如框不贴合目标或类别标签标错。建议用yolo val跑一次验证集把预测结果和标签画出来对比yolo predict modelruns/weights/best.pt sourceval_one.jpg save_txtTrue画出来的框如果偏大偏小就去修标注而不是加训练轮数。训练完还会生成confusion_matrix.png如果里面non_motor和background的混淆严重说明负样本不够去补充完全不包含电动车的路口背景图。这个细节很多人忽略但比调学习率有用得多。4. 可视化界面与部署让模型在路口“跑起来”4.1 用PyQt5搭一个带视频预览的检测界面标题里带可视化界面一般就是用PyQt5实现一个窗口左边是视频播放区右边是检测结果列表和报警日志。最小框架示例import sys from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer import cv2 from ultralytics import YOLO class MainWindow(QWidget): def __init__(self): super().__init__() self.label QLabel() layout QVBoxLayout() layout.addWidget(self.label) self.setLayout(layout) self.model YOLO(weights/best.pt) self.cap cv2.VideoCapture(0) self.timer QTimer() self.timer.timeout.connect(self.update_frame) self.timer.start(30) # 约33ms一帧 def update_frame(self): ret, frame self.cap.read() if not ret: return results self.model(frame) annotated results[0].plot() # BGR转RGB并显示 rgb cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape qimg QImage(rgb.data, w, h, ch*w, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qimg)) app QApplication(sys.argv) win MainWindow() win.show() sys.exit(app.exec_())这个例子把推理放在QTimer回调里对30FPS的视频会卡后面改进。注意cv2.VideoCapture(0)读取的是摄像头索引读视频文件改成路径。界面布局别做太花哨毕设答辩时能稳定跑比特效重要。我在界面上放了三个区域视频画布、报警滚动列表、一个“开始/停止”按钮。报警列表用QListWidget每当检测到越线就把时间戳和置信度加进去这个列表就是你的演示数据。4.2 红绿灯状态判定从图像颜色到信号机数据这部分是闯红灯识别的核心。最简单的做法是截取画面中信号灯区域用颜色阈值判断红绿。示例def get_light_state(frame, roi): # roi是信号灯区域比如 [x1, y1, x2, y2] crop frame[roi[1]:roi[3], roi[0]:roi[2]] # 转HSV提取红色阈值 hsv cv2.cvtColor(crop, cv2.COLOR_BGR2HSV) mask_red cv2.inRange(hsv, (0, 100, 100), (10, 255, 255)) \ cv2.inRange(hsv, (160, 100, 100), (180, 255, 255)) mask_green cv2.inRange(hsv, (35, 100, 100), (85, 255, 255)) red_area cv2.countNonZero(mask_red) green_area cv2.countNonZero(mask_green) if red_area 20 and red_area green_area * 2: return red elif green_area 20 and green_area red_area * 2: return green return unknown红色在HSV有两种范围所以要组合。面积阈值20是因为画面中信号灯区域可能很小阈值设大了远处红灯会漏判。更好的做法是接入信号机输出的RS-485数据但毕设一般没有硬件条件用颜色阈值足够。要注意信号灯区域可能因摄像头移动而漂移所以ROI要跟随固定参考物或者直接让摄像头固定机位。实际项目中红绿灯有可能是LED数字倒计时那颜色判断会被数字干扰我遇到的情况是把ROI缩小到信号灯圆形灯盘的中心区域避开数字。4.3 摄像头/视频流接入线程与帧率控制不能把检测放在UI线程里否则界面会卡死。用QThread读帧推理把结果通过信号发给主线程from PyQt5.QtCore import QThread, pyqtSignal import cv2 from ultralytics import YOLO class DetectThread(QThread): result_signal pyqtSignal(dict) def __init__(self, source): super().__init__() self.source source self.model YOLO(weights/best.pt) self.stop False def run(self): cap cv2.VideoCapture(self.source) while not self.stop: ret, frame cap.read() if not ret: break results self.model(frame) frame_annotated results[0].plot() self.result_signal.emit({frame: frame_annotated, boxes: results[0].boxes.data}) cap.release()主线程里连接信号更新QLabel。帧率控制靠QThread里加time.sleep(0.03)或者丢弃积压帧。如果视频流卡顿优先检查是不是摄像头分辨率设太高把cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)和高度720设上。网络摄像头断流后cap.read()会一直返回False要加重连逻辑比如连续10次False就cap.release()再重新打开。我自己的经验是不要用queue.Queue无脑塞帧一旦推理慢队列会积压成千上万frame内存直接涨上去。改成一个只保留最新帧的缓存即可class LatestFrameBuffer: def __init__(self): self.frame None def set(self, frame): self.frame frame def get(self): return self.frame这样处理线程每次拿到的是最新帧旧帧自动被覆盖界面既不延迟内存也稳定。4.4 导出模型与TensorRT加速可选如果部署到GPU服务器或边缘盒子把PyTorch模型导出成ONNX再转TensorRTyolo export modelweights/best.pt formatonnx yolo export modelweights/best.pt formatengine device0导出engine需要本机有TensorRT和CUDA。很多板端部署比如瑞芯微RK3588不支持直接跑engine需要转成RKNN流程是ONNX - RKNN-Toolkit2 - .rknn。这个不建议在毕设里碰除非题目明确要求。更实际的做法是用ONNX Runtime跑CPU版模型对普通PC部署足够。注意导出时固定imgsz后面推理的输入尺寸必须一致否则会报形状错误。在Windows上打包exe时ultralytics的包很大PyInstaller打包出来经常超过500MB。一个降低体积的方法是不打包torch改用onnxruntime但界面代码里的模型加载方式要换成onnxruntime的Session。这个取舍看你的需求如果只是现场演示源码跑就行如果要交给老师一个双击就能开的exe那得提前一星期处理打包依赖别拖到最后一天。5. 避坑非机动车闯红灯识别最常见的5个翻车点5.1 现象行人被识别成非机动车误报率高这个坑几乎每个做交通识别的都会踩到。原因很直接训练数据里把推车行人、背对摄像头的行人标成了非机动车或者非机动车类别缺少行人负样本。解决首先清理标注把行人框剔除然后在数据集中加入person类别即使不报警也要训练让模型学会区分。我在项目里还加了后处理检测框的长宽比和面积不符合非机动车特征的直接丢弃。非机动车框一般长宽比在0.3到1.5车身像素面积占画面0.01以上用这个过滤能压掉一部分误检。boxes results[0].boxes.data.cpu().numpy() filtered [] for box in boxes: x1, y1, x2, y2, conf, cls box w x2 - x1 h y2 - y1 if 0.3 w/h 1.5 and conf 0.35: filtered.append(box)这个后处理是“宁可漏检不要误报”的逻辑。如果你发现正常行驶的车辆也被过滤掉了把长宽比范围放宽到0.2到2.0。另外conf 0.35要根据实际效果调白天可以设0.4夜间设0.2。我见过有人把conf设到0.7来压误报结果画面里的电动车一个都检测不出来那就本末倒置了。5.2 现象绿灯时也报警判断逻辑串了原因信号灯颜色判断和检测结果处理不同步。比如视频是实时流检测线程在t帧取信号灯状态但显示的是上一帧的结果或者信号灯区域被树枝、车体遮挡颜色阈值永远判成红色。解决把信号灯状态封装成带时间戳的对象检测结果也带时间戳比较两者时间差小于0.5秒才可用信号灯连续10帧判定为同一颜色才更新状态避免单帧闪烁。class LightState: def __init__(self): self.state unknown self.frame_cnt 0 def update(self, detected): self.frame_cnt self.frame_cnt 1 if detected self.state else 1 self.state detected if self.frame_cnt 10 else self.state另一个容易忽略的点视频文件本身是录好的没有实时信号灯状态。如果你拿一段历史视频做测试必须手动标注视频里的红灯时间段或者用颜色阈值判断每一帧。而颜色阈值判断在视频压缩后可能偏色红灯变成了橙红色。解决办法是调HSV范围时用视频里真实过曝的几帧做校准不要用网上找的“标准”红绿灯截图。5.3 现象训练时loss不降或直接爆显存loss不降先检查数据集标签格式。常见问题是坐标归一化后出现大于1的值因为标注时用了绝对坐标没转换。写一段脚本遍历labels验证import os for root, dirs, files in os.walk(dataset/labels): for f in files: with open(os.path.join(root, f)) as fp: for line in fp: parts line.split() if len(parts) ! 5: print(f, 字段数不对) else: x, y, w, h map(float, parts[1:]) if x 1 or y 1 or w 1 or h 1 or x 0 or y 0: print(f, 坐标越界)我自己有一次查了一晚上最后发现是LabelImg在YOLO模式下输出的坐标是0-1的相对值但有人把它导成PascalVOC格式的绝对像素坐标再存成txt导致盒子坐标全乱。所以标注前先确认输出格式别中途切换。爆显存解法batch从16降到8imgsz从640降到512或者换yolov8n。如果还爆开启混合精度训练在训练命令里加ampTrue。GTX1660ti只有6G显存别用yolov8l。如果你用的包是旧版train.pyamp可能是个开关参数一定要确认版本。还有一条减少workers值Windows下workers一多就会报DataLoader错误直接设workers0最省心。5.4 现象可视化界面卡死视频掉帧原因推理放在主线程UI每帧都要等推理结束才能刷新。解决用QThread见上一章代码同时控制队列长度如果队列积压超过2帧就直接丢弃最旧帧保证实时。我在界面里插了一个跳帧策略检测耗时超过100ms时显示原视频但报警仍按每帧检测这样界面不卡报警也不漏。具体做法是检测线程只做模型推理把结果帧放到一个最新帧缓存UI的QTimer只从缓存取最新帧显示这样UI刷新频率和检测频率解耦。还有一种卡死是OpenCV的cv2.waitKey(1)和PyQt的app.processEvents()混用。如果你在代码里还留着旧项目里的cv2.imshow它会创建另一个窗口和Qt事件循环打架。排查方法很简单把cv2.waitKey全部注释只保留Qt的Timer。界面卡死时看一眼CPU占用如果主线程100%多半是推理在主线程如果检测线程100%说明模型太大需要换成更小的权重。5.5 现象部署到CPU机器上检测速度只有1-2FPS原因模型是yolov8s以上CPU推理本来就慢。解决换成yolov8n输入尺寸降到416用ONNX Runtime的CPU推理比PyTorch CPU快20%左右检测间隔改每2帧检测一次中间帧用上一帧的框位置前提是场景静止或车辆移动不大。这个方法对闯红灯识别足够因为我们只需要知道车辆是否越线不需要精确到每一帧。在CPU机器上还要注意线程数设置。onnxruntime可以设置intra_op_num_threads默认会吃满所有核但有时候多线程反而慢。我习惯先用4线程测试再对比8线程取最快。PyTorch CPU则有torch.set_num_threads(4)。另外如果模型输入是640在CPU上单帧推理可能200ms降到416后能压到100ms以内。你的界面如果要做实时预览建议把“预览分辨率”和“检测分辨率”分开预览显示1280x720但送进模型之前缩放到416这样画面清晰度不影响检测速度。6. 从“能跑”到“跑得稳”验证方法与进阶技巧6.1 用一段带红绿灯变化的视频做端到端验证准备一段至少2分钟、包含红灯转绿灯再转红的视频。手动记录每个闯红灯事件的时刻跑系统把报警时刻列表对比。我常用一个简单表真实事件数、系统报出数、其中真阳性、误报数算召回和精确率。如果召回低调低conf_thres如果误报多调高。这个验证必须在固定机位下做不要中途拉镜头否则停止线会漂移。6.2 调节conf_thres与iou_thres阈值到底怎么设conf_thres默认0.25如果误报多调到0.4到0.5如果漏检多降到0.1到0.15。iou_thres用于NMS一般保持0.45。给出推荐表场景conf_thresiou_thres备注白天正常0.40.45宁可少报别乱报夜间0.20.45低置信目标多降阈值远距离小目标0.150.5框太小置信低这个表不是玄学是根据实际路灯下多曝光状态的统计经验。调节时每次改0.05跑一段固定视频看结果别一次跳到0.5。我在最终提交的版本里把conf_thres做成了界面上的滑块这样答辩时能现场演示调节效果比硬编码更出彩。6.3 进阶引入ByteTrack做跨帧目标跟踪单帧检测只能判断“有非机动车越过停止线”没法判断“同一辆车是不是持续闯红灯”加上跟踪能锁ID。ByteTrack是目前在YOLOv8社区里用得最多的方案。集成思路是把检测框送入trackertracker输出ID和跟踪框然后只对“穿过停止线且ID首次出现”的目标报警。伪代码from bytetrack import ByteTrack tracker ByteTrack() for frame in video: boxes detector.detect(frame) # 返回xyxy, conf, cls tracks tracker.update(boxes) for t in tracks: tid, x1, y1, x2, y2, conf t if is_cross_stopline(x1, y1, x2, y2) and light_state red: if tid not in reported_ids: report(tid) reported_ids.add(tid)注意跟踪会让报警延迟几帧因为需要积累几个帧的关联。不要对每一个越线帧都报警否则同一个人会被报5次。报警去重用reported_ids集合但集合会无限增长我设了一个上限超过500就清空一次避免内存占用。6.4 把识别结果写成报警日志和统计表毕设答辩时“只显示框”没有说服力要把报警记录导出来。我喜欢用JSONL一行一个事件import json, time def log_event(tid, conf): event { time: time.strftime(%Y-%m-%d %H:%M:%S), track_id: tid, confidence: round(float(conf), 2), cross_stopline: True, light: red } with open(alerts.jsonl, a, encodingutf-8) as f: f.write(json.dumps(event, ensure_asciiFalse) \n)后续可以用pandas读进来统计小时级报警量画个柱状图。我自己的教训是先把统计表做出来再回头调算法因为只看检测框你永远觉得模型很准一看到误报率数字才知道哪里要改。这个习惯帮我省了至少一周返工时间。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

模糊支持向量机Python实战:抗噪分类与参数调优 2026/10/1 5:31:50

模糊支持向量机Python实战:抗噪分类与参数调优

简介:这份资源面向希望将模糊理论引入分类任务的机器学习学习者与开发者,提供模糊支持向量机(FSVM)的完整Python实现。FSVM在传统SVM基础上引入模糊隶属度,使模型对噪声与类别边界附近的不确定性数据更具鲁棒性&#x…

阅读更多 →
Python实战:深圳二手房房价预测与可视化全流程解析 2026/10/1 5:31:49

Python实战:深圳二手房房价预测与可视化全流程解析

简介:基于Python的深圳二手房房价预测分析及可视化项目,源代码、文档说明与效果图一应俱全,数据采集自链家平台。适合计算机、人工智能、自动化等专业的在校生用于毕业设计、课程设计或项目实战,也适合初学者作为完整案例进阶学习…

阅读更多 →
JavaWeb试题库管理系统:从建库到文档的95分完整实现指南 2026/10/1 5:31:49

JavaWeb试题库管理系统:从建库到文档的95分完整实现指南

简介:这是一套面向计算机、通信、人工智能、自动化等相关专业学生的JavaWeb试题库管理系统完整项目,可直接用于期末课程设计、课程大作业或毕业设计,也适合JavaWeb初学者与进阶者学习借鉴。项目为个人独立设计,答辩评审分达99分&a…

阅读更多 →
MiMo-V2.6登顶AA指数开源榜首:双版本部署与模型选型实战解析 2026/10/1 5:31:49

MiMo-V2.6登顶AA指数开源榜首:双版本部署与模型选型实战解析

这周开源模型圈最热闹的消息,应该就是小米 MiMo-V2.6 的发布。官方口径很直接:Pro 与 Flash 双版本一起上,API 价格维持不变,AA 指数(Artificial Analysis 智能指数)直接把 Kimi K3、GLM-5.3 甩到了身后&am…

阅读更多 →
JavaWeb试题库管理系统实战:从零搭建到答辩高分 2026/10/1 5:31:49

JavaWeb试题库管理系统实战:从零搭建到答辩高分

简介:这是一套面向计算机、通信、人工智能、自动化等相关专业学生的JavaWeb试题库管理系统完整项目,适用于期末课程设计、课程大作业或毕业设计场景,也可供初学者与进阶者学习借鉴。项目由个人独立设计开发,答辩评审分达99分&…

阅读更多 →
无GPS照片定位法:用铁路、山脊线和桥墩实现2米精度 2026/10/1 5:31:42

无GPS照片定位法:用铁路、山脊线和桥墩实现2米精度

前阵子整理电脑里的旧照片,翻出一张只有铁路、一座多孔桥和远处山脊线的风景照。照片里干净到连一块路牌、一行站名都没有,朋友看了一眼问我:这到底是在哪拍的?我当时答不上来,因为照片既没写坐标,也没有任…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉