基于视觉测距的加油站智能停车引导系统实战解析

发布时间:2026/10/17 16:28:19
基于视觉测距的加油站智能停车引导系统实战解析 在加油站待过的人都知道加油停车这事看起来简单实际上门道不少。油枪管线就那么长停太远了够不着来回挪车耽误时间停太近了又怕蹭到加油机机基座或者前面的车。尤其是早晚高峰好几辆车排队进站驾驶员一边看油枪位置一边瞄后视镜几头兼顾经常是车停歪了、距离不对工作人员扯着嗓子指挥效率低不说碰上新车手更容易出岔子。我这次做的小项目就是专门冲着这个问题去的用摄像头实时测车距判断车辆有没有停在安全范围内再把引导位置、停车距离一并用画面和声音告诉驾驶员相当于给加油站配了一个不需要人肉指挥的自动引导员。这套系统适合想用视觉方案做停车辅助的开发者参考也适合加油站管理者了解智能安全停车的落地思路。1. 项目整体设计与需求拆解1.1 加油站停车为什么需要“自动引导”先说场景的特殊性。加油站不像普通停车场停车位不是简简单单画个框就完事它需要满足几个硬性条件车辆必须停在加油岛两侧的指定区域车头方向要跟加油机对齐车身距离加油机不能太近也不能太远。这个“安全距离”不是随便定的——近了车辆进出的时候容易蹭到加油机基座、防撞柱万一加油过程中驾驶员误操作还会拉拽油枪远了油枪软管不够长加油员必须费力拽着管子管线磨损也会加剧。实际运营中很多司机对距离没有直观感知总觉得“差不多就行”结果就是要么贴太近、要么歪七扭八。我还见过比较极端的案例有的司机停得太近车门一开直接撞上加油机外壳维修成本虽然不高但现场处理起来既耽误后面排队车辆又影响站内秩序。另一个痛点在于指挥成本。传统做法是加油员站在车侧用口令指挥高峰期一个员工同时看几台车嗓子喊哑了还可能因为司机听不清导致反复调整。再加上夜间、雨天视线差人工指挥可靠性进一步下降。所以项目的第一诉求很明确让设备替人“看距离”并且把结果以最直观的方式呈现给驾驶员减少人为判断的不确定性。1.2 核心功能需求拆解我把需求拆成四块实时测距系统要能连续检测进入加油位的车辆并计算车辆前端或驾驶侧到基准线比如加油机前端或者防撞柱的距离。状态判定将距离换算成“停车过远、停车合适、停车过近”三档状态合适状态要有一个可调整的容忍区间。引导输出在显示屏上给出文字提示和箭头示意同时用语音模块播报“请向前行驶”“请向后倒车”“停车位置正确”让驾驶员不用下车也能听懂。记录与扩展保存每次加油车辆的距离数据和时间为后续运营分析留口子。这四个功能里最难啃的是第一条——实时测距。测距搞定了后面全是逻辑问题。但就算测距本身也不是买个传感器往那一装就完事它牵扯到安装位置、环境干扰、数据稳定性每一步都得实打实调试。1.3 传感器方案怎么选测距这件事可选的路子不少但放到加油站这个具体环境里每条路都有它的脾气。超声波方案成本最低模块十几块钱就能买到直接读时间差算距离原理简单。但超声波的测量范围通常只有几米而且锥角有限只能测正前方的一个点。车辆是大的平面目标一个点测出来只能代表局部车歪没歪根本不知道。加油站里车来车往发动机噪声、超声波在金属表面多次反射都会造成数据跳变。另外还有一个要命的问题超声波的响应速度一般在几十毫秒级车辆如果缓慢滑行数据可能还行但稍微快一点就容易丢帧或者跳变。它适合做近距离辅助传感器不适合作为主测距手段。红外 / ToF 方案精度很高测距范围可以到几米甚至十几米测量速度也快。但同样存在“单点测量”的问题只能覆盖一个位置想要覆盖整个加油位宽度得装好几组成本一下就上去了。而且ToF在户外强光下的表现并不尽如人意阳光里红外成分非常丰富容易淹没主动发射的信号导致测距结果忽远忽近。我曾在正午的加油站测试过一款ToF模块数据漂移量能到三四十厘米基本没法直接用。视觉方案用摄像头看整个加油位一张画面里同时有车、有地面标线、有加油机。通过标定可以把图像坐标换算成实际距离不仅能测距还能看车身姿态、判断车辆是否歪斜。单个摄像头覆盖范围大硬件的综合成本可控。缺点是计算量比前两个方案大对环境光敏感需要花心思在图像处理上。但整体来说它的“信息密度”是其他方案完全比不了的。同一套画面既能拿来测距又能拿来判断有没有车、有没有人、地面有没有异常扩展性非常强。我最后的结论很明确主测距用视觉必要时用超声波做近距辅助冗余。这个组合对故障成本、维护难度、功能完整性来说是最平衡的。下面重点讲讲视觉方案怎么落地。2. 视觉测距的原理与关键步骤2.1 先解决“图像里怎么量距离”摄像头拍到的画面是透视图像近大远小。想直接从像素坐标算实际距离必须先做一个坐标变换把图像投影到一个平面上变成俯视图。这就是透视变换OpenCV里对应的是getPerspectiveTransform和warpPerspective。具体做法分两步第一步标定。在加油位地面上选四个已知坐标的点比如地面砖缝的交点、标线端点量出它们的实际相对位置X方向间距、Y方向间距同时记录这四个点在图像里的像素坐标。第二步计算变换矩阵。把图像中任意一个像素映射到俯视图中的坐标再结合已知的比例尺就能换算出实际距离。标定这一步是整个系统能不能精准工作的命门。我试过图省事直接拍一张正对加油位的照片随便标四个点就完事结果换出来的俯视图变形很严重远端的距离误差能到几十厘米。后来老老实实按规范来在地面上用卷尺拉好网格选尽可能大的标定区域四角尽量铺满整个加油位的可视范围再记录坐标。这样做完之后整个视场的测距误差基本控制在正负5厘米以内这是后续“安全距离提醒”所有逻辑能站得住脚的基础。这里有一个非常关键的细节透视变换虽然是四个点就能求出矩阵但选点不是随便选的。四个点必须是一个矩形区域的对角顶点而且尽量覆盖实际感兴趣地带的边缘。如果你只标定了车辆停放区域的一部分那么超出标定范围的区域坐标外推时会严重失真。我建议标定区域至少要比最大的目标停车区再向外扩半米留出余量。2.2 车辆识别传统图像处理还是深度学习有了俯视图和坐标换算接下来要回答一个问题怎么知道车在画面里哪个位置两种主流做法。一种是传统图像处理背景差分、帧间差分、边缘检测。加油站的地面一般是静态的用混合高斯背景建模或者简单的背景差分就能把进来车辆的前景轮廓抠出来。好处是计算量小部署简单不依赖大量标注数据坏处是对光照非常敏感树影摇动、灯光强度变化都会导致前景提取一大堆杂点。我在测试时就遇到过比较尴尬的情况傍晚的时候车的影子被拉得特别长背景差分结果直接把影子当成车辆的一部分算出来的“车辆前端”比真实位置偏出去一米多。另一种是深度学习目标检测用YOLO这类模型检测“车辆”类别输出每个目标的位置框。好处是鲁棒性好车在画面里不管什么角度、什么光照基本都能框出来坏处是依赖标注数据模型推理对硬件有要求在边缘设备上跑还要做模型压缩和量化。我的实际选择是主检测用轻量化的YOLO变体比如YOLOv5n或者YOLOv8n在嵌入式板子或者小主机上跑CPU推理帧率能达到10到15帧足够了。配合一个简单的背景差分支路用于检测车辆是否停留在加油位——因为检测模型如果偶尔漏检背景分支还能兜底。两条支路结果做融合再取车辆目标框的底边中点作为车辆前端的近似位置。这里有个细节要提醒车辆目标框直接拿来做距离计算是不行的。目标检测框是外接矩形包含了车顶、车尾等大量信息底边位置跟车辆前端并不严格对应。要从框里进一步提取车辆前端的实际位置常用方法是结合车身底部阴影或者车底轮廓的边缘点来修正。这个修正哪怕只做二十厘米范围的变化也能明显减少最终距离展示的跳变。我自己的做法是从检测框的底边附近取一小块ROI在灰度图上找最低亮度行的位置把这个亮度跳变点当作车辆真正的前沿。实测下来修正后的距离值比直接用检测框稳定得多不会出现车辆刚进画面时距离值突然跳一大截的情况。2.3 安全距离的三级判定逻辑测距数据拿到后判定逻辑我用了一个三级分区停车过远车辆前端到基准线的距离大于安全上限比如1.8米提示向前行驶。停车合适距离落在安全区间比如1.0米到1.8米提示停车位置正确。停车过近距离小于安全下限比如1.0米提示向后倒车。具体阈值可以按油枪软管长度、加油机基座位置灵活调整做成配置文件不需要改代码。三级判定看起来简单但工程上真正要处理的是窗口时间和迟滞。车辆是移动的距离数据来回抖动如果不加迟滞显示器会在“过近”“合适”之间来回闪驾驶员看着更糊涂。我的做法是加上约0.5秒的去抖延时并且判定状态变化需要连续N帧满足条件才切换。这样体验会稳定很多。同时引导输出不只是文字。我在显示画面上用箭头指示方向并且用颜色区分状态红色表示过近、绿色表示合适、蓝色或橙色表示过远。语音模块只在状态切换的时候播报一次避免重复提示。这些都是交互层面的小细节但对实际落地效果影响非常大。我调试的时候关掉语音只保留文字驾驶员反馈说“看不太明白”加上语音和颜色之后基本不用培训就能看懂。3. 实操搭建从硬件到软件3.1 硬件清单与安装位置我的硬件选型兼顾成本、稳定性和后续维护组件选型建议说明摄像头普通USB广角摄像头1080p、30帧广角能覆盖整个加油位1080p保证远处车牌和轮廓还能看清主机小型边缘计算盒子ARM架构CPU推理YOLOv8n能有10帧以上功耗低适合7x24小时运行显示器户外高亮液晶屏或普通屏加遮阳罩14到21寸放在加油机旁立杆上高度约1.5米让驾驶员在驾驶位上直接能看到语音模块带功放的串口语音播报模块可预置语音通过GPIO或串口命令触发播放辅助传感器一到两个超声波模块可选装在防撞柱侧用于近距冗余检测防止视觉在极端强光下失效安装调试时我踩过一个坑摄像头如果装在加油机正上方会被油枪管线、加油机顶棚的阴影干扰画面里还容易把加油机本身当成目标物。后来把安装位置挪到加油位侧前方的立柱上让加油机本体大部分移出画面或者处于画面边缘检测率明显提升。安装完成后要做一次新的透视变换标定位置一动之前的标定数据全部作废这个必须记住。3.2 软件架构与处理流程整个软件流程是摄像头采集一帧。缩放、去畸变、透视变换成俯视图。目标检测得到车辆框背景差分得到运动区域两者融合成车辆前端位置。计算车辆前端到基准线的实际距离。三级判定加上迟滞逻辑。更新显示画面和语音播报。主程序我用的Python写的推理部分用的是OpenCV的DNN模块加载ONNX格式模型避免引入太多重型依赖。整体跑下来在边缘盒子上CPU占用率在50%左右稳定工作没有问题。如果后续想上更大模型或者更高帧率可以考虑在板子上加一颗NPU比如有些边缘盒子自带算力单元能把推理时间从几十毫秒降到十几毫秒体验会更好。3.3 关键实现细节这里放几段关键逻辑的实现思路方便你照着自己的场景改透视变换标定在地面上测量四个基准点的实际坐标比如 (0,0)、(2.0,0)、(0,3.0)、(2.0,3.0)单位米。从图像中点击提取这四个点的像素坐标。调用cv2.getPerspectiveTransform生成矩阵 M。以后每一帧用cv2.warpPerspective生成俯视图尺寸设定为与实际区域等比比如 800x600 像素对应 3 米的区域比例尺就是 800/3.0 像素每米。车辆前端距离计算从检测框取底边中点映射到俯视图坐标。考虑到检测框底边与车辆前端不完全对齐用一个偏移量修正比如减去0.3米具体值根据实测标定。用修正后的点计算到基准线的垂直距离。迟滞判定维护当前状态和连续帧计数。如果第 t 帧的距离落在“合适”区间但上一帧是“过远”不立即切换判断连续满足条件超过5帧再切换状态。每帧只更新一次显示画面语音只在状态切换瞬间触发。工程上还有一个很小的点容易被忽略画面显示。我原本直接输出OpenCV窗口但现场设备是带触控的屏幕、没有桌面环境最终改成把结果渲染成一张RGB图像再写入framebuffer或者用轻量级显示服务输出。这样省掉了窗口管理的开销也不会因为系统桌面崩掉而白屏。3.4 系统长时间运行的稳定性加油站设备是7x24小时运行的需要考虑几个可靠性问题。第一是开机自启和看门狗主程序写成一个systemd服务崩溃后自动重启。如果是裸机环境可以加一个外部看门狗电路定期喂狗程序卡死就自动断电重启。第二是存储日志写到SD卡会写坏卡改成轮转日志加上定期清理画面数据不落盘只保留距离记录文本。我见过有人把检测框截图一直存着结果一个月后存储满了系统直接卡死这个很常见但要非常小心。第三是温度户外高温环境要选工业级板子或者做好被动散热外壳上开散热孔。正午暴晒下外壳温度能到70度不开孔的主板撑不过一个夏天。如果安装地点的太阳直射比较厉害最好加一个遮阳板既保护设备又减少镜头眩光。4. 部署调试中的常见问题与排查技巧4.1 光照变化导致的误检这是视觉方案的天敌。白天树影、傍晚低角度阳光、夜间车灯强光都会让背景差分结果出现大面积噪声也会干扰深度学习模型的输入画质。我的处理思路是多管齐下对输入图像先做直方图均衡化或者自适应伽马校正抵消一部分光照变化。背景差分模型采用带学习率的自适应更新同时设置前景面积阈值把太小的连通域直接过滤。在模型推理的输入尺寸上做归一化处理避免不同亮度导致检测框抖动。最关键的一个办法放宽检测到“确定有车”的置信度阈值比如0.4以保证有车时尽量别漏检再用判定逻辑兜底如果连续多帧都检测不到车才认为车位空着。还有一个实操层面的建议把摄像头的曝光时间固定住不要用自动曝光。加油站的光线变化虽然快但固定曝光配合软件层面的亮度校正比自动曝光来回调整导致的亮度突变要好处理得多。我在调试时就发现自动曝光在黄昏时刻会在明暗之间反复切换直接导致检测框大小跳变距离值跟着一起抖。4.2 多车辆同时进入场景一个加油位旁边可能同时排着两三辆车目标检测能把它们都框出来但引导逻辑该听谁的我的做法是设定一个“关注区域”只有车辆框底边中点位于这个区域内的车辆才参与判定区域外的一概忽略。关注区域就是停车位前方的矩形范围通过配置文件设定。这样就算别的车乱入画面也不会把引导提示带跑偏。这个“关注区域”设计成矩形框就行不用太精细。如果加油位是斜列式的可以做成多边形区域反正代码里就是判断一个点是否在区域内很轻量。需要注意的是区域一定要比实际停车位略大否则车稍微停歪一点就出了区域系统反而判定“无车”这就很尴尬。4.3 摄像头角度与畸变问题广角镜头拍出来的画面边缘畸变很严重直接做透视变换会导致远端距离误差偏大。解决方法是先做镜头畸变校正用棋盘格标定得到畸变系数然后再做透视变换。两步都做完后远端误差能从十几厘米降到五厘米以内。畸变校正代码就是OpenCV标准的calibrateCamera流程素材拍十五到二十张不同角度的棋盘格照片就够了。有一个容易忽略的环节镜头外参数也会影响畸变校正结果。摄像头安装之后最好用胶带把镜头对焦环固定住防止有人误碰导致画面变模糊。加油站现场人员流动大设备经常被擦洗、碰动装好后要定期巡检画面是否清晰、位置有没有偏移。4.4 判定逻辑容易被忽略的边界场景三级判定逻辑表面上简单但有几个边界场景必须处理车辆长时间不动如果一辆车停在原地超过30秒背景差分会把车慢慢“吸收”进背景。这时候主要靠YOLO的持续检测来判断有车背景差分的结果要降权或者直接忽略。我的策略是一旦检测到车辆进入关注区域在车辆离开前背景差分就不参与“是否有车”的判断只用于辅助提取前端位置。车辆中途改方向比如倒车入库的车先正向进画面、再倒向加油位。这时候检测框的朝向会变前端位置的提取逻辑要能跟着变。简化做法是只取检测框底边中点不关心车头朝向但在斜向停车位布局里误差会变大。如果有条件可以用“车底阴影”来辅助定位阴影方向不受车头朝向影响相对稳定。距离值突然跳变绝大多数是因为车辆目标框在帧间发生了跳变。排查思路先看目标检测结果稳不稳定再看畸变校正和透视变换矩阵有没有出问题最后看车速是否过快导致两帧之间移动量本来就大。4.5 实测效果与体验优化装完第一版之后我在现场跑了一周记录了几组典型数据。白天光线良好的情况下从车辆进入关注区域到稳定输出引导提示大概需要1到2秒这个延迟主要来自目标检测的推理时间和去抖逻辑。夜晚光线复杂的情况下检测置信度会有所下降但因为有背景差分兜底基本能维持正常判定。用户反馈比较集中的是两个问题一个是“提示太聒噪”车一进区域就开始播报有时候只是借道路过也会被提示。解决办法是把语音改成只在状态切换时播报并且增加一个短时间的静默窗口比如车辆刚进入区域的前5秒不播报避免误打扰。另一个是“停车位置拿不准”光看提示不知道到底要停在哪个位置。我在画面上加了一条绿色引导带把“合适区间”对应的地面范围直接投影到俯视图上驾驶员能看到自己车头要进入哪个区域直观很多。这个引导带其实就是把两个矩形框画在俯视图上再用逆透视变换映射回原画面代码量不大但效果非常明显。最后再分享一个实用小技巧整套系统调试完之后我留下一个习惯把每次现场调试的画面截图和距离数据都存下来每天翻一遍。不是为了看过程而是为了积累样本。一开始模型的漏检和误检只能靠拍脑袋调整后来数据攒多了把典型问题样本挑出来补齐模型训练集再重新训练一轮轻量模型误检率下降得很快。如果你也准备做类似的项目我建议也把这个“数据回收闭环”跑起来它比事后反复调参数有效得多。个人最深的体会是方案选型上不要贪多求全把一项技术做实比罗列一堆功能有用得多。视觉测距这一个点背后牵扯到标定精度、目标检测鲁棒性、实时状态机设计、硬件散热、现场安装角度每一环都决定最终体验。最初我以为难点在深度学习模型做下来才发现真正拉开稳定性差距的往往是标定和迟滞逻辑这些“细节中的细节”。如果你也准备做类似的项目我建议先花一两天时间把现场场景观察透、把基准距离和现场工作人员沟通清楚再动手写代码。方向对了后面全是体力活。