毕设停车场车辆检测:从YOLOv5到轻量化部署的完整技术路径

📅 发布时间:2026/7/6 11:07:56 👁️ 浏览次数:
毕设停车场车辆检测:从YOLOv5到轻量化部署的完整技术路径
最近在帮学弟做毕设选了个挺实用的题目——停车场车辆检测。这个场景看着简单真做起来才发现坑不少光线忽明忽暗、车子被树或者柱子挡一半、远处的小车像个小黑点……直接用现成的大模型吧服务器开销大、延迟高自己从头搞鲁棒性又很难保证。折腾了一圈最后用YOLOv5s TensorRT Flask这套组合拳跑通了单帧推理能压到50ms以内效果还不错。把整个流程和踩过的坑梳理一下给有类似需求的同学参考。1. 背景与核心痛点停车场检测到底难在哪停车场车辆检测属于安防监控下的一个细分领域和通用目标检测相比它有自己独特的挑战复杂的光照与天气条件室内停车场光线不均出入口处明暗交替剧烈室外停车场则受昼夜、阴晴、雨雪影响。模型必须对光照变化不敏感。严重的遮挡问题车辆密集停放时车身互相遮挡柱子、树木也会造成部分遮挡。这要求模型有较强的局部特征识别能力。小目标检测困难监控摄像头为了覆盖更大范围通常架设较高导致远处的车辆在图像中占比很小小于32x32像素这对检测器的特征提取能力是巨大考验。类内差异大车辆的颜色、型号、姿态正对、侧对、斜对千差万别需要模型有很好的泛化性。实时性要求作为可能的智能停车系统一环需要较高的处理速度通常要求20 FPS才能满足实时分析需求。2. 技术选型YOLOv5、YOLOv8还是EfficientDet选模型是第一步核心是在精度、速度和易用性之间找平衡。当时主要对比了三个主流选择YOLOv5 (ultralytics版)社区生态极其活跃文档和教程丰富。它提供了从n纳米到x超大多个尺寸的预训练模型。YOLOv5s在速度和精度上取得了很好的平衡且其PyTorch实现非常清晰易于修改和调试。对于毕设这种需要快速验证和部署的场景它的综合友好度最高。YOLOv8Ultralytics公司推出的新一代YOLO在精度和速度上相比v5有进一步提升并集成了分类、分割、姿态估计等多种任务。但相对的其模型结构更复杂一些对于完全从零开始理解可能稍费时间且部分部署工具链的适配不如v5成熟。EfficientDet谷歌出品基于EfficientNet骨干网络和BiFPN特征金字塔在COCO数据集上精度很高。但其官方实现多为TensorFlow 1.xPyTorch复现版本众多且质量参差不齐对于新手来说环境配置和调试成本较高。最终选择YOLOv5s的理由对于毕业设计我们的首要目标是“在有限时间内稳定地做出一个可演示的系统”。YOLOv5s提供了开箱即用的训练脚本、清晰的代码结构、活跃的社区遇到问题容易搜到答案并且其模型尺寸适中在消费级GPU如GTX 1660 Ti, RTX 3060上也能快速训练和推理。它是一个非常稳妥且高效的起点。3. 核心实现从数据到训练好的模型选好模型接下来就是“喂数据调模型”的实战环节。3.1 自定义数据集构建与标注数据是模型的上限。我们收集了约2000张包含各种场景白天、夜晚、阴天、拥堵、空旷的停车场图片。标注工具使用labelImg或更高效的CVAT进行标注。只标注一个类别car。标注格式YOLOv5使用的是归一化的中心坐标和宽高格式(class_id, x_center, y_center, width, height)所有值都在0到1之间。一张图片对应一个.txt文件。数据组织按以下结构放置dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/数据增强YOLOv5内置了强大的数据增强Mosaic MixUp等能有效提升模型鲁棒性。我们在data.yaml中配置路径和类别信息即可。3.2 模型微调与超参调整我们采用迁移学习在COCO预训练的YOLOv5s权重基础上进行微调。关键超参数设置在hyp.scratch-low.yaml或直接传入命令行imgsz: 640输入图像尺寸。更大的尺寸有利于小目标检测但会增加计算量。640是兼顾速度和精感的常用值。batch: 16批次大小。根据你的GPU显存调整如8G显存可设16。太小可能训练不稳定太大可能爆显存。epochs: 100迭代轮数。通常50-100轮足够微调收敛可以观察验证集mAP曲线决定是否早停。lr0: 0.01初始学习率。微调时可以从更小的值开始如0.001以防破坏预训练权重。weight_decay: 0.0005权重衰减防止过拟合。训练命令示例python train.py --img 640 --batch 16 --epochs 100 --data ./data/parking.yaml --cfg ./models/yolov5s.yaml --weights yolov5s.pt --hyp ./data/hyps/hyp.scratch-low.yaml --name parking_exp监控与评估训练时TensorBoard日志会记录损失、精度(mAP0.5, mAP0.5:0.95)等指标。重点关注验证集mAP的变化确保模型没有过拟合。4. 部署优化让模型飞起来训练出模型只是第一步如何高效部署才是毕设演示的亮点。4.1 模型导出与TensorRT加速PyTorch的.pt模型直接推理速度不够理想。我们将其转换为TensorRT引擎利用GPU的Tensor Core进行极致加速。导出ONNXYOLOv5提供了方便的导出脚本。python export.py --weights runs/train/parking_exp/weights/best.pt --include onnx --img 640 --batch 1 --simplify--simplify参数可以优化ONNX图结构。转换为TensorRT引擎使用TensorRT的trtexec工具或Python API进行转换。关键一步是启用FP16量化能在几乎不损失精度的情况下大幅提升速度、减小模型体积。trtexec --onnxbest.onnx --saveEnginebest_fp16.engine --fp16 --workspace2048 --minShapesinput:1x3x640x640 --optShapesinput:1x3x640x640 --maxShapesinput:1x3x640x640转换后模型体积通常能减少40%以上。4.2 构建带错误处理的Flask API将TensorRT引擎封装成Web API方便其他系统如前端车位状态展示调用。from flask import Flask, request, jsonify import cv2 import numpy as np import torch import json from flask_cors import CORS # 处理跨域请求 import logging from typing import List, Dict # 初始化Flask应用 app Flask(__name__) CORS(app) # 允许跨域方便前端调试 app.logger.setLevel(logging.INFO) # 加载TensorRT引擎的推理类 (这里需要你根据实际的TensorRT推理代码实现load_engine和infer方法) # 假设我们已经有一个封装好的类TensorRTInference try: from trt_inference import TensorRTInference detector TensorRTInference(engine_pathbest_fp16.engine) app.logger.info(模型加载成功) except Exception as e: app.logger.error(f模型加载失败: {e}) detector None def preprocess_image(image_bytes): 将上传的图片字节流转换为模型输入张量 nparr np.frombuffer(image_bytes, np.uint8) img cv2.imdecode(nparr, cv2.IMREAD_COLOR) if img is None: raise ValueError(无法解码图像) # 这里应添加与训练时一致的预处理resize, 归一化, BGR2RGB, 维度转换等 # 示例resize到640x640归一化HWC转CHW img_resized cv2.resize(img, (640, 640)) img_rgb cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB) img_normalized img_rgb / 255.0 input_tensor img_normalized.transpose(2, 0, 1).astype(np.float32) return input_tensor, img.shape[:2] # 返回原始图像尺寸用于后续坐标映射 app.route(/detect, methods[POST]) def detect(): 车辆检测API端点 if detector is None: return jsonify({error: 模型未加载}), 503 if image not in request.files: return jsonify({error: 未提供图像文件}), 400 file request.files[image] try: image_bytes file.read() input_tensor, orig_shape preprocess_image(image_bytes) except Exception as e: app.logger.error(f图像预处理失败: {e}) return jsonify({error: 图像处理错误}), 400 try: # 执行推理 detections detector.infer(input_tensor) # 假设返回格式为 [x1, y1, x2, y2, conf, cls] # 将坐标映射回原始图像尺寸 scale_x orig_shape[1] / 640 scale_y orig_shape[0] / 640 results [] for det in detections: if det[4] 0.25: # 置信度阈值 x1, y1, x2, y2 det[0]*scale_x, det[1]*scale_y, det[2]*scale_x, det[3]*scale_y results.append({ bbox: [round(x1), round(y1), round(x2), round(y2)], confidence: float(det[4]), class: car }) app.logger.info(f检测到 {len(results)} 辆车) return jsonify({detections: results}) except RuntimeError as e: app.logger.error(f推理过程错误: {e}) return jsonify({error: 推理服务内部错误}), 500 if __name__ __main__: # 生产环境建议使用 waitress 或 gunicorn app.run(host0.0.0.0, port5000, debugFalse)5. 性能实测与安全考量5.1 性能测试在不同硬件上测试我们的优化管道TensorRT FP16 FlaskNVIDIA GTX 1660 Ti (6GB): 平均推理时间 ~45ms 包含前后处理总耗时 ~70ms 内存占用约1.2GB。NVIDIA RTX 3060 (12GB): 平均推理时间 ~22ms 总耗时 ~45ms 内存占用约1.5GB。CPU (Intel i7-10750H): 仅使用ONNX Runtime时推理时间 ~350ms 不满足实时要求。结论在消费级GPU上实现50ms的单帧处理目标是完全可行的这为实时视频流处理约20FPS奠定了基础。5.2 安全与工程化考量模型版本管理当更新模型时如用新数据重新训练API服务应能平滑切换。我们的做法是将模型版本号加入引擎文件名如yolov5s_parking_v1.2.engine并在API启动时加载配置文件中指定的版本。更新时先部署新版本引擎和配置文件然后重启服务。输入验证与限流上述API示例包含了基本的错误处理。在生产环境中还应添加请求速率限制如使用Flask-Limiter防止恶意请求压垮服务。健康检查端点可以添加一个/health端点返回模型状态和服务负载便于监控。6. 避坑指南那些我们踩过的坑标注不一致导致漏检初期标注时对于被严重遮挡的车辆可见部分小于30%有的标注了有的没标导致模型学习混乱。解决方案制定明确的标注规范文档所有标注员统一标准并对标注结果进行交叉检查。摄像头角度引起的变形广角摄像头边缘的车辆会发生形变影响检测。解决方案在数据收集中就包含各种角度的图片让模型学习这种透视变换。如果条件允许可以对视频流先进行透视校正逆透视变换IPM将画面转换为鸟瞰图再进行检测这样车辆大小和形状更统一。服务冷启动的首帧延迟Flask应用启动后第一次推理耗时特别长主要是TensorRT上下文创建和初始化。解决方案在服务启动后主动用一张空白或示例图片进行一次“预热”推理让所有初始化工作在第一次真实请求前完成。误检与漏检的平衡调整置信度阈值conf-thres和非极大值抑制阈值iou-thres。对于停车场场景车辆通常不会重叠得太厉害可以适当降低iou-thres如0.4来分离靠得很近的车辆同时通过验证集调优conf-thres在误检和漏检间找到平衡点。总结与扩展思考通过以上步骤我们完成了一个从数据准备、模型训练、加速优化到服务部署的完整技术闭环。这个系统已经可以稳定地接收图片并返回车辆位置为毕设演示打下了坚实基础。如何让毕设更出彩这里有几个扩展方向多摄像头协同部署多个检测服务节点由一个中心调度器分配视频流任务。可以研究简单的负载均衡或者更高级的利用车辆重识别Re-ID技术跨摄像头跟踪特定车辆。车位状态联动这是最自然的延伸。在检测到车辆的基础上你需要一个“车位定义”的步骤可以是预先标定的车位坐标或使用语义分割模型动态划分。然后计算车辆边界框与车位区域的IoU判断车位是否被占用。最终可以统计出车位空闲率并可视化展示。集成到更大系统将你的检测API作为后端服务开发一个简单的前端页面用Vue或React实时显示摄像头画面、用框标出车辆并展示车位占用统计面板。这样一个完整的“智能停车场管理系统”原型就诞生了。希望这篇笔记能帮你理清思路。技术选型没有绝对的对错关键是快速迭代、解决问题。祝各位毕设顺利