☰
停车场车位识别实战:从深度学习模型到工程化落地全攻略
2026/10/19 3:47:46 网站建设 项目流程

做停车场车位识别这个方向,前前后后我跟过三个不同场景的项目:某商业广场的负一层车库、某园区的露天停车场,还有一个商场楼顶的临时停车场。这三类场地加在一起,让我对“停车场车位识别”有了一个很深的体会:真正决定项目成败的,往往不是模型准确率小数点后两位的差距,而是你有没有把现场各种乱七八糟的情况提前想清楚。这篇文章我就把这几个项目里沉淀下来的方案选型、实现流程、踩坑记录和工程化经验一次性整理出来,给正在做或者准备做同类项目的朋友一个参考。

1. 车位识别真正要解决的不是“识别”,而是“全天候判定”

1.1 用户要的是“车位有没有车”,不是“画面里有没有车”

很多第一次接触车位识别的朋友,容易把这个问题理解成“用深度学习检测出车辆”,然后给每个车位打个标签。这个理解不算错,但离实际需求还有一段距离。业务方真正关心的是:某个车位现在能不能停?引导屏上那个绿点该不该亮?手机App里这个车位是不是显示为“空闲”?他们要的是车位维度的状态判定结果,而不是一张画满检测框的图。

这里面的区别很关键。目标检测模型输出的是“画面里有什么车、车在什么位置”,而车位识别需要的是“某个固定区域内是否被车辆占用”。后者是一个区域状态分类问题,不是通用目标检测问题。虽然检测模型也能通过计算检测框和车位区域的交并比来推算占用状态,但在实际工程里,直接对每个车位区域做二分类,往往更稳定、更快,也更省算力。这也是我后来在多个项目里最终采用的方案:先把每个车位在图像里的多边形区域固定下来,然后对区域内的图像内容做占用/空闲分类。

1.2 判断模糊的边界:什么样的状态算“占用”

“有没有车”听起来是一个非黑即白的问题,但到了真实停车场,边界情况多到你怀疑人生。最常见的是跨线停车:一辆车压着两个车位之间的线停,两个车位区域里都出现了车辆的一部分。这时候你判哪个车位被占用?如果只按“区域内是否有明显车辆轮廓”来判,可能出现两个车位同时显示占用,可实际上两个车位都停不了车——这倒也算合理。还有一种情况是半个车头探进车位,车身还在通道上,这种算占用还是算过路车辆?

我当时的处理逻辑是:只要车辆轮廓进入车位区域超过一定比例,就视为占用。这个比例需要根据车位大小和摄像头角度调整,一般在30%到50%之间。阈值设得太低,过路车辆一晃就会被误判占用;设得太高,小型车停进大车位时可能漏报。另外,电动自行车、三轮车、甚至购物手推车停进车位的情况也要提前和甲方确认口径:如果停车场允许非机动车进入,模型训练时就要把这类目标加进去;如果不允许,就要通过业务规则过滤掉。

1.3 识别结果给谁用,直接决定技术指标

同样一套识别系统,接不同的下游业务,技术指标要求完全不同。用于车位引导屏,状态刷新慢几秒没有关系,但绝对不能出现大面积闪烁,否则司机看着诱导牌一会儿绿一会儿红,体验极差。用于手机端车位预约,要求秒级更新,而且要尽量做到有车驶入后第一时间上报,方便其他用户看到准确状态。用于对接收费系统的联动记录,反而不能太“灵敏”:车辆只是暂时停在车位上等人,几分钟后就走,如果每次都生成一条完整的事件记录,会干扰计费逻辑。

所以我在项目启动后的第一件事,不是选模型,而是和甲方确认这三个问题:结果展示在哪里?状态变化多久需要反映出来?误报和漏报哪个更不能接受?这三个问题的答案直接决定了后续算法设计里的消抖策略、状态保持时间和上报逻辑。记住一句话:车位识别不是模型比赛,而是业务系统里的一个传感器。

2. 技术路线对比:视频方案的优势与传感器方案的兜底价值

2.1 三类常见方案的基本原理

停车场车位状态检测,市面上常见的方案主要有三大类:地磁传感器、超声波雷达和视频识别。地磁传感器埋在每个车位下方的地面里,车辆驶入后引起磁场变化,从而判断占用。超声波雷达一般装在车位上方或后方,通过测距判断有没有车。视频识别就是本文重点,用摄像头拍摄车位区域,再用算法分析图像。

