资讯动态

共享Backbone的多任务视觉感知:红绿灯、车辆与停止线联合检测

发布时间:2026/10/22 13:58:31 来源:尧图企业网站定制
1. 项目背景与整体方案设计先说结论这是一个典型的车端视觉感知综合项目核心要解决三件事——看到灯、看到车、看到线。所谓“看到灯”就是红绿灯的检测与颜色状态识别“看到车”就是对前方车辆的图像分割“看到线”就是识别路口的停止线具体在哪里。放在深度学习框架里这三个任务用同一套图像输入、同一个特征提取网络最终输出多类感知结果。为什么非要把三个任务放一起早期我是分开做的红绿灯一个模型、车辆检测一个模型、停止线又一个模型各管各的。实际跑起来就发现问题了第一算力浪费严重边缘设备上三套模型轮流跑一遍前向推理宝贵的帧率全被吃掉了第二结果不一致灯刚变绿但车辆框还停在旧画面停止线的位置也在帧间跳来跳去决策模块根本不知道该信谁第三维护成本高任何一个模型要迭代整体都要重新联调。所以这个项目的核心架构思路可以概括成一句话共享Backbone的多任务学习框架一个编码器三个任务头。这套方案适合谁参考正在做自动驾驶感知、辅助驾驶L2/L3或者车路协同相关项目的人以及想了解一个完整视觉感知Pipeline从数据到上线全流程的开发者应该都能在里面找到有用的东西。它不是纯算法Demo而是从数据采集、标注、训练到部署调试的完整记录很多踩坑经验直接来自实际路面测试中暴露的问题。1.1 为什么选择多任务框架而不是多个独立模型多任务框架最直接的好处是计算开销小。以这个项目为例独立方案需要跑两次目标检测网络加两次分割网络总计算量大概是多任务方案的2.5倍左右。而多任务方案只需要一次前向传播主干网络提取的特征被三个任务头共用虽然每个任务头都有额外计算但相比单独跑多个模型已经省了很大一部分。另一个好处是特征互通。红绿灯、车辆、停止线在语义上有天然关联——停止线通常在车辆的正前方红绿灯通常挂在路口上方。共享Backbone会让底层特征同时感知这些关联比如提取“路面区域”的特征既能帮助定位停止线也能帮助排除非路面上的车辆误检。这种隐式关联在独立模型里是完全丢失的。当然多任务也有风险就是所谓的“梯度冲突”。一个任务更新Backbone的梯度可能不利于另一个任务。我后面的损失函数设计那节会专门讲怎么处理这个问题这里先记住一个原则任务头可以共享但反馈不能蛮干加权和分级训练是必须做的。1.2 模型整体结构与选型对比这个项目的网络结构分三块共享主干网络负责提取基础视觉特征采用轻量化ResNet结构检测任务头负责红绿灯的定位与颜色状态分类分割任务头负责车辆像素级分割和停止线像素级分割NLP方向的人可能会问为什么不直接用纯Transformer结构原因很实在Transformer在视觉任务上确实强但部署到边缘设备时注意力计算的内存占用和算子支持还不理想尤其在低端推理芯片上兼容性不好。CNN方案在这类场景里仍然是工程落地最稳的选择。选Backbone时我做了一组对比实验具体情况可以参考下表Backbone参数量红绿灯检测AP分割mIoU边缘设备帧率ResNet-5025.5M78.272.114 FPSResNet-50轻量化变体18.2M77.671.825 FPSMobileNetV311.4M72.367.531 FPSEfficientNet-B015.0M75.469.822 FPS最终选的是ResNet-50轻量化变体。主要原因有两个一是它在精度上和原始ResNet-50几乎持平但部署帧率提升了接近一倍二是MobileNetV3虽然在帧率上表现更好但红绿灯这种小目标检测掉点太多车辆分割的边界也不够干净。在这个场景里精度和速度需要蹲在一个平衡点不能一味追速度。1.3 输入分辨率与实时性的权衡输入分辨率是容易被低估的配置项。红绿灯是典型小目标640×640输入下目标可能只占20×30像素你不可能指望网络在这种情况下还能稳定识别。我把输入分辨率设为640×640同时训练时做随机增强到960相当于让网络同时适应两种尺度。推理时默认用640算力富余时切到960能提升小目标召回。这个策略的代价是分辨率越高计算量越大。边缘设备的算力很紧张所以我额外开了一个旁路图像预处理时只对上半部区域做高分辨率处理下半部路面的车和停止线保持常规分辨率。因为红绿灯物理上只会出现在上半部停止线和车辆主要在下半部这样既保住了小目标又压住了整体计算量。这个旁路在前向时效率极高强烈建议在类似项目里做一做。2. 数据准备与标注最耗时也最值钱的一块数据质量直接决定模型上限这句话在这个项目里体现得淋漓尽致。我先把结论放在这红绿灯识别这类任务公开数据集只够打底真正决定效果的是你自己采的现场数据覆盖度。2.1 数据来源与场景覆盖策略我采用“公开数据自采数据”双轨模式。公开数据先用约1.5万张解决通用特征的冷启动问题自采数据约2万帧解决特定场景适配问题。自采数据怎么采去实际路口架相机或者从行车记录仪视频里抽帧都可以。关键是场景要覆盖够全光照维度白天顺光、白天逆光、傍晚、夜间、雨天至少各一批道路维度标准十字路口、丁字路口、多车道大路口、施工路段交通流维度拥堵排队、畅通行驶、远处有车、近处无车特殊场景树影遮挡、灯体被大车挡住、阳光直射镜头、夜间对面远光灯直射为什么这么强调覆盖因为红绿灯识别的难点根本不是“认出灯”而是“在各种光照下认出灯”。同一个十字路口白天顺光和夜间过曝的红绿灯特征差异可能比不同路口的灯差异还大。实测下来夜间和逆光样本占比低于30%时真实路口测试的夜间精度会断崖式下跌。一个经验数字自采数据里夜间和逆光合计占比不要低于30%最好到40%。这个比例看着不均衡但实际场景就是这样——白天数据好采夜间数据难得样本分布必须刻意向难场景倾斜。2.2 标注流程与效率优化这个项目需要两种标注红绿灯的检测框框颜色状态红/绿/黄/熄灭/数字倒计时以及车辆和停止线的像素级掩膜。掩膜标注是典型的“费人费力”环节2万帧全部纯人工标注一个熟练标注员一天也就能标100多帧。我的做法是两轮标注法。第一轮先用一个预训练过的分割网络生成初始掩膜人工只修正边缘错误区域这一步能把效率提升约40%。第二轮对模型置信度低的区域做重复标注专门找那些容易被混淆的样本。这样做的额外好处是第一轮的预标注结果本身就是一个难样本筛选器——模型预测不好、置信度低的帧自动进入“重点标注”队列让人的精力花在最有效的地方。标注格式统一走COCO格式检测任务用bounding box分割任务用polygon训练时再转成RLE编码。有人问要不要自研一个统一标注平台我的建议是2万帧这个量级直接用好开源标注工具就行自研平台的开发成本比数据成本还高完全不划算。2.3 有针对性的数据增强常规的随机翻转、裁剪、颜色抖动肯定要做我就不多说了。这里额外讲三个针对本场景特别有效的增强方法第一是非对称光照扰动。普通方法是在整幅图像上调整亮度、对比度但真实路口最常见的情况是顺光和逆光并存——画面上方亮、下方暗或者反过来。我在HSV空间随机对上下区域设置不同的亮度系数模拟逆光场景让模型学会在亮暗不均的环境下依然能识别灯和路。这个方法对逆光场景的提升非常明显。第二是随机遮挡模拟。把图像随机一块区域涂成纯黑或模糊块模拟前车挡住停止线、灯杆柱子挡住车辆的情况。这迫使模型在被遮挡时也能从上下文推断目标存在对停止线这种细长且容易被挡的目标特别有效。第三是Copy-Paste小目标增强。红绿灯样本天然稀少尤其是特定颜色状态黄灯、熄灯更难采到。我把已有样本里的红绿灯区域抠出来做随机旋转、缩放、亮度扰动后粘贴到不同背景的合理位置贴在杆子附近、画面中上部以此扩充小目标样本。这一步对红绿灯召回率提升有直接帮助实测召回率提高了约4个百分点。3. 模型训练与参数调优实操训练阶段是决定最终指标的环节也是最容易出现“照搬别人的配置但跑不出来”的环节。我把自己实际调过的关键参数和经验整理成了一套完整配置下面详细展开。3.1 预训练权重与分阶段训练策略多任务模型不要从头训练这是第一原则。Backbone直接加载ImageNet预训练权重能大幅缩短收敛时间。实测下来用预训练权重比随机初始化在红绿灯检测精度上高出约10个百分点在训练80轮时。收益主要来自浅层特征——边缘、纹理、角点这些通用特征预训练权重已经学得很好了。更关键的是分阶段训练策略。整个训练过程拆成两段冻结期前30轮冻结Backbone的浅层参数只训练三个任务头。这样做的目的是防止某个任务头一开始就把浅层特征“带偏”——比如车辆分割任务梯度强烈导致特征提取器过早偏向车辆方向红绿灯检测就废了。解冻期后90轮解冻整个网络所有参数一起微调。此时任务头已经基本稳定全网络微调的风险最小。这套分阶段策略是稳定收敛的关键。我一开始直接全网络训练三个Loss互相拉扯前50轮精度几乎不涨改成两段式之后问题就解决了。3.2 最终稳定收敛的参数配置下面这份配置可以直接作为你项目的起点参考配置项数值备注输入尺寸640×640训练时随机640~960高分辨率对小目标友好优化器SGD Momentum 0.9比Adam收敛更稳学习率初始0.01余弦退火衰减前5轮线性warmupBatch Size32双卡每卡16显存不足时降到16总训练轮数120轮前30轮冻结期BackboneResNet-50轻量化变体预训练权重初始化Loss权重检测0.5 / 车辆分割0.3 / 停止线0.2先固定后微调这里特别提一下为什么用SGD而不是Adam。多任务模型里Adam的自适应学习率会放大某些任务的梯度导致任务间不平衡SGD配合动量反而是更平滑的选择收敛过程更稳定。我试过用AdamW效果也可以但需要更精细地调各任务学习率时间成本高对这个项目来说得不偿失。3.3 损失函数设计与类别不平衡处理项目的损失函数组合如下检测分支CIoU Loss 交叉熵分类Loss权重0.5车辆分割分支Dice Loss 交叉熵权重0.3停止线分割分支Focal Loss 结构相似性Loss权重0.2总Loss直接加权求和。选这些Loss不是随便堆的背后逻辑是Dice Loss对边缘像素的梯度更友好适合车辆这种形状复杂的目标Focal Loss能压低易分样本的梯度贡献适合停止线这种正样本像素极少、绝大多数是背景的情况。类别不平衡是这个项目里最典型的问题之一。城市道路正常巡航时拍到的基本都是绿灯红灯样本天然稀缺。如果不管它模型会把不确定的灯猜成绿灯——绿灯猜错最多是多等一个周期红灯猜错就是直接闯过去这种错误是绝对不能接受的。处理手段有三个第一对红灯样本过采样并配合更强的几何增强第二在分类损失里给“红灯”类别乘以1.8倍的类别权重第三用上Focal Loss降低易分样本大量绿灯背景的梯度干扰。这三个手段叠加后红灯识别的召回率从83%提升到了92%虽然还不能说完美但已经能满足路口通行决策的最低要求。3.4 训练过程的质量监控训练时不能只看总Loss曲线要同时盯三个子任务的Loss。多任务模型里总Loss平滑下降但某个子任务Loss在升的情况太多了不拆开看根本发现不了。我常用的监控项总Loss曲线是否整体下降三个分支各自Loss曲线是否都有下降趋势验证集上红绿灯AP、车辆mIoU、停止线mIoU的独立变化训练每10轮保存一次权重并导出一批badcase可视化其中最有用的就是badcase可视化。也许你会觉得打印几张图很简单但它的信息量极大——直接给你看模型到底“漏了谁”“误判了什么”。有一次我发现夜间红灯大量漏检第一反应是加夜间数据后来打印badcase一看漏检的主要是远距离的小灯近处的灯没问题。于是改成提高输入分辨率用更小的Anchor一次就解决了。这就是可视化排查的价值。4. 部署压缩与实时性优化训练好的模型直接扔到边缘设备上是跑不动实时推断的必须做模型压缩和推理优化。这一节我记录一下实测有效的优化流程。4.1 模型剪枝与量化流程我用的三板斧是剪枝、量化、算子融合。剪枝用的是稀疏正则化训练训练过程给卷积核的权重加L1稀疏约束训练结束后把接近零的通道剪掉。实测剪掉约30%冗余参数精度下降约0.5个百分点完全在可接受范围内。剪枝后要再做一轮很短的重训练让剩余参数适应新的通道结构这一步能挽回约0.3个百分点精度。量化用的是8位定点量化INT8推理时权重和激活值都用整数计算。量化后推理速度提升约2倍精度又掉了约0.5个点。注意一个细节量化校准集不要用训练数据要另外准备一组跟真实场景分布接近的图像否则量化误差会被低估。算子融合就是把相邻层的计算合并。比如卷积层后面的批归一化层在推理时可以把归一化的缩放因子直接折进卷积核里省一次张量运算。常见的融合组合有卷积批归一化、卷积激活函数、短路连接上的逐元素加法。这套组合拳下来又带来约20%的提速。最终优化效果剪枝量化算子融合后模型在边缘AI设备上的推理速度从初始的约12FPS提升到25FPS以上已经超过了辅助驾驶场景的最低帧率要求15FPS留有一定余量。4.2 后处理与状态平滑后处理也是部署环节的重头戏。红绿灯分类输出最怕单帧误判——某一帧光照突变导致红灯被误判成绿灯决策模块如果立刻响应就是事故。我加了一个状态平滑器为每个红绿灯检测框维护一个固定长度的状态队列取5帧只有当连续多帧分类结果一致且置信度超过阈值比如0.7才把状态输出给决策模块如果最近几帧置信度都不稳定保持上一次可靠状态不输出不确定结果这个逻辑简单但非常顶用。加了平滑器后模拟路测中单帧误判引发的错误响应数量从每千帧约5次降到了接近0次值得强烈推荐。停止线的后处理也有东西。单帧分割结果会抖动我用了5帧加权融合同时加了“贴地约束”——只有位于消失线下方的像素才能被归类为停止线因为物理上停止线一定在地平面上。相机外参标定准确时这个约束会让分割结果稳定得多线也不再断断续续了。5. 常见问题与排查技巧实录这一节我挑几个实车测试中最常遇到的问题把排查思路和解决办法一并写清楚。5.1 红绿灯小目标漏检怎么办现象车子离路口远时红灯检测不到靠近后才能检测到。排查顺序先看输入分辨率——如果用的是480×640等较低分辨率红绿灯在远处可能只有几个像素先提升到640×640或更高检查锚框配置——红绿灯长宽比接近1:2甚至1:3如果还在用默认的通用anchor比例根本框不中小灯看badcase可视化——把检测结果画出来确认漏检目标的实际尺寸多大、亮度如何确认是否需要特定光照数据——夜间远距离小灯和白天远距离小灯的难度不一样补对应场景数据这个项目里小目标漏检最主要的原因是锚框比例不匹配调整后召回率提升了约5个百分点。5.2 停止线识别线断了或被遮挡现象停止线被前车挡住时单帧分割结果会断成几段无法判断“线”的完整位置。解决办法分两步。第一步是时序融合取最近5帧的分割结果做加权平均帧与帧之间的信息互补断线就能补上第二步是加贴地约束根据相机高度和俯仰角把停止线的可能位置限制在地平面投影区域内排除建筑、树影等干扰。这里有个前提相机外参必须标定准确。如果外参偏移大贴地约束会把正确的像素点也过滤掉反而让精度更差。我建议上线前先做一个简单校验在平整路口放一块已知尺寸的标定板验证投影误差不超过几个像素。5.3 夜间场景过曝和低光夜间是红绿灯识别最折磨人的场景。灯体过曝后原本的红绿颜色信息严重丢失整片区域都是刺眼的亮白色块。我踩过几个坑强行调低相机曝光会牺牲整个画面的可见度单独加一个夜间增强分支增加了太多计算量。最终有效的是“黑夜模拟增强”——把白天数据做极低亮度处理加高斯噪声、随机过曝光斑模拟夜间成像特征再用少量真实夜间数据微调。这套组合把夜间检测精度从58%提升到了81%虽然和白天仍有差距但已经能支撑路口通行决策了。5.4 模型在某个特定路口频繁出错这类问题的本质是数据分布外样本。具体路口的摄像头角度、灯杆位置、信号灯造型甚至背景建筑跟训练数据相差太大。我实际遇到的情况是模型在大多数路口跑得挺好但走到一个灯杆横装的路口就频繁漏检红灯。解法分两条线。第一条线是数据线把这个路口的数据单独拎出来做增量微调而不是盲目改全局参数。增量微调用小学习率初始学习率的十分之一训练20轮左右保留原来的精度。第二条线是兜底线把常见路口的红绿灯形态做成模板库检测失败时用模板匹配做兜底。但兜底手段不能太强否则模型会产生“模板依赖”换个新路口又崩了。5.5 车辆分割边缘粗糙分割边缘粗糙的根源通常有两个一是Ground Truth标注质量不高边缘像素本身标得含糊二是边缘样本量不足模型没学到清晰的边界特征。我用的方法是给车辆分割头加一个边缘注意力模块思路很简单额外预测一个边缘概率图把它和主分割结果相乘迫使网络在车辆轮廓附近投入更多注意力。这个模块让车辆分割的mIoU从68%提升到了73%而且推理时几乎不增加额外耗时。6. 复盘与后续扩展方向项目收尾时做一个复盘最大的感悟是多任务感知系统在论文展示里看着“优雅”但实际工程里天天面对的都是光照变化、目标遮挡、小目标、类别不平衡这类“土问题”。网络结构再有创新最终决定系统能否可靠运行的仍然是数据覆盖率、后处理策略和部署优化这三板斧。如果你要继续扩展有几个实践价值很高的方向可以尝试。一是把红绿灯状态识别与时序预测结合根据前几帧的状态变化推测下一秒的信号灯状态给决策模块留出更长的反应窗口。二是把车辆分割升级为实例级分割为每辆车分配独立ID这样能支持更细粒度的路权判断比如相邻车道车辆的插队意图。三是把停止线与高精度地图融合用地图先验约束分割结果减少视觉系统的过度依赖这在雨雪天或者强逆光时尤其有价值。最后一个小建议验证模型时千万别只看总体mAP或总体mIoU一定要按场景维度拆分开看——白天、夜间、雨天、逆光分别计算指标。单看一个总体数字你很难发现夜间已经差到不可用的程度。只有拆开看才能知道下一步该补哪类数据、调哪个模块这也是我在这个项目里印象最深刻的一条经验。

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

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

免费获取报价 →
↑