计算机毕业设计选题推荐|【基于深度学习的电梯电动车违规进入检测研究】YOLO26m+可视化大屏

精彩专栏推荐订阅:在下方主页👇🏻👇🏻👇🏻👇🏻

💖🔥作者主页 :计算机毕设木哥🔥 💖

文章目录

一、项目介绍

电梯轿厢空间狭小,电动车一旦被推进楼道或电梯,起火后逃生通道很快被堵住,物业靠人盯监控很难做到全天候。普通监控只能看到画面,无法自动区分自行车、电瓶车和人员,事后追溯也要一帧一帧翻录像。本文通过开发一个基于深度学习的电梯电动车违规进入检测系统,用以帮助解决电梯场景下违规车辆识别与记录追溯的问题。

系统以 YOLO26m 模型为核心,用 SGD 优化器配合 Mosaic、HSV、翻转等增强,导出 ONNX 后由 onnxruntime 在 Django 后端完成推理,前端用 Vue 与 ECharts 呈现。后端按 preprocess.json 做 letterbox 预处理,对输出解码、NMS 和坐标反算,再用 Energy Score 对域外图片做拒识;图片页支持多图队列与三并发,视频页按时间抽帧并把帧与框合成到同一画布,摄像头页接实时流逐帧识别,结果连同类别、置信度、耗时写入历史表,聚合出小时趋势、类别分布、置信度与星期热力五张大屏图表。

经过图片、视频、摄像头三条链路和不同光照、遮挡样张的测试,本系统能满足物业值班人员、小区管理员和住户的日常使用需求。值班人员可以快速确认违规画面并留存证据,管理员能从历史记录里回看高频时段与车辆类别,住户也能通过识别结果了解电梯内的通行情况。系统把模型训练、推理部署和业务管理串成一条线,为电梯电动车治理提供了一个可落地、可复盘的辅助工具。

二、视频展示

基于深度学习的电梯电动车违规进入检测研究

三、开发环境

模型与训练:YOLO26m 目标检测模型,PyTorch,Ultralytics,SGD 优化器,Mosaic / HSV / 翻转数据增强

图像与数据处理:OpenCV,NumPy,Pandas,scikit-learn,cleanlab(数据错标审计)

模型导出与推理:ONNX,onnxruntime,NMS 在后端运行时执行

后端:Django,PyMySQL,django-cors-headers,MySQL(utf8mb4)

前端:Vue,Element UI,ECharts,axios

运行与构建:Node.js

四、系统展示

系统页面模块展示:

模型结果图:

五、代码展示

bash 复制代码
def load_decisions():
    """读 lr_finder.json 的 decisions ------ 正式训练配置的唯一来源(#154 落点 c)。"""
    import json

    if not os.path.isfile(LR_FINDER_JSON):
        log(f"[main] FAIL:短扫产物不存在 {LR_FINDER_JSON} ------ 正式训练前必跑一次短扫(#35)")
        sys.exit(1)
    with open(LR_FINDER_JSON, encoding="utf-8") as f:
        jd = json.load(f)
    dec = jd.get("decisions")
    if not isinstance(dec, dict) or not dec.get("optimizer"):
        log("[main] FAIL:lr_finder.json 缺 decisions.optimizer ------ 短扫未定稿,不准开正式训练")
        sys.exit(1)
    return jd, dec


def load_bench():
    """读 bench 实测定稿(batch / grad_ckpt / imgsz / amp)------短扫与正式同配置。"""
    import json

    with open(BENCH_JSON, encoding="utf-8") as f:
        return json.load(f)


def dataset_hash():
    """数据集指纹(防 best.pt 换数据集)------split 文件 + 标签目录 md5。"""
    import hashlib

    h = hashlib.md5()
    h.update(DATA_YAML.encode("utf-8"))
    labels_dir = os.path.join(MODEL_TRAINING, "data", "labels")
    if os.path.isdir(labels_dir):
        for name in sorted(os.listdir(labels_dir)):
            if name.endswith(".txt") and name.split(".")[0] in {"train", "val", "test"}:
                h.update(name.encode("utf-8"))
                with open(os.path.join(labels_dir, name), "rb") as f:
                    h.update(f.read())
    return h.hexdigest()[:12]