三种方案各有适用场景。室内车库信号遮挡少,地磁和超声波都还稳定;露天停车场地磁维护成本高,因为要开挖地面、换电池;超声波雷达对安装高度和角度要求高,一个探头只能覆盖一个车道方向的车位。视频方案的好处是:摄像头可以复用安防监控系统,不需要在每个车位单独装设备,而且从画面里能直接看到现场情况,方便运维人员远程确认。我之前在某个园区项目里就遇到了这个问题:甲方原本装了一批地磁传感器,用了半年坏了将近三成,最后才决定在关键区域加装视频识别做补充。

2.2 视频方案里的两个分支:传统图像处理与深度学习

视频识别内部又可以分成两个路线。传统图像处理路线,比如背景差分、颜色统计、边缘检测,思路是先建立无车的背景模型,然后通过对比当前帧和背景帧的差异来判断是否有车。这个方案在光照稳定的地下车库还能用,但一到露天停车场就行不通:太阳角度变化、树影移动、雨后积水反光,都会让背景模型迅速失效。我在最早的项目里试过混合高斯背景建模,调试了将近两周,最后还是放弃了。

深度学习路线的核心思路,是用卷积神经网络学习“有车区域”和“无车区域”的图像特征。优势非常明显:适应复杂光照、抗阴影干扰、对车位线不完整的情况也有一定鲁棒性。缺点是前期需要采集数据、标注、训练模型,而且对算力有一定要求。不过现在边缘计算设备已经很成熟,跑一个轻量级分类模型完全够用,这点硬件成本相对于地磁设备的维护成本,反而更划算。

2.3 我的选型结论和真实理由

综合几个项目的经验,我最终的选型结论是:以视频深度学习识别为主,在个别特殊车位辅以地磁传感器兜底。这里的“特殊车位”指的是摄像头很难覆盖到的角落车位,或者经常被大型车辆遮挡视角的车位。地磁不需要每天维护,埋在地下也不怕风吹雨淋,作为补充手段是合适的。

选视频为主还有一层原因:停车场通常已经有一套安防监控系统,摄像头点位本身就存在。只要把车位识别算法部署在已有的视频流上,不需要额外布线,也不需要进场施工改造地面,项目周期能缩短很多。当然,前提是原有摄像头的安装位置和清晰度满足识别要求。如果原有摄像头装在太低的位置或者角度太偏,那该加装还是要加装。光照、角度、遮盖问题,永远是视频方案的命门,后面我会专门展开讲。

方案安装方式优点主要问题
地磁传感器埋入地面不受光照和视角影响,精度稳定施工破坏地面,电池需更换,故障排查困难
超声波雷达车位上方或后方成本较低,安装相对简单一个探头管一个车位,安装角度敏感
视频识别借用监控摄像头或加装相机可复用现有设备,能远程可视化确认,支持多车位同时检测受光照、遮挡、视角影响,需算法和算力投入

3. 识别流程的核心拆解:车位标定、状态分类与稳定化输出

3.1 车位区域标定:一次配置,长期使用

选定了视频方案,接下来第一步是车位标定。所谓标定,就是把图像里每个车位用多边形圈出来,并写上对应的车位编号。标定工作看起来简单,实际上直接影响后续所有识别结果。我当时用的做法是:在摄像头画面里逐个人工标注四个角点,保存成坐标文件,启动时加载到内存里。这里有两个细节需要特别注意。

第一,多边形一定要贴合车位线的内侧边缘,不要只框一个大概矩形。因为车位判定是针对区域内容的,如果框得太大,把旁边通道都包进来了,过路车辆会频繁触发误判;框得太小,车辆停进去后车头和车尾超出区域,模型看到的特征不完整。我一般会让多边形边缘比车位线内缩2到3个像素,这样车辆进入时特征变化最明显。

第二,标定时要对着车头方向思考。同一个车位,车头朝里和车头朝外停,摄像头看到的画面差异很大。如果停车场允许双向停车,最好在训练数据里都覆盖到。标定完成之后,每个车位区域会被单独裁剪出来,缩放成固定尺寸,比如224×224或者尺寸更小的128×128,再送入分类模型。这样整个识别流程就变成了:一个全景图里,按坐标裁剪出十几个小图,各自判断占用状态。计算量很小,十几路摄像头同时跑也没压力。

3.2 状态判定模型:输入、输出与推理逻辑

状态判定模型我用的方法是二分类卷积网络。输入是一张车位区域的裁剪图,输出是两个概率值:empty的概率和occupied的概率。实际判定时,取概率较大的那个作为当前帧的识别结果。这种设计比直接用目标检测模型更轻量,因为车位区域是固定的,不需要模型在全图里搜索目标,只需要聚焦在局部做精细分类。模型结构不用太复杂,轻量级网络完全能满足要求。我在某个露天停车场项目里,用了一个基于残差结构的轻量模型,输入128×128,单帧推理在普通CPU上也只有几十毫秒,准确率足够日常使用。

