简介这是一份围绕电梯监控视角下电动车与自行车识别的人工智能毕业设计项目包适合计算机视觉方向的本科生、研究生以及希望用完整案例入门深度学习的开发者。项目链路覆盖数据准备、特征学习、模型训练与评估核心涉及卷积神经网络、图像分类、数据集增广、过拟合缓解和实时部署等知识点能够帮助理解算法在真实监控场景中的落地方式与鲁棒性挑战。压缩包共计一百三十四个文件大小约十七兆包含三十四个可执行脚本、三十四个配置文件、二十三张图片样本、十八张图示以及容器部署文件、训练结果统计、事件日志、交互式教程笔记本和说明文档兼顾复现训练、环境搭建与理论研读。目前已有158人浏览学习学习者可以从教程笔记入手分步运行也可直接阅读源码与配置将训练流程迁移至自己的毕业设计或相关课题。1. 电梯监控里识别电动车不是“再训练一次”那么简单把“用于识别电梯监控视角内的电动车以及自行车”这个项目落地第一件事是承认这不是普通目标检测训练课的课后作业。电梯摄像头装在角落镜头朝下带广角畸变人推着自行车进去时车把、踏板互相遮挡电动车和自行车在俯视画面里轮廓高度相似。实测里最容易翻车的不是“检测不到”而是“把自行车当成电动车报警”或者是“电动车进了轿厢系统却等到关门后才出框”。这套方案的价值是让物业和安防团队在非机动车进入电梯的几秒内收到提醒同时尽量不误报。适合手里有电梯监控网络、想用视觉识别替代保安盯屏幕的团队也适合能把模型推到边缘盒子里的算法工程师往下看。2. 先看懂电梯监控视角为什么同一个目标换个角度就翻车2.1 电梯摄像头的画面特征俯角、短焦、顶光电梯监控的画质和普通道路监控完全是两个世界。摄像头多数是 2.8mm 或 3.6mm 短焦镜头安装高度两米多向下倾斜 30 到 60 度。画面里目标呈现强烈的透视形变一辆电动车从进门到停稳车长和车宽在画面里变化非常大。这种视角下目标检测框的宽高比不稳定容易从 1:2 变到 2:1模型如果用常规数据集训练第一关就会被视角打懵。另一个麻烦是光照。电梯轿厢顶部是 LED 灯板直下式照明导致车篮、座椅下方出现高光阴影对比轿厢不锈钢侧壁还会形成大面积反光。电梯门开的时候外部走廊光和轿厢内光剧烈交替摄像头自动增益会把画面拉得忽明忽暗。用白天的普通视频做训练模型在夜间和高动态场景下会出现肉眼可见的漏检。应对思路很明确不要死磕预训练模型的通用能力而是用电梯视角的样本做迁移。数据增强中要专门加透视变换、亮度抖动、反光模拟让模型学会在短焦广角下也认得出车。目标对象识别在这种场景里拼的不是模型结构多新而是训练数据分布和现场画面有多接近。2.2 电动车和自行车的关键差异点轮径、踏板、车篮、反光两类车在侧视图里很好分电动车有标志性的电池盒、宽踏板和后轮毂电机自行车只有细细的车架和脚踏。但在电梯俯视视角里这些特征全部被压扁只剩下“一个长条形的车体”。因此标注逻辑要从“认出这辆车”转向“找到几个稳定的判别特征”。我在项目里惯用的判据有三个。第一是踏板宽度电动车的脚踏区域明显比自行车宽而且很多电动车装了防滑脚垫在俯视画面里表现为一块深色矩形第二是后轮毂电动车后轮多数是轮毂电机侧边是圆盘状几乎看不到辐条自行车后轮则辐条清晰可见第三是车篮和前围很多电动车在踏板上方有封闭式前围板自行车通常没有。这些特征受监控分辨率影响相对小比看车漆、贴纸这些颜色特征可靠得多。还有一个容易被忽略的细节反光板。自行车出厂强制带前后反光板监控的红外补光灯或电梯白光打到反光板上会出现高亮点而电动车反光板经常损坏或缺失。这个特征可以作为辅助但不能做唯一依据否则后期很容易被现场其他发光物体干扰。标注时如果只画一个框模型只能学到整体轮廓如果要进一步提高细分准确率可以考虑在数据里增加关键点标签例如把“后轮中心”“踏板中心”作为额外监督信息。2.3 数据采集与标注目标对象识别的第一步没有现场数据后面所有参数都是空谈。常见做法是从电梯监控的 RTSP 流里抽帧而不是下载公开数据集因为公开数据集几乎没有“电梯顶部视角”这个分布。抽帧脚本用 OpenCV 就能写注意处理断流重连。import cv2 import os import time rtsp_url rtsp://your_user:your_passwordcamera_ip:554/stream1 cap cv2.VideoCapture(rtsp_url) # 只缓冲最新一帧避免画面越积越旧 cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) cap.set(cv2.CAP_PROP_FPS, 5) save_dir capture os.makedirs(save_dir, exist_okTrue) frame_id 0 while True: ok, frame cap.read() if not ok: print(read fail, reconnect after 2s) time.sleep(2) cap.open(rtsp_url) continue # 按帧号抽样25fps 视频每 10 帧约 0.4 秒一张 if frame_id % 10 0: cv2.imwrite(os.path.join(save_dir, f{frame_id:05d}.jpg), frame) frame_id 1 if cv2.waitKey(1) 0xFF ord(q): break cap.release()这段脚本里有三个参数值得解释。CAP_PROP_BUFFERSIZE设置为 1是为了保证读到的是最新画面而不是积压了三秒的旧帧frame_id % 10控制抽帧密度电梯进出过程通常只有 10 到 30 秒抽太密会让同一目标大量重复抽太疏又会漏掉关键姿态time.sleep(2)是 RTSP 断流后的重连间隔摄像头 IP 地址、用户名密码要在实际现场填。抽出的帧先人工快速筛一遍去掉空车、无关人员和画面完全模糊的帧剩下的图用 LabelMe 标注。标注类别就是两个ebike和bicycle。我的建议是标注完整的车体包围盒哪怕车辆有一部分被轿厢里的人挡住。如果一辆车被严重遮挡到只剩一个车把这种样本不要硬标放进“丢弃”列表。每类有效样本尽量不少于 1500 张图、3000 个实例。只标几百张就训练模型会很快过拟合到少量场景的固定光照下换一台电梯立刻翻车。3. 把识别模型跑通从数据目录到 YOLOv8 训练的最小路线3.1 选 YOLOv8 还是 YOLOv5边缘设备上的推理开销电梯识别项目里模型最终跑在嵌入式盒子、IPC 主板或者带有 GPU 的小服务器上。YOLOv5 非常稳定资料多但 YOLOv8 在多类别细分和训练收敛上更省心尤其是提供了 nano 和 small 两个轻量版本适合边缘部署。实际项目里我用得最多的是 YOLOv8n理论上 GFLOPs 最低在 RK3588 或 Jetson 上可以跑到实时。如果标注数据很多追求更高精度再切到 YOLOv8s。这里要明确一个原则电梯识别不需要很小的目标框。电梯轿厢最大也就两三米见方摄像头视角内的一辆电动车在 640×640 输入下大约占 150 到 400 像素的框。不需要为了远处小目标放大输入到 1280那只会白白增加延迟。用imgsz640是最平衡的选择。3.2 按 YOLO 格式组织数据集和 YAML 配置LabelMe 输出的 JSON 不能直接喂给 YOLO需要转换。YOLO txt 标注的格式是每行一个目标class_id center_x center_y width height其中坐标是相对图像宽高的归一化值。转换脚本要处理两个细节一是多边形标注转矩形框二是坐标越界裁剪。电梯门打开时车身常被画面边缘切掉一半边界框坐标可能出现超出 0~1 的情况YOLO 训练能容忍稍微越界但最好还是 clamp 到 0.0001~0.9999。import json import os import glob def convert_labelme_to_yolo(json_path, out_dir, class_map): with open(json_path, encodingutf-8) as f: data json.load(f) image_h data[imageHeight] image_w data[imageWidth] lines [] for shape in data[shapes]: label shape[label] if label not in class_map: continue # LabelMe 存的是多边形顶点这里直接取矩形包围盒 pts shape[points] xs [p[0] for p in pts] ys [p[1] for p in pts] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) cx ((x_min x_max) / 2) / image_w cy ((y_min y_max) / 2) / image_h bw (x_max - x_min) / image_w bh (y_max - y_min) / image_h # 防止转换后面朝边界越界 cx min(max(cx, 0.0001), 0.9999) cy min(max(cy, 0.0001), 0.9999) bw min(max(bw, 0.0001), 0.9999) bh min(max(bh, 0.0001), 0.9999) lines.append(f{class_map[label]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) if lines: base_name os.path.basename(json_path).replace(.json, .txt) with open(os.path.join(out_dir, base_name), w, encodingutf-8) as f: f.write(\n.join(lines))这个脚本的核心逻辑只有一个把多边形的矩形外接框转成 YOLO 需要的中心点加宽高格式。实际标注中不建议用很夸张的多边形去描车轮廓直接画矩形框更快也足够训练。class_map可以定义为{ebike: 0, bicycle: 1}转完以后检查一遍 txt 文件看看没有漏生成、没有空文件。数据集目录按 YOLO 约定建成这样dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── electric_bike.yaml验证集建议从不同电梯、不同时段的数据里抽取而不是随机抽帧。很多项目在这里犯迷糊随机抽帧会让同一天的画面同时出现在训练集和验证集里Final mAP 虚高到现场换一台电梯就不行。每台电梯保留 20% 的帧做验证跨场景验证集才有说服力。3.3 训练命令和关键参数epochs、imgsz、batchYAML 内容如下path: /path/to/dataset train: images/train val: images/val names: 0: ebike 1: bicycle然后执行训练yolo detect train \ dataelectric_bike.yaml \ modelyolov8n.pt \ epochs120 \ imgsz640 \ batch16 \ device0 \ patience20 \ project./runs \ nameelecbike_v1参数说明epochs120是初始值配合patience20早停模型连续 20 个 epoch 在验证集上不涨就自动结束batch16在 16GB 显存下比较稳妥显存小的改成 8不用太纠结device0指定第一张 GPU没有 GPU 环境把训练规模缩小但会非常慢project和name指定输出目录方便多个实验对比。训练过程中重点看两个指标一是mAP50它反映“框的位置大致对了就算对”适合电梯这类对精确分割要求不高的场景二是bicycle与ebike这两类之间的混淆程度。如果训练结束后的混淆矩阵显示自行车有 15% 被判成了电动车这个模型不能直接上线因为误报会触发物业警报。3.4 从 results.csv 里读模型的真实水平YOLOv8 训练完会在运行目录留下results.csv里面每个 epoch 都有train/box_loss、val/cls_loss等记录。用一个小脚本扫一眼python -c import pandas as pd; dfpd.read_csv(runs/elecbike_v1/results.csv); print(df.columns.tolist()); print(df.tail(1))关注最后一列平衡的指标并输出 PR 曲线。电梯场景里我会额外统计一个“每千帧误报数”这个数比 mAP 更贴近物业的体验。如果模型在 1000 帧里把过道里的垃圾桶误认成自行车虽然 mAP50 还是 0.98现场也无法接受。这个统计可以用测试集视频跑一遍推理脚本把连续 3 帧以上误报的片段记录下来单独分析。4. 从模型到电梯RTSP 视频流里的实时识别与报警逻辑4.1 拉取电梯监控流OpenCV 的 VideoCapture 与延迟控制训练好的模型如果只是离线跑图片没有落地价值。现场部署时算法服务要以 RTSP 流为输入。实际写推理服务时OpenCV 的VideoCapture虽然简单但有几个明显的坑RTSP 流断线后不会自动恢复cap.read()会阻塞到下一帧到达导致 CPU 空转还有缓冲区积累带来的画面延迟。我常用的拉流推理结构长这样import cv2 import torch import time model torch.hub.load(./yolov8, custom, pathbest.pt, sourcelocal) cap cv2.VideoCapture(rtsp://your_user:your_passwordcamera_ip:554/stream1) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) skip_count 0 while True: ok, frame cap.read() if not ok: print(connection lost, wait 3s) time.sleep(3) cap.open(rtsp://your_user:your_passwordcamera_ip:554/stream1) continue # 电梯场景 5~10fps 足够不需要每帧都推理 skip_count 1 if skip_count % 3 ! 0: continue results model.predict(frame, imgsz640, conf0.35, device0, verboseFalse) boxes results[0].boxes ...这里的skip_count % 3是抽帧推理控制。电梯门开关、人的走动不会快到单帧内完成25fps 的视频每 3 帧推理一次大约 8fps已经足够抓取“推车进入”这个行为。如果边缘设备算力不够可以继续降到% 5。不要用模型处理每一帧那样只会把延迟拉高反而丢失报警窗口。4.2 行为识别连续帧判定而不是单帧报警单帧检测到电动车就报警是最早被现场否掉的方案。电梯门打开时走廊上停着的电动车可能短暂出现在画面边缘如果此时报警等于每天报几百次。正确做法是基于连续帧做行为判定只有当电动车或自行车“进入轿厢并停留超过一定时间”才触发。一个可复现的滑动窗口逻辑如下from collections import deque window deque(maxlen5) alarm_threshold 3 # 连续5帧中至少3帧有有效目标 def update_detection(current_frame_has_target): window.append(1 if current_frame_has_target else 0) if sum(window) alarm_threshold: return True return False这个逻辑的意义很简单用 5 帧的窗口做去抖瞬时噪声不会触发报警。结合电梯场景还应该加一个“停留时间”条件。进门可能只要 1 到 2 秒但如果车停在轿厢内窗口会持续命中。我一般会取连续 1.5 秒存在目标作为确认报警报警后要等到连续 2 秒无目标才解除避免重复报警。这里有个容易被忽略的参数conf阈值。模型训练时默认用 0.25 的置信度导出预测框但现场频闪、反光会把置信度推高。我建议部署时把conf设在 0.35~0.45 之间宁肯漏掉一些低置信度目标也要保证报警不吵。置信度阈值要根据电梯实际画面调不能照抄训练环境。4.3 边缘端部署把 PyTorch 模型导出成 TensorRT Engine训练机上是 PyTorch现场设备多数是 NVIDIA Jetson 或者带独立显卡的工控机。直接把.pt文件拷过去推理速度慢而且依赖环境多。常见做法是先导出 ONNX再在目标设备上编译成 TensorRT engine。导出命令yolo export modelbest.pt formatonnx imgsz640 opset11 # 在 Jetson 或 x86 上使用 TensorRT 8.x trtexec --onnxbest.onnx \ --saveEnginebest.engine \ --fp16 \ --maxBatch1这两个命令背后的参数含义opset11是为了兼容旧版推理框架--fp16半精度在电梯识别这类分类任务上精度损失很小但推理速度能提升接近一倍--maxBatch1表示单路单帧批处理因为电梯检测通常是一路视频对应一个模型实例不需要动态 batch。如果现场设备不是 NVIDIA例如瑞芯微 RK3588建议用rknn-toolkit2把 ONNX 转成.rknn格式注意 YOLOv8 的检测头在 RKNN 转换时要额外处理输出层最好参考官方提供的 YOLOv8 适配脚本。这块很容易踩坑我在常见问题里详细说。5. 避坑与排查电梯场景里最容易翻车的五个实际问题5.1 自行车和电动车互相误识别这个现场最容易翻车。有些自行车配有宽大的车筐和电池组外形上和轻型电动车非常接近反过来一些电动车断电推行时踏板不动前后轮辐条清晰模型会误判成自行车。排查思路先看混淆矩阵确认是“检测框问题”还是“分类头问题”。如果ebike的框位置很准但框内物体被分类成bicycle说明模型学到的主要特征是挡泥板、车架粗细这类细纹理而这些纹理在俯视视角下不稳定。解决方法是补数据针对性标注“轮廓接近”的样本同时把两者互为负样本加入数据增强。另一个有效做法是把问题从“二分类”改成“检测属性分类”先用一个通用模型检出所有两轮车再对框内区域用一个小分类网络判断是电动还是自行车。这样即使框不完美分类网络也能看到更大上下文。5.2 夜间模式和背光导致的漏检电梯摄像头在光线暗时自动切到红外模式或补光模式画面变成黑白且对比度低。训练集以白平衡彩色画面为主的话模型在红外画面上的特征模式不匹配表现断崖式下降。解决方法是采集同场景的黑白/夜视片段加入训练集。如果现场不方便可以用数据集增强里的灰度化、亮度抖动和对比度调整来近似。还有个实用习惯给模型输入时先做自适应直方图均衡化CLAHE只在推理前处理中加上gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) clahe cv2.createCLAHE(clipLimit3.0, tileGridSize(8, 8)) enhanced clahe.apply(gray) frame cv2.cvtColor(enhanced, cv2.COLOR_GRAY2BGR)这种预处理可以让夜间画面对模型更友好但要注意亮度提升也会把电梯金属框的反射放大需要和降置信度阈值配合使用。5.3 推车进出时检测框抖动触发断断续续的报警电梯内人推着车移动时车身大部分被人体挡住。模型可能这一帧检出ebike下一帧因为遮挡强度不够变成低置信度窗口逻辑反复横跳报警器直到人走了才触发。处理方法是给推理结果做一个短跟踪。不用上 DeepSORT 这种重型跟踪器单纯用上一次检测的 IoU 匹配就够def match_previous(prev_box, curr_boxes, iou_threshold0.3): for box in curr_boxes: if iou(prev_box, box) iou_threshold: return box return prev_box # 短暂遮挡时沿用上一帧检测结果这个“沿用”逻辑最多延续 3 帧超过 5 帧仍然无匹配就清除目标。它解决的是电梯内目标被短暂遮挡导致的报警闪断而不是跨镜头跟踪。操作上要注意不要把其他乘客的腿误当成延续目标IoU 阈值要调低到 0.2~0.3 之间。5.4 边缘设备推理慢一帧要 300 毫秒很多团队直接把 YOLOv8s 或 m 型号带上 Jetson Nano发现根本跑不动。原因不是模型训练不好而是没有做模型剪枝和输入尺寸限制。解决路线有两条。第一条是把imgsz640降到imgsz480电梯目标占画面比例较大降低分辨率对 mAP50 影响很小速度提升明显第二条是换用yolov8n配合 TensorRT FP16实测在 Jetson Orin Nano 上能跑到 30ms 左右。如果还不能接受就检查有没有在推理时意外开启verboseTrue或持续把所有结果写入日志I/O 反而比模型更耗时。5.5 测试集准确率很高但现场误报暴增这是最玄学也最伤人信心的问题。测试集是从这台电梯抽帧出来的验证集也是同一台模型相当于作弊式记住了这部电梯的背景。到现场换一台不同品牌电梯地面反光、门框颜色、顶上装饰灯全变了模型把反光边缘推断成自行车辐条。解决方法是训练时把验证集改成“跨电梯集”保证训练集和验证集不要从同一台设备抽帧。现场上线后还要做增量训练把误报的截图回传每隔一周标注一两百张误报样本用小学习率继续训练。这是模型部署后三个月内必须坚持的一步电梯视角的差异一定要靠现场数据来填。6. 现场验证与模型迭代用 2000 张真实截图检验过不过关模型准备上线前我会先跑一个很“土”但很有效的验收脚本。找现场部署那台电梯保存 2000 张不同光线、不同时段、不同人流的截图按时间顺序回放模型对这 2000 张图逐张推理输出每个目标的类别、置信度和时间点。然后人工对着结果表检查哪些是真正需要报警的车哪些是误报警。这个验证脚本最关键的不是平均精度而是误报率和漏报率。我会设定一个明确标准电梯识别工况下每 1000 帧允许最多 2 次误报漏报允许在真正推车进入后的 3 秒内出现 1 次。超过这个线就不上正式环境。通过这轮验证后再花一小时调阈值# 把误报、漏报最多的阈值区间打印出来 def print_threshold_report(results, ground_truth): for conf_threshold in [0.25, 0.3, 0.35, 0.4, 0.45, 0.5]: tp len(results[(results.conf conf_threshold) (results.is_target 1)]) fp len(results[(results.conf conf_threshold) (results.is_target 0)]) fn len(results[(results.conf conf_threshold) (results.is_target 1)]) print(fconf{conf_threshold:.2f} TP{tp} FP{fp} FN{fn})这里得到的不是百分之百完美的阈值只是一个起点。上线后第一周我会每天翻一次报警记录特别是深夜和早晨逆光时段的误报截图把可以复现的问题样本攒起来做下一轮增量训练。这个习惯帮我解决过无数个角落里的暗光问题也让我意识到电梯监控视角下的两轮车识别其实没有一劳永逸的模型只有持续跟现场搏斗的小模型。现在我把 YOLOv8n 作为默认基线凡是新接的电梯先在本地跑一遍模拟回放再决定要不要加现场样本。这套流程走顺之后从拿到视频流到模型上线大约只需要三天希望帮到你。本文还有配套的精品资源点击获取