尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

小样本也能训出可用的交通标志检测模型:基于1886张图片的实践

小样本也能训出可用的交通标志检测模型:基于1886张图片的实践 我们最近在推进一个智能驾驶系统地图数据更新的项目任务说白了就是外业采回车跑完一圈之后把道路沿线的交通标志变化找出来。限速值改了、禁行时段变了、路口多了块施工提示牌这些都要反映到地图里。最早我们靠人工一帧一帧看行车记录仪画面几万张图看下来眼睛受不了效率也低。后来我把流程砍成两段先用一个目标检测模型把可能含交通标志的图片筛出来、把标志框出来并自动分类再由人工只做最终确认。这里面的核心就是那 1,886 张图片的交通标志检测与分类数据集。这套数据集规模乍一看不大但它承载的并不只是“训练一个模型”而是整条地图更新流水线的前置视觉能力。做完之后模型在测试路段上的 mAP0.5:0.95 做到了 0.72 左右人工看图的工作量压掉了七成。这篇文章就围绕这批数据的构建和使用展开包括数据怎么筛、类别怎么定、标注怎么控质量、模型怎么训、检测结果怎么接回地图更新流程。如果你也在做智能驾驶感知、地图数据生产或者手里只有小规模数据却想训出一个能用的模型这篇应该能给你一些可复现的方案。1. 1,886张图片是怎么来的从外业原片到高信噪比数据集1.1 外业采集的真实情况先说外业采集。我们的采集车在目标城市跑一圈车上装的行车记录仪和工业相机以固定间距或时间间隔拍照一趟下来单个批次通常能带回上万张图片。很多人一听“上万张”就觉得够了但真正归档的时候会发现数量不等于质量。这批原始图片里有几个典型问题大量图片是纯路面、绿化带、车道线整张图里没有任何交通标志这类图片约占六成。同一个标志在连续多帧里反复出现比如车辆从 100 米外接近一个限速牌到贴近它只有两三米这段时间里标志可能被拍到 8 到 12 次。如果不做去重训练集相当于被同一个样本灌了好几遍模型学到的其实是“这条路段长什么样”而不是“限速牌长什么样”。部分图片因为逆光、夜间过曝、挡风玻璃反光、雨滴模糊标志区域根本无法辨认硬标进去只会给模型制造噪声。我们当时很清楚目标不是做一个“尽可能多图片”的数据集而是做一个“每张图都有明确学习价值”的数据集。所以第一步动作是从原始图池里把带标志的候选帧挑出来再做抽帧去重最后进入精标流程。这个漏斗走完原始一万多张图片里只剩下一批真正可用的帧再经过筛选和清洗最终保留 1,886 张。数字虽然降下来了但信噪比高了不止一个量级。1.2 筛选标准和抽帧策略筛选不是随便看看“有没有标志”就行它需要同时满足几个条件缺一项都可能给后续引入坑。清晰度是最基本的门槛。我们先用 Laplacian 算子做了一轮粗筛把方差低于设定阈值的图片直接标为“模糊待定区”再人工二次确认。原因很简单交通标志本身就含文字和精细图形图像一模糊限速 30 和限速 40 就几乎无法区分这种样本会让分类头学得一团糟。角度和完整性同样关键。标志被车辆或树木遮挡超过 40% 的放弃标志在画面边缘被切掉大半的放弃从侧面拍导致标志严重变形的放弃。不是说这些图以后没用而是在首版数据里它们会让模型对“标志长什么样”产生偏差。等到模型有了一定能力再用难例挖掘的方式处理遮挡和侧视角场景更合理。抽帧去重上我们按轨迹距离来抽而不是按时间。采集车在高速公路上跑时间抽帧可能连续抽到高度相似的画面按里程抽帧比如每 10 米取一帧配合 GPS 轨迹信息能比较均匀地覆盖路段同时避免同一标志被太多次重复采样。同一标志在多帧中反复出现时我们只保留标志区域最大、角度最正、清晰度最高的那一张。这条规则虽然简单却是整个数据集质量的生命线。1.3 数据集构成的基本统计1,886 张图片最终构成如下维度分布情况道路场景城市道路 65%快速路/高速 22%国道/乡村道路 13%光照条件白天 82%黄昏/晨昏 11%夜间 7%图像分辨率1920x1080 为主部分 3840x2160标注质量平均每张图 1.7 个标志实例总计约 3,200 个实例框数据划分训练集 1,521 张验证集 365 张这个构成不是随手分的。夜间图片虽然只占 7%但训练时一张都没删因为地图更新项目里夜间采集数据一定会出现模型如果在训练阶段完全没见过夜间场景部署时遇到暗光就直接失效。城市道路占大头也和地图更新频率直接相关——城市里交通标志变化最快高速和国道相对稳定。这里有个关键决策值得多说一句划分训练集和验证集时我们按路段划分而不是按图片随机划分。同一路段前后帧背景高度相似如果同一路段的图片同时出现在训练集和验证集里验证指标会虚高模型真正遇到新路段时表现会明显下滑。按路段切分虽然会让验证集稍难一些但评估出来的数字更接近真实部署水平。2. 标注体系设计类别怎么定框怎么画2.1 类别粒度由业务需求决定交通标志检测和分类的数据集最怕上来就照抄某个开源数据集的类别体系。不同数据集的类别粒度差异很大有按“禁令标志、警告标志、指示标志”分大类归类的也有把“限速40”“解除限速40”“禁止停车”“禁止长时间停车”拆得非常细的。如果只做自动驾驶实时感知可能大类就够了但我们是给地图数据更新做视觉前置业务上必须知道具体语义地图更新需要记录的是“这个路段的限速值从 60 变成了 40”而不是“这里有个禁令标志”。所以类别树基本参考了国内道路交通标志标准里标志的功能分类但没有照搬编号而是按实际拍摄中出现的情况收敛最终固定为 27 个具体类别。举几个典型限速系列speed_limit_40、speed_limit_60、speed_limit_80、speed_limit_100 等按具体数值分开禁令系列no_parking禁止停车、no_stopping禁止长时间停车、no_horn禁止鸣喇叭、stop_yield停车让行等警告系列pedestrian_crossing注意行人、school_zone注意儿童/学校区域等指示与指路单行路、人行横道、车道方向指示等施工临时标志construction 类别单独列其中几个类别的实例数分布是这样的类别ID类别名实例数0speed_limit_404151speed_limit_603582speed_limit_802863no_parking2324stop_yield1875pedestrian_crossing1566construction977school_zone438no_horn7最后一行那个 no_horn 只有 7 个实例是所有类别里最少的一类。刚开始我们犹豫要不要直接删掉后来一想地图更新里禁止鸣喇叭标志虽然少但一旦漏更新对某些对噪声敏感的区域影响很大所以还是保留。只是对这个类别的训练策略要单独处理这个后面再讲。2.2 标注工具与半自动流程标注工具的选择直接决定了 3,200 个框要多长时间标完。第一版我用 LabelImg 纯手工框200 张图就让人有点崩溃了。后来换了 X-AnyLabeling用预训练检测模型先出一轮初标人工只需要修正框的位置和类别速度提升明显。对于轮子比较规整的交通标志初标质量尤其好人工要做的往往只是挪一下边界。标注规范里有一条很关键矩形框要贴合标志外缘。比如红圈白底的限速牌框要包含整个圆形标志可以把边框稍微往外留一点但不能切进圆形区域。半径类标志如果框切到图形内部模型学到的特征就被截断了检测精度会明显下降。另外我们还立了几条硬性约定标志在图像中的最短边小于 16 像素不标注。标志被遮挡面积超过 40%不标注。同一标志在多帧中重复出现只标注清晰度最高的一帧。实在看不清类别的先标成“待定”并在备注里写清原因之后统一复核。这几条约定后来成为整个数据集一致性的基础。如果每个人对“小目标标不标、遮挡标不标”的理解都不一样标注出来的框一会有一会没有模型训练时标签本身就是矛盾的。2.3 双重复核与类别一致性控制标注做完一轮还不算完。我们的流程是标注员 A 初标标注员 B 抽检至少 10% 的图片重点看框的位置、类别选择和边界情况。抽检中发现的错误分两类一类是手滑比如框歪了、框大了直接修正另一类是理解不一致比如“禁止停车”和“禁止长时间停车”在远距离小目标下经常被混标这种就不是改一个框能解决的需要回到标注规范里补充示例图再全员同步。我自己的经验是交通标志数据集的标注错误大头不是框的位置而是类别的细微混淆。限速 40 和限速 30 在一起时红圈里的数字如果不放大看是很容易标反的施工标志里的“道路施工”和“前方施工”也是相似的橙底图形。所以复核时我要求标注员特别关注这些“高危类别对”单独做一轮交叉验证。3. 清洗与增强1,886张图怎么撑起一个能用模型3.1 清洗阶段发现的几个真实问题清洗是在标注之前做的但它解决的问题会直接反映在训练效率和模型效果上。第一个问题是近似重复图。我们用感知哈希dHash对图片做指纹计算两张图指纹汉明距离低于阈值的视为近似重复。这一步清掉的主要是同一标志在不同帧中的高度相似图。有一点要提醒汉明距离的阈值不要压得太低否则会把确实不同但背景相似的路段图误删我们实测阈值设在 0.7 左右比较稳。第二个问题是 GPS 时间戳错乱。因为后续要把检测结果映射到地图坐标图片的位姿信息必须可靠。如果一张图的拍摄时间和位置对不上它在训练集里也许还能给模型提供视觉特征但对地图融合流程来说就是脏数据。我们清洗时会把 GPS 轨迹明显跳变、时间戳和前一张图间隔异常的图片单独拉出来人工判断确认是设备丢星还是轨迹正常。第三个问题是曝光异常。夜间图片在直方图上会有一大块低亮度分布逆光图片则会在局部区域出现过曝。对这类图我的策略是保留并纳入训练而不是一味剔除。地图更新项目里夜间、逆光采集是常态模型如果只在白天图上训练到了真实采集环境基本是不能用的。3.2 增强策略要针对标志的特殊性1,886 张图片跑 YOLOv8s数据增强不是可选项是必需品。但交通标志的增强有个天然约束标志和文字、箭头强相关方向感极强乱做增强会适得其反。以“禁止驶入”标志为例它是一个红色圆底加白色横杠语义明确指向“不能进入”一旦做了垂直翻转或者 80 度旋转它看起来就像另一个完全不存在的标志再比如“限速 40”的牌子水平镜像后数字 40 会变成镜像文字模型学到的特征就是错的。所以我们把增强分成三个梯队第一梯队是安全增强基本不会破坏标志语义亮度/对比度扰动、HSV 颜色扰动、高斯噪声、轻微模糊。这些主要用来模拟不同天气和采光条件下的画面差异。第二梯队是针对采集姿态的增强随机透视变换、仿射变换模拟车辆偏航时标志从侧面拍到的形状变化。交通标志安装在杆子上视角变化确实会带来几何形变这种增强对模型的视角鲁棒性帮助很大。第三梯队是特殊增强小角度旋转控制在 ±5 度以内随机裁剪模拟遮挡但裁剪不能切掉标志主体。大角度旋转、垂直翻转、全图的水平镜像这些对大部分类别都是禁忌。还有一个实测后的经验MixUp 在这个任务上是负优化。交通标志是结构非常清晰的强语义目标MixUp 把两张图叠在一起后标志文字和图形混成一片模型反而学乱了。对比实验里加 MixUp 的模型 mAP 比不加低了约 1.8 个点后来直接关掉。3.3 少样本类别与小目标怎么补no_horn 类只有 7 个实例这种数量级别下任何模型都无法学会。我们做了两步第一步是数据重采样把这类样本在训练时重复多次参与梯度更新相当于把它的权重顶上去第二步是后续外业采集时让采集员在已知有禁止鸣喇叭标志的区域多跑两圈专门补拍。小目标问题更棘手。交通标志在 100 米外时640x640 输入下可能只有 16x16 像素勉强是人眼能认出来的极限。模型对小目标天然不敏感增强帮不了太多只能靠提高采集密度、让同一标志在更近距离处被拍到然后抽帧时保留这些近距离帧。这也是为什么原始一万多张最终只保留 1,886 张——去重时删除大量重复帧但补拍和近距离帧的取舍必须非常克制否则数据集会迅速膨胀回低信噪比状态。4. YOLOv8s训练实录参数、指标和失败案例4.1 模型选型和训练配置在 1,886 张图片这个规模下模型选型其实没有太多悬念。YOLOv8n 参数少、训练快但对小目标明显乏力YOLOv8s 比 n 大了约一倍参数量精度提升在交通标志这种小目标场景下非常可观更大的 m 和 l 在这个数据量下容易过拟合收益不明显。RT-DETR 这类 Transformer 结构在这种中小规模数据集上也没必要训练不稳定收敛还慢。训练环境是单张 RTX 4090PyTorch 2.x 加 Ultralytics 8.x模型选的 YOLOv8s。关键超参数配置如下参数配置输入尺寸img640批大小batch16优化器SGDmomentum0.937初始学习率lr00.01训练轮数epochs100早停触发约 42 轮数据增强mosaic 前中期开启最后 10 轮 close_mosaic推理置信度conf0.35NMS IoUiou0.5SGD 和 AdamW 我各跑了一版实测 SGD 在这个数据集上更稳。AdamW 前期收敛快但后期在少样本类别上更容易震荡对小数据集不友好。4.2 评估结果与分类别看最终模型在验证集上的指标是mAP0.5 约 0.931mAP0.5:0.95 约 0.72。这两组数字单独看没概念拆开类别看就很有意思限速系列40、60、80AP 都超过了 0.95属于最好学的一批。原因是这类标志颜色固定、形状统一、文字信息清楚且样本数量充足。no_parking 和 stop_yield 这类图形型禁令标志也不错AP 在 0.88 左右。pedestrian_crossing 这个类别稍微差一点因为部分蓝底矩形和蓝底圆形的“人行横道”标志外观太接近人和斑马线图形在远距离下又难以分辨。construction 施工类只有 0.79原因是有几种不同的施工标志模板黄色背景、橙色背景都有样本多样性不足。school_zone 因为实例数只有 43 个AP 勉强到 0.7。这里想提醒一句评估指标一定要看分类别的结果不能只看一个总 mAP。总 mAP 被限速系列拉得很高容易掩盖施工标志和学校区域这些短板。地图更新业务里漏一个学校区域标志和漏一个限速标志一样都是事故隐患。4.3 几个怎么调都救不回来的失败案例训练过程中有几类失败案例直到现在也没完全解决说出来的目的是希望大家对模型边界有个准确预期。第一类是雨夜场景下“限速 40”和“限速 30”的混淆。降雨导致反光红圈内的白色底子在高光下反白数字边缘糊在一起模型容易把 40 看成 30或者反过来。我们把亮度扰动增强拉满过一轮帮助有限因为这种反光是局部高光加雨滴折射的复合效应单纯改变全局亮度模拟不出来。第二类是 60 米以外的远距离小目标漏检。标志在 640x640 输入下小于 20 像素时模型基本就失去检测能力了。试过把输入分辨率调到 1024小目标召回确实有所提升但训练显存和时间成本涨了很多最终没有采用。第三类是施工临时标志。快速路上的橙色临时标志和固定安装在路侧的蓝色指路牌外观差异很大但类别都属于“施工”语义样本量又不足模型学得非常吃力。后来我们单独给 construction 增加了增强权重进展有但不彻底。面对失败案例我的处理原则是部署时把推理置信度从 0.35 调低到 0.25宁肯多给人工复核队列塞一些疑似样本也不能漏真。地图更新流程里多一次人工点击的成本远低于漏一个标志导致地图数据不准确产生的连锁问题。5. 从检测框到地图要素接入地图更新流程的完整走法5.1 原人工流程和新自动流程的差异为什么要专门用一整章讲这个因为模型训出来只是第一步如果检测结果不能顺利落到地图更新流程里数据集做得再考究也是白搭。原来的流程是这样的外业图片回来后地图编辑人员打开视频逐帧查看看到交通标志就暂停记下类别、大致位置再去地图编辑平台里手动加要素。一个城市几百公里的采集数据一个人要看好几天而且很容易疲劳漏看。接入检测模型后流程变成采集车图片连同 GPS/IMU 位姿一起进入推理服务。模型输出图片中的标志框、类别和置信度。通过相机内参和车辆位姿把 2D 框中心点映射到地面坐标结合标志牌的典型安装高度和尺寸做单目测距生成地图上的候选点。多帧检测结果按空间位置聚类同一个物理标志的多帧结果合并成一个要素候选。地图编辑平台只展示这些候选要素附上抓拍图片原图由人工确认“新增、删除、不变”三种操作。人工编辑不再需要看全量视频只需要看模型挑出来的候选。我们做了一次统计这个流程上线后单批次地图更新的编辑耗时大约是原来的 30% 左右省下来的是大量无意义浏览时间。5.2 多帧融合与人工复核的边界多帧融合是整个流程里最容易出错也最值得花时间设计的一环。单帧检测的置信度再高也可能因为瞬时反光、运动模糊出现误检而单帧的漏检则可能意味着一个标志彻底消失在地图里。所以我们的融合逻辑是同一段连续轨迹中同一个物理标志至少在 3 帧被检测到且检测类别一致才生成一个要素候选。置信度取多帧最大值而不是平均值因为我们更关注“最清晰的那一眼看到的结论”。类别不一致时比如 2 帧判定为限速 40、1 帧判定为限速 30自动标记为“类别冲突”强制进入人工复核不尝试自动仲裁。人工复核界面里会同时显示候选框的抓拍图、类别、置信度和地图位置。复核员要做的判断只有两类一是类别对不对二是这个标志是否仍然存在。如果某个候选框多次出现“误检”标签我们会把这个样本捞出来加入下一轮训练集的难例池。5.3 数据回流与后续扩容首版 1,886 张跑通流程后下一个问题自然是数据集怎么扩我的答案不是“一次性搞几万张”而是随着流程跑起来慢慢扩。每一轮地图更新项目结束后人工复核产生的正负样本都会回流到数据集。确认“新增”的标志实例作为新训练样本确认“误检”的检测框作为难负样本。这个过程听起来慢但胜在数据分布和真实部署场景完全一致——不会有实验室数据和现场数据偏差过大的问题。目前我们已经追加了约 1,200 张新采集和复核回流样本第二轮增量训练后模型 mAP0.5:0.95 比首版提升了约 1.5 个点其中施工标志类别的提升最明显。这个扩展速度不算快但每一步数据都经过真实业务验证不会引入太多噪声。我自己的体会是交通标志检测这类垂直任务数据集的价值不体现在数量上而是体现在“类别粒度和业务需求是否对齐、标注一致性是否可控、清洗是否彻底”这几件事上。1,886 张起步完全够用关键是把每一张图的质量和每一条标签的语义都搞扎实。后面再想让模型变强就往难例和边缘场景补数据而不是盲目堆图量。
返回列表