python 复制代码
def letterbox(im, new_shape, stride, pad_value, center, scaleup, interpolation):
    """LetterBox 缩放填充:与训练侧预处理保持同一种几何变换。"""
    import cv2
    h, w = im.shape[:2]
    r = min(new_shape[0] / h, new_shape[1] / w)
    if not scaleup:
        r = min(r, 1.0)
    new_unpad = (int(round(w * r)), int(round(h * r)))
    if (w, h) != new_unpad:
        im = cv2.resize(im, new_unpad, interpolation=interpolation)
    dw, dh = new_shape[1] - new_unpad[0], new_shape[0] - new_unpad[1]
    if center:
        top, bottom = dh // 2, dh - dh // 2
        left, right = dw // 2, dw - dw // 2
    else:
        top, bottom = 0, dh
        left, right = 0, dw
    im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(pad_value, pad_value, pad_value))
    return im, r, (left, top)


def preprocess(img_bgr, cfg):
    """按该模型 preprocess.json 逐字段复刻训练侧预处理:BGR → LetterBox → RGB → /255 → NCHW。

    返回 (tensor, meta):meta 带 letterbox 的缩放比 r 与左/上填充 (left, top),
    供后处理把检测框从网络输入空间反算回原图像素坐标(不回算则框整体偏移)。
    """
    import cv2
    size = cfg.get('input_size') or [3, cfg.get('imgsz', 512), cfg.get('imgsz', 512)]
    h, w = size[1], size[2]
    lb = cfg.get('letterbox') or {}
    stride = int(lb.get('stride', 32))
    scaleup = bool(lb.get('scaleup', True))
    center = bool(lb.get('center', True))
    pad_value = float(lb.get('padding_value', 114))
    interp = cv2.INTER_LINEAR
    if not scaleup:
        r = min(h / img_bgr.shape[0], w / img_bgr.shape[1])
        new_unpad = (int(round(img_bgr.shape[1] * r)), int(round(img_bgr.shape[0] * r)))
        dh, dw = h - new_unpad[1], w - new_unpad[0]
        top, bottom = dh // 2, dh - dh // 2
        left, right = dw // 2, dw - dw // 2
        img_bgr = cv2.copyMakeBorder(img_bgr, top, bottom, left, right,
                                     cv2.BORDER_CONSTANT, value=(pad_value, pad_value, pad_value))
    else:
        img_bgr, r, (left, top) = letterbox(img_bgr, (h, w), stride, pad_value, center, scaleup, interp)
    if (img_bgr.shape[0] != h) or (img_bgr.shape[1] != w):
        img_bgr = cv2.resize(img_bgr, (w, h), interpolation=interp)
    if str(cfg.get('color_order', 'RGB')).upper() == 'RGB':
        img_bgr = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
    arr = img_bgr.astype(np.float32) * float(cfg.get('scale', 1.0 / 255))
    mean = np.array(cfg.get('mean', [0, 0, 0]), dtype=np.float32)
    std = np.array(cfg.get('std', [1, 1, 1]), dtype=np.float32)
    arr = (arr - mean) / std
    arr = arr.transpose(2, 0, 1)
    tensor = np.ascontiguousarray(arr[np.newaxis], dtype=np.float32)
    return tensor, {'r': float(r), 'left': int(left), 'top': int(top),
                    'net_h': int(h), 'net_w': int(w)}


def unletterbox_boxes(boxes, prep):
    """把网络输入空间的 xyxy 框反算回原图像素坐标:x_orig = (x_net - left) / r。"""
    if not boxes:
        return boxes
    r = float(prep.get('r') or 1.0)
    if r <= 0:
        r = 1.0
    left = float(prep.get('left') or 0)
    top = float(prep.get('top') or 0)
    out = []
    for b in boxes:
        out.append([(b[0] - left) / r, (b[1] - top) / r,
                    (b[2] - left) / r, (b[3] - top) / r])
    return out


def nms(boxes, scores, iou_thr, max_det):
    """标准非极大值抑制(框为 xyxy 像素坐标)。"""
    if len(boxes) == 0:
        return []
    x1, y1, x2, y2 = boxes[:, 0], boxes[:, 1], boxes[:, 2], boxes[:, 3]
    areas = np.clip((x2 - x1) * (y2 - y1), 0, None)
    order = scores.argsort()[::-1]
    keep = []
    while order.size > 0 and len(keep) < max_det:
        i = order[0]
        keep.append(i)
        if order.size == 1:
            break
        xx1 = np.maximum(x1[i], x1[order[1:]])
        yy1 = np.maximum(y1[i], y1[order[1:]])
        xx2 = np.minimum(x2[i], x2[order[1:]])
        yy2 = np.minimum(y2[i], y2[order[1:]])
        inter = np.clip(xx2 - xx1, 0, None) * np.clip(yy2 - yy1, 0, None)
        union = areas[i] + areas[order[1:]] - inter
        iou = inter / np.clip(union, 1e-9, None)
        order = order[1:][iou <= iou_thr]
    return keep