为什么不用目标检测?原因有两个。第一,目标检测模型输出的是全图的目标框,我还得额外计算每个框与车位区域的IoU,代码复杂度和调试成本都上去了。第二,当车位区域出现“半个车身”时,检测框和车位区域的重合比例会因为车的位置飘忽不定而产生抖动,导致状态在占用和空闲之间反复横跳。直接做区域分类可以学到“区域内有物体”这种更稳定的特征,对跨线停车、车头探入这类情况更鲁棒。

3.3 时间维度的稳定化:消抖动与状态保持

单帧识别结果不能直接拿去用,必须要做时间维度的稳定化处理。我在项目里用的是一种简单的“连续N帧确认”机制:只有当连续N帧都判定为同一状态时,才认为车位状态发生变化。N的取值需要平衡响应速度和稳定性,我一般取3到5。以每2秒一次的检测频率为例,5帧确认意味着状态变化会在6到10秒内反映出来,这个延迟对引导屏完全可接受,对手机端也不算太慢。

除了连续帧确认,我还会加一个“状态保持时间”逻辑:一旦车位从空闲变成占用,至少保持30秒不变;从占用变成空闲,至少保持1分钟不变。为什么释放要比占用保持更久?因为车辆驶离车位时,可能人还在车边走动、搬东西,车门开合会造成区域内的图像特征波动,如果立刻判为空闲,紧接着又判为占用,系统就会上报两次状态变化,容易把后端业务搞乱。实测下来,这个时间参数在露天停车场效果很好,尤其是傍晚光线变化快的时段,能明显减少误报。

3.4 代码层面的最小实现

这里给出一段简化后的识别循环示例,方便理解整个流程。实际项目中还涉及到状态去抖、异常恢复等逻辑,但核心思路就是下面这样:

import cv2 # 加载车位坐标,结构示例: # parking_spots = [{"id": "A001", "polygon": [(x1,y1), (x2,y2), ...]}, ...] parking_spots = load_parking_spots("spots.json") # 加载训练好的二分类模型 model = load_model("spot_classifier.onnx") cap = cv2.VideoCapture("rtsp://camera_ip/stream") # 设置相机自动曝光模式为固定,避免亮度突变引发误判 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25) while True: ret, frame = cap.read() if not ret: # 相机掉线重连逻辑 time.sleep(2) cap.open("rtsp://camera_ip/stream") continue for spot in parking_spots: # 根据标定多边形裁剪车位区域 mask = get_polygon_mask(frame.shape, spot["polygon"]) cropped = crop_by_mask(frame, mask) # 缩放并归一化 input_tensor = preprocess(cropped, size=(128, 128)) # 推理,得到占用概率 prob_occupied = model.predict(input_tensor) # 和上一帧结果做消抖 spot.update_state(prob_occupied, threshold=0.5) # 如果状态变化且满足连续N帧确认,进行上报 if spot.state_changed_and_confirmed(): report_state_change(spot["id"], spot.state) time.sleep(2)

这段代码展示的是最小闭环。需要注意,裁剪区域要稍微做边缘扩展,不要把车身的明暗边缘卡在裁剪边界上,否则不同车辆进出时,边缘像素变化会被模型当成关键特征,造成不稳定。

4. 最容易翻车的三类现场:光照突变、遮挡和摄像头角度

4.1 白天反光、夜晚车灯与逆光补偿

光照问题是我在所有项目里遇到的最大敌人,没有之一。露天停车场从早到晚太阳角度不断变化,车位区域里的阴影位置也在缓慢移动。上午还是空车位的地面阴影,下午就变成了一辆车的形状,如果模型没有见过足够多阴影样本,很容易把阴影误判为车辆。应对办法有两个:一是在训练数据里加入各个时段的阴影样本,二是把图像输入改成局部纹理特征更明显的表示方式,降低对色块的依赖。实际操作中,我还会在预处理阶段做一个轻量的对比度增强,让车辆轮廓更突出。

夜晚车灯是另一个容易忽视的问题。有些停车场夜间灯光昏暗,车辆进车位时开着大灯,近光灯直射车位区域,会把原本空车位照得一片白。这时候模型很容易把高光区域误判成车辆。我处理过的方案是:对摄像头开启背光补偿,同时调整曝光时间,避免高光溢出。另外在训练阶段,专门采集车灯朝内、朝外的样本,让模型明白“亮瞎眼不代表有车”。如果你用的是支持红外补光的摄像头,那夜间效果会稳很多,因为红外图像不受可见光影响,但这时模型训练数据也要换成红外图。

