ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLOv8停车位检测实战:从数据集构建到训练部署全流程

YOLOv8停车位检测实战:从数据集构建到训练部署全流程 简介本资源是面向计算机视觉初学者与智能交通应用开发者的停车位目标检测专用数据集基于YOLOv8框架构建适用于停车场自动化管理、车位状态识别等实际场景的模型训练与验证。数据集共1520张真实停车场图像含延时摄影、多角度监控画面经标准化预处理自动EXIF定向校正、统一缩放至640×640分辨率并通过水平/垂直翻转、±15°随机旋转、亮度扰动、高斯模糊及椒盐噪声增强为每张原图生成3个增强样本显著提升模型鲁棒性。压缩包含2000个文件主体为1520个YOLOv8格式txt标注文件、479张jpg图像含原始与增强样本及1个结构清晰的data.yaml配置文件总大小164.36MB目录组织规范开箱即用于YOLOv8训练流程。目前已有162人学习下载可直接支撑从数据加载、模型训练到推理部署的完整实践闭环。 我刚把YOLOv8项目从通用检测切到停车位检测时一个很强烈的感受是网上现成的停车位检测数据集不少但真能拿来训练出可靠模型的并不多。很多所谓公开数据集要么是在同一场景里连拍的照片样本多样性严重不足要么标注风格五花八门——有人标车位线框有人标空位/占用位还有人把整辆车的矩形框也算一份。这篇内容就围绕我实际跑通的一条路线来写从数据集的选型、自建标注到YOLOv8训练、踩坑排查再到最后导出部署。目标读者是手里已经跑过基础目标检测、但对停车位这种细分场景还不太有把握的人。1. 停车位检测到底难在哪不是框一个车位这么简单1.1 两个容易搞混的子任务车位线检测和空位检测先说一个非常容易踩的坑。停车位检测在真实项目里通常会分化成两个任务一个是车位线检测模型要去框出画面里所有有标线的车位区域另一个是空位检测模型需要在框出车位的同时判断这个车位当前是空着还是被占用。这两个任务对标注的要求完全不同。如果只做车位线检测一张图里标一个类别就行但如果你最终要输出的是哪个车位能停那就必须把每个车位的状态标成两个类别。我见过有人在同一个类里既标空位又标占用训练出来的模型在实拍画面里频繁把空位后面露出的一截车轮误判成占用原因就是标注阶段没做类别区分。所以在做数据集之前先想清楚你的业务到底需要哪个结果。1.2 通用目标检测模型为什么在停车场里容易失灵很多人拿YOLOv8默认的COCO预训练权重去停车场实拍画面直接测试结果往往是一堆漏检和误检。这不是YOLOv8不行而是停车位场景有几个通用检测不常遇到的硬伤标线退化国内很多停车场的白色标线磨损非常严重尤其露天停车场日晒雨淋之后标线边缘模糊到人眼都要仔细辨认模型自然更容易漏检。这是停车位检测最大的现实敌人。视角问题通用检测模型训练数据大多是平视或稍微俯视的画面而停车位监控摄像头通常是高杆俯拍或者干脆是无人机视角。视角一变特征分布就变了泛化能力立刻下降。小目标占比高从高处俯拍时单个车位在1080p画面里的尺寸往往只有几十个像素接近小目标检测的范畴。YOLOv8的默认检测头对小目标本来就偏弱更别提很多开源数据集用的是720p甚至更低分辨率。光照跨度大地下车库的荧光灯、地面停车场的正午强光、傍晚逆光光照条件变化范围极大。只靠数据增强里的HSV抖动很难模拟出真实的极端光照。这些问题单靠调参解决不了源头还是在数据上。2. 数据集从哪来开源、合成、自建三条路怎么选2.1 开源数据集横向对比PKLot、CNRPark-EXT、ACM我在做这个项目时把几个用得比较多的公开数据集挨个试了一遍简单列个表方便你选型。数据集场景规模/特点适合做什么PKLot巴西两个露天停车场12000张图像包含晴天/阴天/雨天标注露天场景的空位分类光照变化丰富CNRPark-EXT欧洲某园区停车场超过24小时连续采集带空/占用标注做时序推理、模拟真实监控流ACM航拍视角停车场无人机俯拍分辨率较高做航拍场景的车位检测训练自建你的实际部署场地数量可控质量可控最终落地效果通常最好以上设计表要加点实际使用结论。PKLot的样本确实多但是两个停车场的固定机位场景其实比较单调而且图像分辨率不高训练出来的模型换个停车场就掉点。CNRPark-EXT更适合做验证不适合做主力训练数据。ACM的航拍视角很好但每张图的车位太多标注密集程度高如果只是几百个样本起步训练成本也不低。2.2 自建数据集的采集要点角度、时段、反复拍摄如果你希望最终部署在某个具体停车场我强烈建议花一到两周时间去采集自建数据集。这样做的好处是模型见到的就是部署时要见到的画面从源头上消除域差异。采集时注意三点机位固定后不要来回挪。停车场监控角度通常固定采集时也尽量固定机位让模型学习这个固定视野下车位长什么样而不是学习各种透视变形。覆盖不同时段和天气。至少要拍一组大晴天正午、一组阴天、一组晚上灯光开启、一组清晨低照度的样本。如果条件允许雨天也拍一组雨天地面反光对特征干扰非常大。每一处标线磨损的车位都要拍。这是很多人漏掉的——只拍清晰标线导致模型在真实场景里遇到模糊标线直接歇菜。我在标注时会把标线模糊但仍可辨认的车位单独分组训练时对这些样本做额外增强效果提升很显著。2.3 标注规范用什么工具、怎么设计类别标注工具我推荐用LabelImg或者LabelStudio。LabelImg轻量、和YOLO格式无缝衔接适合快速框标注LabelStudio适合团队协作但上手稍微复杂一点。两者都支持输出YOLO txt格式后面省去转换步骤。类别设计上如果你的目标是最小可行产品建议直接用两个类0: empty空车位1: occupied占用车位这样模型在推理时天然输出每个车位的状态不用再额外写判断逻辑。你可能会问那要不要单独设一个background或者line类我的经验是不要。YOLOv8本身会对无目标的区域做背景判定额外加一个line类反而会干扰目标框的回归尤其当车位线与相邻车位有重叠时。另外有一个很关键的原则不要框进车位的全部物理区域。停车位的矩形框在画面里经常被停着的车辆遮挡一部分如果框把车也包进去模型会学到车位区域包括了车身侧面在空位检测时反而容易把后车的一角算进来。我的做法是框只圈标线内侧的可停车区域即使这样会导致某些标注框与车体重叠也比包住整车要稳。3. YOLOv8训练前的数据组织与关键配置3.1 数据集目录结构和格式转换YOLOv8对数据集的目录要求比较固定但也足够灵活。我习惯的目录结构是dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── parking.yamlimages里放图片labels里放同名的txt标注文件。每个txt文件按YOLO格式逐行写class x_center y_center width height其中坐标值是相对图片宽高的归一化小数。如果你用LabelImg导出的是VOC XML格式需要先做一次转换脚本网上很多但注意一定不要用绝对路径拼接图片路径尽量处理成相对路径后面换机器训练才不会出问题。train和val的划分要注意按停车场场景切分不要按文件随机切分。如果你把同一个机位拍到的连续帧既放train又放val模型的mAP会虚高到接近1.0但换到新场景立刻打回原形。我一般按不同天拍摄的批次来切保证验证集里的画面是模型没见过的。3.2 data.yaml 正确写法与几个易错点配置文件内容不复杂容易错的是路径和类别名path: ./dataset train: images/train val: images/val nc: 2 names: 0: empty 1: occupied易错点有这么几个path如果写成相对路径注意它相对于你执行trian命令的工作目录而不是yaml文件所在目录。放错位置会报找不到图片排查起来很闹心。nc必须与names的个数一致否则训练直接报错。这个很粗暴但报错信息也很清楚。如果有两个类names是0和1不要写成1和2。训练时会自动从0开始。3.3 模型选型为什么最终选了yolov8s而不是n或m很多教程上来就让人用yolov8s但没有解释为什么。这里说一下我的横向测试结果。显卡是GTX 1660 Ti6GB显存这个约束条件直接决定了选择范围。模型参数量显存占用batch16, imgsz640训练耗时/epoch约1000张图实测mAP50yolov8n3.2M约2.5GB约30s0.86yolov8s11.2M约4.8GB约55s0.92yolov8m25.9M溢出或需要降batch--我最终选yolov8s因为n在标线模糊的车位上漏检率明显要高而m在6GB卡上得把batch降到4左右才能跑训练时间翻倍收益却不明显。如果你想在CPU上跑那只能用n但说实话CPU训练这种数据集太折磨了。有一点要说清楚预训练权重非常有用不要随机初始化从零训练。用YOLOv8在COCO上的官方权重作为起点即便COCO里根本没有停车位这个类别模型也已经学好了通用的边缘、纹理、形状特征迁移到停车位任务能少花大量迭代。命令里直接指定modelyolov8s.pt即可ultralytics会自动下载。4. GTX 1660 Ti实测训练参数、损失曲线与标线退化增强4.1 我跑通的完整训练脚本与参数解释下面是我的训练命令直接放出来给有同样显卡的朋友做参考yolo detect train \ dataparking.yaml \ modelyolov8s.pt \ epochs120 \ imgsz640 \ batch16 \ cacheTrue \ device0 \ workers4 \ lr00.01 \ lrf0.01 \ warmup_epochs3 \ mosaic1.0 \ patience20逐项解释几个关键的imgsz640不是越高越好。停车位是小目标理论上图片越大越好但是640在GTX 1660 Ti上已经是batch16的稳定上限。如果你把imgsz提到960batch得降到8整体训练速度反而更慢且收益有限。如果后期要用更高分辨率推理可以训练时用640推理时用960YOLOv8对输入尺寸的鲁棒性还不错。mosaic1.0马赛克增强对停车位场景非常有效尤其能模拟车位线被截断的画面。但注意最后10个epoch建议手动关掉或者让ultralytics自动在最后epoch关闭否则模型可能学不到精准的框回归。patience20早停连续20个epoch验证集mAP没有提升就停。我这次跑到第80轮就停了后面40轮都在波动早停能省不少时间。cacheTrue把图片加载到内存里省去每轮重复IO的时间。如果你内存小于16GB谨慎开启。4.2 损失曲线怎么看正常训练的图像长什么样训练结束后在runs/detect/trainX目录下会生成results.png包含box_loss、cls_loss、dfl_loss的train曲线和val曲线以及mAP50、mAP50-95的指标曲线。正常的曲线长这样训练损失和验证损失都在下降mAP曲线在前期快速上升随后渐趋平缓验证损失偶尔有小波动是正常的。如果出现训练损失降得很低、验证损失却不降反升这是过拟合的典型信号优先检查训练集和验证集是不是有相同场景的帧泄漏其次再看是不是数据量太少最后才考虑加大增强。另一个值得关注的指标是mAP50 和 mAP50-95 的差距。停车位检测的框通常比较大mAP50很容易刷到0.9以上但mAP50-95往往只有0.6左右。这个差距大说明你的框定位不够精确——对停车位业务来说框偏几个像素通常无所谓但如果要做后续的车位级联判断框的稳定性还是重要的。4.3 标线淡化场景的针对性增强我把这一类放在训练之后单独说是因为它被我验证过是最有效的提点手段。停车场标线褪色是普遍现象靠真实采集只能覆盖一部分磨损状态更高效的办法是让模型在训练时见过更多退化样式。在ultralytics的配置里数据增强主要靠hsv_h、hsv_s、hsv_v以及翻转、缩放、平移这些参数。针对标线淡化我额外做了两件事在训练集里手动对50%的图片做高斯模糊增强模拟远景失焦和标线边缘不清的情况。把一部分图片转为灰度图让模型去掉颜色依赖更关注标线与地面的亮度对比关系。这一步对夜间场景效果特别明显因为夜间很多标线其实是靠反光亮度来区分的而不是靠颜色。实测下来加了这两项增强后mAP50从0.88左右提升到0.92而且漏检率明显下降代价只是训练时间增加了10%左右。代价很小收益很大。5. 训练中跑出来的几个坑从报错排查到指标陷阱5.1 ultralytics和NumPy 2.x的兼容性问题这里顺手记录一个很常见但对新手来说很头疼的报错。如果你使用较新版本的ultralytics训练刚开始时会报类似AttributeError: numpy._core.multiarray._reconstruct...的错误本质是NumPy 2.x引入了不向后兼容的改动而ultralytics内部某些模块还依赖旧版NumPy的pickle序列化接口。解决方案有两个一个是把NumPy降级到1.24.x这个最省事另一个是把ultralytics升级到最新版。但注意升级ultralytics也有风险有些新版本训练参数变了旧脚本可能报unexpected keyword argument。我个人是固定版本链形成一套稳定的虚拟环境不做频繁升级。5.2 验证mAP很高实拍却识别不出来三个检查项这个坑很多人会踩一次。模型在验证集上mAP50接近0.95但拿到真实停车场画面一测经常是漏检一堆。原因通常出在三个方面验证集泄漏就像前面说的train和val没有按场景切分模型其实是背下了这些画面。推理尺寸和训练尺寸不一致训练用640实拍输入用1280模型很难适应这么大幅度的尺度变化。建议推理时用和训练时接近的尺寸或者把推理尺寸控制在960以内。置信度阈值设置不合理默认conf0.25对停车位场景可能偏高尤其是标线褪色的车位模型输出的置信度普遍偏低。可以在测试时把conf降到0.1看召回率是否大幅提升以此来诊断模型是在漏检还是不自信。如果降到0.1后召回率明显上来了说明模型其实学到了特征只是车位本身的视觉特征就弱需要靠调阈值取舍。5.3 空位和占用类别不均衡的处理思路自建数据集时采集到的占用样本通常远多于空位样本因为白天停车场大部分车位都有车。这种不均衡会导致模型倾向于把所有车位都判定为occupied因为这样在训练集上准确率更高。我的处理办法比较直接在采集阶段就刻意去拍空位多的时段比如清晨和夜间尽量让训练集里空位和占用的比例接近1:1。如果实在凑不齐才考虑用复制粘贴的方式扩充空位样本或者调整loss权重。但坦白说调loss权重属于治标不治本数据域本身的分布不平衡是根因。5.4 容易忽略的标注边界问题标注时一个常见的争议是车头已经越过车位线但车身还在车道里这时候框应该怎么画我的经验是以车位线为准不按车辆投影为准。也就是说只要车头进入车位区域这个车位就算是occupied但矩形框仍然框住整个车位线内部区域。这样标注出来的数据集模型学习到的是车位于某一时刻是否保持可停状态而不是车A和车位B的重叠面积有多大。前者更贴近停车位检测的真实业务语义。6. 训练完之后导出、部署与下一步优化6.1 ONNX导出和高分辨率推理的注意点训练收敛后第一步是导出成ONNX格式方便后续各种部署yolo export modelbest.pt formatonnx opset12导出时注意一点如果目标平台支持FP16建议导出时顺手做半精度转换模型体积和推理速度都会有明显改善。如果后期要用TensorRT进行推理ONNX的opset版本尽量和TensorRT版本匹配否则会遇到不支持的算子。在Jetson Nano这类边缘设备上实测FP16的yolov8s模型640输入下推理一张图大约在20-30毫秒基本能满足停车场道闸这种实时性不高的场景。如果追求更快可以裁剪模型到yolov8n速度能再翻一倍但准确率有一定损失需要做权衡。6.2 从yolov8s到嵌入式设备模型量化和轻量化的方向如果你要把模型装到嵌入式设备上比如RK3588或者Jetson Nano有几个方向是可以直接去做的ONNX转NCNN对国产嵌入式平台非常友好支持int8量化。int8量化需要准备一小批校准图片用验证集里的几百张图就够了不需要重新训练。量化后模型体积大约是FP32的四分之一在部分芯片上的推理速度可以提升2-3倍。TensorRT FP16在Jetson平台上性能表现优秀稳定性也好。缺点是需要编译引擎对硬件绑定较强换一台设备就要重新编译。模型蒸馏如果你希望保留yolov8s的精度但部署的时候用yolov8n的速度可以用蒸馏方式让小型模型学习大模型的软标签输出。这个方案需要一定的代码改动但收益是实打实的。我个人的建议是如果只是验证概念直接用ONNX在PC上跑就足够了如果真的要落地到道闸或巡检设备上优先花时间做TensorRT或者NCNN的int8量化。6.3 后续可以做的方向车位状态追踪与多摄像头融合训练完一个静态检测模型只是第一步。实际业务里停车场管理系统通常还需要知道某个车位被占了多久、哪些车位长时间空置这类推断信息。这就需要在检测框的基础上加上一个简单的跟踪器比如ByteTrack或者DeepSort对同一个车位ID做时序管理。基于YOLOv8的检测框输出做跟踪不复杂但能显著提升系统的实用价值。更进一步的方向是多摄像头融合。单摄像头总有盲区两个摄像头拼起来覆盖整个停车场需要处理视野重叠区域的输入输出去重。这一块会和车位编号关联涉及更多业务逻辑但从检测模型的角度看上游做好检测、下游做关联是整个系统里最经典的架构。6.4 关于我自己实验环境的一些补充最后补充一点硬件相关。我用的训练机是GTX 1660 Ti 6GB跑yolov8s训练大约19分钟一个epoch整体项目跑了大概5个小时训练加上数据整理。如果你手上的显卡是RTX 3060或更高训练时间和显存限制都宽裕很多可以直接尝试yolov8m。反过来说如果只有CPU建议优先考虑用Google Colab的免费GPU来跑训练效率会好非常多。另外提一句我用的是Linux环境Windows下大多数命令是兼容的但路径分隔符和文件权限偶尔会出些小问题。如果在Windows上遇到奇怪的文件找不到报错优先检查一下路径是不是被反斜杠转义了。做停车位检测这个细分方向其实没有特别复杂的高深理论真正拉开差距的往往就是数据集的构造方式和对场景特殊性的理解。把标线退化、视角差异、类别定义这些问题在数据准备阶段想清楚训练环节反而是最顺的。本文还有配套的精品资源点击获取
返回列表