资讯动态

停车场车位识别实战:从YOLO模型训练到边缘部署的完整方案

发布时间:2026/10/19 17:09:35 来源:尧图企业网站定制
停车场车位识别这个项目我在真实场景里前后折腾了快两个月。从最开始用摄像头对着空荡荡的地面拍照到后来在阴雨天、夜间、被挡了一半车头的复杂工况下还能稳定输出空位状态中间踩过的坑确实不少。这篇文章就把我这套完整方案从数据、模型、部署到排查全流程捋一遍给正要入坑或者已经被坑住的朋友一个直接能抄作业的参考。1. 项目整体设计与方案选型1.1 先想清楚这个项目到底要解决什么问题很多人一听到“停车场车位识别”第一反应就是“用目标检测框出车来”。这个想法不完全错但如果你真按这个思路去做后面一定会返工。原因很简单停车场管理方要的不是“有没有车”而是“哪个车位被占了、哪个车位空着”。这两个需求看起来差不多实际在工程实现上是两条完全不同的路。检测车辆只需要输出一张图上所有车的包围框然后把框和车位区域的坐标做交集判断就能推断出占用状态。但这里有个很实际的麻烦摄像头视角通常比较倾斜车辆会互相遮挡一个框可能同时压住两个车位而且车头的形状在不同角度下差异巨大检测框不稳定空位判断就会跟着抖。我在项目初期就是吃了这个亏模型精度做到90%以上但落到具体车位编号的占用率统计上准确率只有八成出头根本没法上线。所以后来我换了个思路把问题拆成“车位区域定位 区域内车辆存在性判断”两个子任务。车位区域用人工标定的固定多边形来定义车辆存在性用检测模型对每个区域做判定。这样既能保证车位编号和服务端的数据库一一对应又避免了自由检测框和车位映射的错位问题。搞清楚这一点后面所有技术选型都顺了。1.2 技术路线对比传统视觉方案为什么被淘汰我最早试的是纯OpenCV方案具体做法是车位地面上画框然后对每个车位区域做背景差分或者边缘检测。背景差分在室内灯光稳定的地下车库效果还行光线均匀、地面颜色一致车开走之后背景恢复得很快。但遇到室外停车场就完全崩了——树影晃动、云层遮挡、早晚色温变化这些都会让背景模型跟着“漂移”几分钟之后它自己都不知道哪个是背景了。边缘检测加颜色特征的办法也试过主要思路是统计车位框内白色引导线的完整度。空车位的时候地面标线是连成一条的有车停进去之后标线会被车身打断同时出现大量不属于标线颜色的像素。这个思路在标准化的室内车位里偶尔能跑通但遇到车体颜色和地面接近的“白色车停白色线框”场景就失灵了更别说车身反光、地面污渍这些干扰因素。深度学习方案的优势在于它不需要人肉设计“什么叫有车”的特征而是直接从大量标注数据里学。尤其是YOLO系列出现之后模型体积、推理速度和检测精度之间取得了很好的平衡跑在边缘设备上也能做到实时。选深度学习的另外一个实际原因是可维护性传统方案的阈值参数散布在各种预处理函数里换一个停车场的摄像头光照条件变了得调半天参数深度学习模型虽然也需要微调但泛化能力明显强得多换场地后重新标注少量数据就能适配。1.3 检测方案的核心决策点全局检测还是区域分类技术路线定了之后还有一个必须想清楚的问题是输出粒度。我当时在“整图检测所有车辆再映射车位”和“只对每个固定车位区域做判断”之间反复权衡最后选了后者。这个决策不是我拍脑袋拍的三个原因第一个是稳定性。固定车位的多边形区域是人工标定的坐标精确且和业务编号绑定服务端可以直接查到“3号车位空着”这样结构化的结果。如果用车辆检测框去映射车位摄影师角度稍微一变或者车头朝向不同IoU计算就飘了。第二个是计算量。假设一个摄像头管20个车位区域分类方案只需要对20个小区域做推理判断而全局检测需要处理整张高清图。虽然单张图差异不大但多个摄像头同时接入的时候计算量的差距会被放大边缘设备压力明显不同。第三个是可解释性。车位状态判断错了区域分类方案可以直接把那个车位的裁剪图调出来看模型到底看到了什么车辆检测映射方案出了错很难定位是检测框的问题还是映射逻辑的问题。后面我还会详细讲这个排障思路它在真实项目里救了我很多次。2. 数据采集、标注规范与预处理细节2.1 数据集从哪里来怎么采最有效率训练数据永远是这类项目最头疼的部分。公开数据集我参考过一些通用的车辆检测数据集但它们大多是街景或行车记录仪视角和停车场摄像头的俯视斜视角差距很大直接拿来训练迁移效果很差。所以我的做法是自己在目标停车场采集原始视频然后抽帧标注。采集阶段有几个关键细节。第一是覆盖时段我连续采集了三天确保包含晴天、阴天、雨天、清晨、正午、傍晚、夜间各时段的画面。夜间的车灯反光、路灯不足造成的暗部盲区这些如果不进训练集上线必翻车。第二是覆盖状态既要拍车辆正常停放也要拍大量空车位和半遮挡状态——比如车头超出车位线压到旁边车位、行人路过挡住镜头、车辆临时停靠双闪等这些边缘情况才是模型精度的分水岭。抽帧不是均匀抽就行。监控视频一秒钟25帧早晚高峰车辆进出频繁均匀抽帧会得到大量重复的静止画面。我先用OpenCV做了简单的帧间差分析画面变化超过阈值的帧才保留然后再从中随机抽帧用于标注。这样同样的标注工作量样本的信息量能多出不少。另外一个很多人忽略的点是摄像头本身的参数。我用的摄像头鱼眼畸变比较明显车位在画面边缘会弯得很厉害。这就需要先做畸变矫正再抽帧标注否则标注框和实际车位多边形对不齐模型学习的时候特征本身就是歪的后面怎么调都白搭。2.2 标注规范决定了模型精度的上限标注质量对车位识别项目的影响比想象中大得多。我第一版训练集是自己用脚本半自动生成的结果模型训练完精度一直卡在85%左右上不去。后来复盘发现问题出在标注标签上——我只标了“occupied”和“empty”但实际车位区域里经常同时出现“车头已经进入车位、车身还在通道上”的中间状态这种状态被强行归到occupied还是empty都不对模型学到的边界就很模糊。后来我把标签体系改成三分类加一个辅助标签标签含义处理建议empty车位完全空置正常训练样本occupied车辆完整停在车位内正常训练样本partial车辆部分进入或部分遮挡车位训练时并入occupiedshadow树影/建筑阴影覆盖车位辅助标注增强阴影鲁棒性partial状态我一开始是单独建模的但后来发现服务端业务逻辑里partial大概率是“即将停入”或“正在驶出”短时间内状态还会变化。强行让模型预测中间态意义不大反而消耗样本量。所以我把它合并到occupied里但保留了这个标签的图片样本让模型见过更多遮挡形态。标注工具我用的是labelme多边形标注比矩形框更适合车位这种不规则区域。注意标注的是车位区域而不是车体这一点和常规目标检测不一样。框选车位的时候我要求标定到车位线的内边缘不要把线本身框进去因为线宽会随透视角度变化导致区域坐标不稳定。还有一个实操经验一个摄像头对应一套固定的车位多边形坐标。标注完第一次之后把坐标持久化保存到配置文件里后续每次推理都复用这套坐标不需要重新标注。换摄像头角度或者挪动摄像头位置才需要重新标定一遍。2.3 预处理透视矫正与ROI裁剪停车场的摄像头通常是立杆斜装画面里车道和车位都是透视变形的——车位看起来是梯形甚至不规则的四边形远处车位很小近处车位很大。直接拿这种图做区域分类模型需要自己学会尺度不变性这对小模型来说是很大的负担。我做的预处理分两步。第一步是透视矫正用车位区域的四个角点做透视变换把整个停车区投影成俯视平面图。矫正之后所有车位理论上都是近似相同的矩形模型只需要关注“这个区域里有没有车”这一个维度不需要同时应付尺度变化和透视形变训练难度明显下降。第二步是按标定的车位多边形裁剪ROI。推理的时候把矫正后的图中每个车位区域裁剪出来缩放到统一尺寸我用的是128x128再送入分类模型。这个尺寸是经过测试的再小会丢失车灯、后视镜等局部细节再大推理速度会受影响边缘设备上容易掉帧。有一点必须提醒透视矫正会拉伸图像远处的车位会被放大很多近处的车位被压缩插值算法会带来一定程度的模糊。我实测双线性插值比最近邻插值效果好很多虽然计算量稍微大一点但模型精度提升了2到3个百分点这点开销完全值得。3. 模型选型、训练策略与后处理逻辑3.1 模型选型小模型还是大模型轻量化的平衡模型选择上我对比过好几条路线。最初用Faster R-CNN做检测精度确实不错但在边缘设备上的推理速度只有几帧每秒完全达不到实时监控的要求。后来转向YOLO系列速度和精度都满意但发现自己把问题改成了“区域分类”之后杀鸡用牛刀了——每个车位只是一张小图不需要那么大感受野的检测头。最终我采用的是YOLOv8n作为特征提取骨干网络结构本身是个检测模型但我只保留它前几层的特征提取能力后面接了自定义的分类头。这样做的理由有两点一是YOLOv8n的权重在COCO上预训练过对车辆这种常规物体的底层特征已经学得很好了迁移到我的车位图上有现成的特征基础二是只分类不回归包围框省掉了anchor匹配和NMS的计算开销推理更快。如果你不想这么折腾直接用最朴素的ResNet18或MobileNetV3做分类也能跑通。区别在于通用分类网络对“车辆”的先验知识不如检测模型丰富如果训练数据不够多小模型的精度上限会低一些。从我实测来看在每类2000张左右的数据规模下YOLO特征分类头的方案比直接用MobileNetV3高大约4个点的F1差距还是比较明显的。3.2 训练策略数据增强、损失函数与超参数训练数据增强这一块我刚开始做得很保守只用了随机翻转和裁剪因为担心车位是固定视角的增强过度会让模型学到不存在的视角。后来实证下来翻转确实要慎用——左右翻转之后车位里的车头和车尾方向会颠倒如果训练集里两种方向都有且比例均衡翻转没问题但如果你的停车场是单行道车辆只能一个方向驶入那翻转就是灾难。我最终确定的增强组合是亮度扰动亮度系数随机在0.8到1.2之间变动模拟早中晚光照差异。对比度扰动对比度系数0.85到1.15主要为了让模型对阴影和反光不那么敏感。高斯噪声轻微噪声模拟摄像头传感器在高ISO下的颗粒感。随机遮挡在小图上随机挖掉一块模拟行人或邻车遮挡。损失函数方面二分类任务用交叉熵就够了但我加了标签平滑。标签平滑系数设0.05目的是防止模型对训练样本过于自信提升泛化能力。这个细节在最终测试里拉低了过拟合现象F1稳定了一些。训练超参数我是这么定的batch size 64初始学习率0.001用余弦退火调度总计训练60个epoch。优化器选AdamWweight decay设为1e-4。这些参数不是什么金科玉律但我测试下来在这个数据规模下很稳你可以作为起点再根据自己数据量调整。3.3 后端处理时序平滑才是真正能上线的关键模型输出单个车位的占用概率后直接拿这个概率当最终结果发布你会发现线上表现比测试集差很多。原因在于单帧误判是随机出现的直接展示会导致车位状态在“空”和“占用”之间疯狂跳变用户看着就是闪烁体验极差。我的做法是引入一个基于时间窗口的滑动平均。具体逻辑是维护每个车位最近10帧的预测概率取平均值作为当前帧的最终占用概率只有当平均值连续跨过阈值时才更新车位状态。阈值我设为0.7连续3帧平均概率大于0.7判定为占用小于0.3判定为空闲0.3到0.7之间保持上一状态不变。这个机制引入之后效果立竿见影。原本单帧偶尔出现的误判因为时序上不连续基本被滤掉了。代价是状态切换有大约1到2秒的延迟但对停车引导场景来说完全可接受。如果有车辆快速驶离状态更新滞后两三秒屏幕上多显示几秒“占用”不会造成严重后果。另外还有一个容易被忽略的后处理遮挡处理。当一辆车的车头伸到邻车位上或者行人从车位前走过模型的预测可能短暂波动。时序平滑能挡住大部分瞬时干扰但如果是持续的半遮挡比如一辆大SUV的车头一直压着旁边车位单纯靠时序平滑就没用了。我的补充策略是合并车位区域——如果两个相邻车位共享一条边且其中一个持续处于partial状态服务端把两个车位合并显示为“一个大会车位”避免用户看到“空位”开过去却发现停不进去的尴尬。4. 硬件选型、推理优化与部署方案4.1 边缘设备怎么选算力怎么分配部署方案我考虑过云端纯计算和边缘端本地推理两条路线。云端方案的优点是可以随时扩容算力缺点是带宽和延迟——停车场摄像头数量多持续推送高清画面到云端流量费是个不小的成本而且网络抖动会导致状态更新延迟。边缘端推理正好相反模型跑在摄像头旁边的计算盒子上只上报结构化结果一个车位占用的数据量不过几十字节带宽压力几乎为零。我最后用的是边缘端方案设备选的是带GPU的嵌入式工控机。选型标准很简单算力够跑我的模型而且推理延迟低于50毫秒功耗不能太大散热要能扛得住机房或者弱电箱的闷热环境。实测下来YOLOv8n骨干加分类头的模型在INT8量化之后单帧20个车位的推理总耗时大约是35毫秒稳定跑在25帧以上完全满足监控场景。多摄像头的算力分配也值得说一说。如果一台边缘设备接多路摄像头最稳妥的做法是分时复用GPU每路视频按顺序推理中间插入队列缓冲保证不丢帧。实测4路1080P视频接入时每路分配到大约6帧每秒的推理频率对车位状态监控这种低频变化的应用足够了。千万不要让各路并行跑满GPU温度一上来推理不稳定掉帧不说设备寿命也会受影响。4.2 模型压缩量化与剪枝的取舍模型压缩我只做了INT8量化没有做剪枝。量化的收益非常直接模型体积缩小将近4倍推理速度提升2到3倍而且只要校准集选得合适精度损失可以控制在1个百分点以内。剪枝的收益也大但调试成本很高需要反复验证剪枝后哪些层敏感、哪些层冗余对项目周期的压力比较大所以我没采用。量化的关键在校准数据集。TensorRT或ONNX Runtime的量化工具都支持校准集但我发现很多人随手拿验证集当校准集这是错误的。校准集应该从训练集里随机抽样并且要覆盖模型可能遇到的各种光照和遮挡情况。我用的是每类500张、总共1000张的训练子集量化后精度只掉了0.8个百分点后来部署到现场表现稳定。4.3 服务端对接与状态同步机制模型推理只是链路里的一环真正给客户交付的是车位状态数据。我把边缘端的输出定义为一个简单的JSON结构每个字段对应一个车位编号和状态通过HTTP或WebSocket推送到服务端。服务端再对接LED引导屏、小程序或APP接口。这里有一个同步机制的坑必须提边缘端设备断电重启后内部的时序平滑状态会清零模型恢复到空状态但它上报给服务端的还是重启前的数据。如果不做对账服务端会以为车位上还有车停着。我的解决办法是边缘端启动时先上报一条“全量状态”消息服务端收到后强制覆盖旧状态。同时每30秒做一次心跳如果心跳丢失服务端标记该摄像头离线引导屏显示该区域状态未知而不是显示错误的空位信息。5. 上线后的常见问题与排查技巧实录5.1 高频问题速查表运行了几个月之后我总结出下面这些最常遇到的问题附上排查思路和解决方案现象可能原因排查与解决同一个车位白天正常晚上频繁误判夜间光照不足暗部细节丢失检查是否开启了红外补光对夜间样本做针对性增强或单独训练夜间模型空车位显示占用且持续不恢复车位区域被长时间遮挡如邻车越线检查车位多边形标定是否被邻车车体占用合并相邻车位逻辑是否生效雨天车位状态随机跳变地面反光和水渍造成特征混乱增加雨天样本在预处理里加入去反光算法或用偏振镜硬件方案摄像头角度松动后全部误判透视矫正矩阵失效ROI偏移定期巡检物理摄像头状态做画面相似度检测画面突变时自动告警推理延迟越来越高边缘设备老化或系统日志膨胀清理系统日志重启服务检查是否有其他进程占用GPU显存5.2 实战调试心得如何快速定位是模型问题还是逻辑问题部署现场出问题时第一件事不是调模型而是先确认问题出在链路哪一段。我的排查顺序是这样先看边缘端原始画面的模型输出日志确认模型本身判没判错。如果模型输出是对的问题在后处理或通信层如果模型输出就是错的才需要回到模型和数据上找原因。举个例子有一次现场的5号车位一直显示占用但车早就开走了。我先调出5号车位的最近10帧裁剪图和模型原始概率发现模型概率一直在0.9以上说明模型确实认为有车。再看原图才发现是旁边SUV的车头一直压着5号车位。这就不是模型的问题而是车位空间被邻近车辆物理占用了合并车位的逻辑又因为概率没有回落到阈值以下没有触发。最后我把partial状态的判定阈值从0.7降到0.5合并逻辑提前介入问题就解决了。这套方法帮我避免了很多无效调参。模型出问题通常表现为随机误判、某个时段整体性能下降、特定车位稳定出错而后处理和通信问题通常表现为状态跳变无规律、重启后状态错乱、延迟攀升。先分类再定位效率会高很多。5.3 长期运行维护的几个小建议项目上线不代表结束长期维护才是真正考验工程能力的地方。第一个建议是给边缘设备加上看门狗机制。嵌入式设备常年运行偶尔会出现进程卡死或者显存泄漏看门狗能够自动重启服务避免现场出现长时间无人维护的真空期。第二个建议是保留每帧画面的缩略图存个几天就够。出问题的时候直接回看当时画面比对着日志猜要直观得多。注意控制缩略图的分辨率和压缩比一张图几十KB一天下来几百MB用环形存储滚动覆盖就行。第三个建议是模型要定期做增量微调。停车场环境不是一成不变的——新划线的车位、装了新的照明灯、旁边盖了楼导致阴影变化这些都可能让模型性能缓慢退化。我给自己定的节奏是每三个月收集一次现场的新数据人工筛选后加入训练集做一次小规模的增量训练每六个月做一次全面评估和模型替换。整体下来项目从上线到现在精度一直没有明显掉过。最后想分享一个我个人的体会车位识别这类项目算法模型的难度其实只占四成剩下六成是数据管理、设备运维和状态同步这些“不起眼”的工程问题。很多朋友一头扎进模型调参里出不来结果是被现场各种边缘情况反复打脸。如果你正在做类似的项目希望你从一开始就把视野放宽——把数据规范、设备监控、状态对账这些环节都当成一等公民来对待线上运行的时候你会感谢提前做的这些铺垫。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