4.2 车辆遮挡、跨线停车与“半辆车”误判

遮挡问题在所有停车场都避免不了。大型SUV停在相邻车位,会把旁边小车位的半个车头挡住;通道里的过路车辆也会短暂穿过车位区域前方。模型面对被遮挡的局部车身,很容易给出不确定的判定。我的处理思路是扩大车位区域的可视范围:除了车位本身的多边形,另外再定义一个“关注区域”,把车头朝向的那一片通道也纳入裁剪范围。这样即使车身被部分遮挡,模型也能根据通道里多出来的那一截车头判断出车位被占用。

跨线停车更是家常便饭。有些司机技术不好,车轮压着线停,半个车在车位A,半个车在车位B。这时候两个车位的区域内部都有车辆特征。我的处理是:判定规则采用“存在即占用”,只要任一车位的占用概率超过阈值,就上报该车位占用。这样虽然看起来“两个车位都显示占用”不太美观,但至少不会出现“一个车位已被占,系统还显示空闲”这种更严重的错误。毕竟引导屏的关键职责,是别让用户白跑一趟。

4.3 安装角度不佳时,透视校正与区域重标定

摄像头的安装角度是决定识别难度上限的硬件因素。我见过一个老旧停车场的摄像头装在立柱上,高度只有2米左右,俯角很小,画面几乎平视。平视视角下,近处的车很大,远处的车很小,一个车位区域在不同距离下的透视变形非常严重,模型很难学到稳定特征。这种情况下的补救办法是做透视校正:在标定时选择四个参考点,把停车场地面映射成俯视图,然后统一裁剪车位。透视校正之后,远处和近处的车位区域在尺寸上更一致,分类模型的准确率能提升一大截。

但我也要提醒,透视校正不是万能的。图像拉伸之后,远处原本就很小的车位会变得模糊,信息损失反而更大。所以在条件允许时,最好还是调整摄像头本身:安装高度尽量在3米以上,俯角控制在30到60度之间,让车位区域在画面里占据足够大的像素面积。如果现场已经固定了摄像头,不能改,那就优先保证中间一排车位的识别质量,边缘角落的车位用其他传感器兜底。不要奢望一个摄像头把整个停车场都完美覆盖。

5. 数据和标注决定模型上限,训练细节决定实际精度

5.1 自采数据比公开数据集更管用

车位识别这个任务很特别:不同停车场的车位线颜色、地面材质、顶棚灯光、车辆类型分布都不同。公开数据集里那些国外停车场的样本,拿到国内老旧地库用,效果会打很大折扣。我的经验是,每个项目都要安排一次专门的现场数据采集。采集时覆盖全天时段:早中晚各拍一批,晴天雨天各拍一批,工作日和周末也要区分,因为不同时间段的车型密度差异很大。

数据量不用贪多。一个摄像头点位,每个车位区域的有效样本至少几百张就够启动训练了。关键在于覆盖度:同一个车位,至少要包含空闲、车辆完全停入、车辆半入、车辆即将驶离、阴影遮挡和灯光变化这几类典型场景。我习惯把全天视频流分段截帧,每隔几秒保存一帧,然后按车位裁剪,形成原始样本池。这样比人工拿着相机对着每个车位狂拍高效得多,而且场景覆盖更自然。

5.2 标注规则要统一边界情况

标注是很容易出内耗的环节。如果标注同学和算法同学对“占用”的理解不一致,训练出来的模型就会学到错误的东西。我在项目里制定的标注规范是这样的:只要车位区域内能够清晰辨认出车辆的任何一部分,包括车身、轮胎、车灯,就标注为占用;如果只有阴影、积水倒影、或者非车辆物体,标注为空闲。对于跨线车辆,只要某个车位区域内的车辆部分超过该区域面积的五分之一,就标为占用;低于这个比例,按空闲处理。

这个规范看上去简单,但执行起来有很多细节。比如一辆白色车反光很强,地面倒影在画面里非常清晰,模型可能把倒影误当成真车。规范的解决办法是,倒影像素不应作为“车辆部分”计算,标注时只以车身本体为准。再比如车位区域边线正好经过车轮,车轮有一半在区域内,这时候应该标记为占用。为了避免标注不一致,我建议做一轮“预标注”:先用一个初版模型跑一遍所有样本,标注人员只修正模型错的样本,这样能大大减少标注工作量,也更容易保持一致。

5.3 训练策略:难例挖掘与样本均衡