def postprocess_detection(out, meta, work_point):
    """原始张量 (B, 4+nc, anchors) → xyxy 像素框 + 类别 + 置信度;NMS 在运行时执行。"""
    arr = np.asarray(out, dtype=np.float32)
    if arr.ndim == 3:
        arr = arr[0]
    nc = int(meta.get('num_classes') or 3)
    if arr.shape[0] < 4 + nc:
        return []
    dbox = arr[:4, :]
    cls = arr[4:4 + nc, :]
    # 分类段已是 sigmoid 概率
    if float(np.max(cls)) > 1.0 + 1e-4:
        cls = 1.0 / (1.0 + np.exp(-cls))
    conf_thr = float(work_point.get('conf', 0.6))
    iou_thr = float(work_point.get('iou', 0.45))
    max_det = int(work_point.get('max_det', 300))
    # dbox 为 cx,cy,w,h(输入图像素空间)
    cx, cy, bw, bh = dbox[0], dbox[1], dbox[2], dbox[3]
    x1 = (cx - bw / 2.0)
    y1 = (cy - bh / 2.0)
    x2 = (cx + bw / 2.0)
    y2 = (cy + bh / 2.0)
    out_rows = []
    for ci in range(nc):
        scores = cls[ci]
        mask = scores >= conf_thr
        if not np.any(mask):
            continue
        idx = np.nonzero(mask)[0]
        b = np.stack([x1[idx], y1[idx], x2[idx], y2[idx]], axis=1)
        s = scores[idx]
        keep = nms(b, s, iou_thr, max_det)
        for k in keep:
            out_rows.append({'cls': ci, 'conf': float(s[k]),
                             'bbox': [float(b[k][0]), float(b[k][1]), float(b[k][2]), float(b[k][3])]})
    out_rows.sort(key=lambda r: r['conf'], reverse=True)
    return out_rows[:max_det]

六、项目文档展示

七、项目总结

本课题面向电梯轿厢内电动车违规进入的治理场景,使用 5461 张电梯监控图片、11676 个标注实例训练 YOLO26m 检测模型,按自行车、电瓶车、人员三类输出检测框与置信度,并以 conf=0.6、iou=0.45 为工作点完成 NMS,导出 ONNX 后接入 Django 后端完成预处理、推理、坐标反算与域外拒识。系统前端用 Vue 与 ECharts 实现图片多图并发识别、视频抽帧帧同步合成、摄像头实时识别,识别结果写入历史表并按账号分流,支持类别筛选、详情查看与软删除,大屏从真实记录聚合小时趋势、类别分布、置信度与星期热力五张图。测试表明该方案能把模型训练、部署推理和业务管理串成闭环,为物业值班人员、小区管理员和住户提供可追溯的辅助手段,也为同类电梯场景的视觉检测落地提供参考

大家可以帮忙点赞、收藏、关注、评论啦 👇🏻

💖🔥作者主页 :计算机毕设木哥🔥 💖

相关推荐
盼小辉丶28 分钟前
PyTorch强化学习实战(35)——多智能体强化学习
人工智能·pytorch·深度学习·强化学习
我就是全世界43 分钟前
【轻AI越影视觉开发板】local_voice_process 语音功能模块教程——从音频采集到本地语音识别、多模态视觉交互与 ESP32-S31 硬核对比
人工智能·语音识别
hpoenixf1 小时前
Agent 测评的身份难题:一次任务换了模型,历史成绩还能算数吗?
人工智能
hpoenixf1 小时前
专家、Subagent、Review、Judge:都是另一个模型,为什么不是同一回事?
人工智能
深蓝AI3 小时前
26.1% 的 Agent 技能带漏洞:skills 霸榜 GitHub 当天,NVIDIA 和 OpenAI 同时掏出安检仪
人工智能·程序员
锋行天下8 小时前
langgraph 后端发自定义数据,前端接收方法概括
人工智能·python
泯泷9 小时前
单个 AI 再强,为什么也干不过一支 AI 团队?
人工智能·llm·agent
浪遏10 小时前
认识 wm:从多平台发布到可扩展 CLI 的架构设计
人工智能