模型训练本身不需要特别高深的技术,关键在难例挖掘和样本均衡。车位识别的正负样本天然不均衡:一个车位的空闲时间远多于占用时间,如果直接拿全量样本训练,模型会倾向于把所有输入都判成空闲,因为这样loss最低。我处理时会对正负样本做重采样,让占用样本和空闲样本的比例保持在1比1到1比1.5之间,避免模型偷懒。

难例挖掘的意思是,训练第一版模型后,用它在全量样本上跑一遍,把预测错误的样本挑出来,额外做数据增强,比如随机亮度扰动、随机模糊、随机透视微调,然后混合到下一轮训练集里。经过两三轮难例挖掘,模型对光照突变和遮挡的鲁棒性会有明显提升。我在某个项目里,第一版模型在测试集上是97%的准确率,看着不错,但一上现场就原形毕露,各种错判。后来把夜间样本、逆光样本和半遮挡样本强化训练三轮之后,准确率才真正达到99%以上。所以别迷信测试集数字,现场反馈才是硬标准。

6. 工程化落地:从“识别准”到“用得稳”之间还有一堆事

6.1 现场算力与推理方案的取舍

算法跑通了,接下来要考虑部署硬件。一个停车场几十个车位,通常只需要一台边缘计算设备,就能同时接管所有摄像头流。我实际使用的配置是:CPU多核处理器加集成GPU的工控机,或者带NPU的小型开发板。轻量级分类模型在CPU上跑,每帧推理几十毫秒,整个停车场每2秒轮询一轮,完全跑得动。不需要上昂贵的独立显卡,那样只会增加功耗和散热压力,对车位识别这种低频小模型没有意义。

还有一个容易忽略的细节:检测频率不是越高越好。停车场车位状态本来就是缓变信号,车辆停入或驶离至少需要十几秒。把检测频率从2秒一次提到200毫秒一次,准确率不会提升,反而会增加设备功耗和后端消息量。我在项目里一般会把每路摄像头的处理间隔设置成2到3秒,夜间甚至可以拉到5秒,既省电又降低对后端业务系统的压力。

6.2 相机掉线、程序重启与断网自恢复

工程化项目里,程序崩溃和相机掉线是常态,不能指望现场人员随时重启服务。所以我在部署时一定会加三样东西:进程守护、相机重连、数据缓存。进程守护用一个简单的看门狗脚本,检测识别程序是否还在跑,如果异常退出则自动拉起。相机重连在代码里做,检测到读取视频流失败后,定时重新尝试连接,连续重试次数超过一定阈值就发出告警消息。数据缓存则是为了保证断网期间的状态变化不丢失:先把状态写进本地存储,网络恢复后再把积压的数据补报到后端。

有人会觉得这些功能可有可无,但我亲历过一个停车场项目,因为现场交换机端口松动,一路摄像头频繁掉线,告警短信铺天盖地,甲方运维半夜打电话来质问。后来加了重连机制和告警熔断,问题才算平息。做项目,算法能力只是一部分,“稳定”才是甲方真正付钱买的东西。

6.3 状态联动:诱导屏、手机端与收费系统怎么对接

车位识别的下游对接,是整个系统里最考验沟通能力的地方。诱导屏刷新最简单,后端每隔一段时间推一次全量车位状态即可,通常刷新周期5到10秒。手机端则需要推送状态变化事件:车位从空闲变占用,或者从占用变空闲,都要实时推送给正在寻找车位的用户。收费系统联动反而要谨慎,因为计费逻辑里,“车辆进入车位”和“车辆驶离车位”这两个事件必须准确成对出现,任何一次误报都会导致计费异常。

我建议的设计是:识别算法只负责输出“车位状态变化事件”,具体业务判断全部由后端完成。比如某车位报告占用后5分钟内又报告空闲,这种短时变化可以标记为“疑似过路车辆”,不直接触发计费。后端还可以把同一车位的连续状态变化做持久化,方便甲方事后回看当天每个车位被占用了多少次、平均占用时长是多少。这些数据对停车场运营者来说,价值和车位识别本身一样大。

说实话,做到这一步,车位识别项目才算真正闭环。很多团队把模型准确率做到99%就觉得万事大吉,结果上现场三天两头出问题,最后被甲方质疑算法水平。根据我踩过的坑,一个可靠的停车场车位识别系统,70%的功夫在算法之外:现场勘察、摄像头调试、数据采集、异常恢复、业务联动,每一项都比堆模型参数更影响最终体验。如果让我再启动一个同类项目,我会先把摄像头安装规范写进施工交底里,因为后期99%的识别问题,根源都出在视角和光照上。希望这篇分享能帮你在自己的项目里少走几段弯路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询