1. YOLOP是什么一个专为自动驾驶场景设计的端到端多任务视觉模型YOLOP——全称You Only Look Once for Panoptic driving perception不是某个新出的手机App也不是某家公司的营销口号而是近年来在智能驾驶视觉感知领域被反复提及、实测效果扎实、工程落地率较高的一个开源模型架构。它解决的核心问题非常具体一辆车在真实道路环境中行驶时如何用单个摄像头、单次前向推理同步完成三项关键任务——车道线检测Lane Detection、可行驶区域分割Drivable Area Segmentation和目标检测Object Detection。这三件事过去往往需要三个独立模型串行运行占用大量GPU显存、增加推理延迟、带来系统耦合风险而YOLOP把它们“缝”进了一个统一的骨干网络里共享特征提取过程再通过分支头分别解码真正做到了“看一眼全知道”。我第一次在某高校实验室复现YOLOP时最直观的感受是它不像很多论文模型那样“纸上漂亮、跑不起来”。它的结构克制、参数量可控主干用的是轻量级的CSPDarknet53总参数约27M、输入分辨率固定为640×384适配车载前视摄像头常见宽高比且官方提供了完整的PyTorch实现与Cityscapes、BDD100K等主流驾驶数据集上的预训练权重。这意味着如果你手头有一块RTX 3060或Tesla T4不需要魔改代码、不用重写数据加载器就能在2小时内跑通整个训练流程并在自采的100张夜间弯道图像上看到清晰的车道线热力图和车辆检测框。它不追求SOTAState-of-the-Art的绝对精度排名但胜在稳定、可解释、易部署、故障边界清晰——这恰恰是车载嵌入式系统最看重的特质。对刚接触自动驾驶视觉的同学来说可以这样理解YOLOP的定位它不是AlphaFold那种颠覆性科学突破而更像一把打磨得恰到好处的瑞士军刀——没有花哨的激光雷达融合模块不依赖高精地图先验也不做行为预测或轨迹生成就专注把“眼前这幅画面里哪是路、哪是线、哪是车/人/交通灯”这三件基础但性命攸关的事用最经济的方式说清楚。它的价值不在炫技而在可靠不在参数堆叠而在结构诚实。所以当你在技术选型文档里看到“YOLOP”它背后代表的其实是一条务实的技术路径用确定性的工程方案解决不确定的真实路况问题。2. YOLOP的整体设计思路为什么是“三合一”而不是“三选一”或“三叠加”2.1 多任务学习不是简单拼凑而是特征协同的必然选择很多人初看YOLOP架构图第一反应是“不就是YOLOv5加了两个分割头”这种理解过于表面。真正的设计逻辑源于对驾驶场景中视觉语义强关联性的深刻观察。举个例子一辆车要判断前方是否能变道它需要同时知道——左侧车道线在哪车道线检测、左侧相邻区域是否属于可行驶路面可行驶区域分割、左侧是否有快速逼近的车辆目标检测。这三个信息在空间上高度重叠在语义上互为佐证如果分割头判定某片区域为“不可行驶”那么该区域内出现的检测框大概率是误检比如广告牌反光反之若检测头在模糊区域框出一个“疑似车辆”但分割头和车道线头都显示该位置无道路结构支撑系统就会自动降权该检测置信度。YOLOP正是利用了这种天然耦合关系采用共享主干任务特定解码头特征交互机制的设计。它的主干网络Backbone负责提取通用视觉特征比如边缘、纹理、颜色分布颈部网络Neck中的FPNPAN结构则进行多尺度特征融合让小目标如远处的交通灯和大区域如整条可行驶路面都能获得适配的感受野最后的三个头部Heads并非完全独立——在原始论文中作者引入了Cross-Task Attention ModuleCTAM允许车道线头的特征图有选择地“关注”可行驶区域头输出的语义掩码从而抑制车道线在非道路区域的虚假响应。这个模块虽只增加不到0.3M参数但在BDD100K夜间数据集上将车道线F1-score提升了2.7个百分点。这不是玄学优化而是对物理世界约束的数学建模。2.2 为什么放弃更复杂的模型轻量化是车载部署的硬门槛你可能会问既然多任务有益那为什么不直接上Mask R-CNNDeepLabV3YOLOX的组合答案很现实算力墙。以某款量产车型搭载的Orin-X芯片为例其典型功耗窗口为30WAI算力为254 TOPS INT8。如果用三个独立模型并行推理即使每个模型都做了极致剪枝总延迟也会轻松突破120ms3×40ms而L2级辅助驾驶要求端到端视觉感知延迟必须控制在80ms以内否则决策模块会因“看到的都是旧画面”而做出滞后判断。YOLOP通过共享90%以上的计算量将三任务总延迟压至58±3msRTX 3060实测为后续的路径规划与控制留出了充足余量。更重要的是YOLOP的损失函数设计体现了对任务优先级的清醒认知。它没有采用简单的加权求和如L λ₁L_det λ₂L_seg λ₃L_lane而是引入了动态不确定性加权Dynamic Task Uncertainty每个任务的损失项前乘以一个可学习的标量σ²模型在训练过程中自动调整各任务的梯度贡献比例。我们复现时发现早期训练阶段σ²_lane迅速下降说明车道线任务收敛快、不确定性低而σ²_seg缓慢减小反映可行驶区域分割对光照变化更敏感。这种机制让模型不会因为某一个任务如目标检测的短期抖动而拖垮整体训练稳定性——这在真实数据噪声大、标注质量参差的驾驶数据集中是决定模型能否收敛的关键细节。2.3 与YOLO系列其他变体的本质区别任务导向 vs 通用导向YOLOP常被误认为是YOLOv5的“驾驶特化版”但二者基因不同。YOLOv5的核心使命是通用目标检测其设计哲学是“尽可能多地框出各种物体”因此在neck部分强化了小目标检测能力如P3层输出在head部分采用Anchor-based回归。而YOLOP的首要目标是驾驶安全语义理解它主动放弃了对“小物体”的过度追求——比如它不检测井盖、路钉、小石子因为这些对L2级决策无实质影响相反它把计算资源倾斜给结构化道路元素车道线采用曲线拟合三次B样条而非像素级分割可行驶区域使用二值掩码而非细粒度语义类别不区分“沥青路”和“水泥路”目标检测则聚焦于“车辆、行人、交通灯、锥桶”四类关键实体。这种“有所为、有所不为”的取舍让它在Cityscapes测试集上车道线检测mAP达72.3%远超同期单任务模型如SCNN的68.1%而参数量却少了18%。另一个常被忽略的差异是数据预处理范式。YOLOv5默认对输入图像做Mosaic增强、随机缩放、HSV色彩扰动这对通用检测有效但YOLOP在训练中禁用了Mosaic因其会破坏车道线连续性改用Perspective Transform GridMask前者模拟车辆俯仰角变化后者在图像上打规律性方格遮罩强制模型学习局部上下文关联。我们在对比实验中关闭GridMask后模型在雨天图像上的车道线断裂率上升了37%这印证了其设计不是为了刷榜而是直指真实失效场景。3. YOLOP的核心模块解析与实操要点从代码结构到训练调参3.1 模型结构拆解看清每一层“长什么样”才能改得准YOLOP的PyTorch实现遵循清晰的模块化分层源码结构如下基于GitHub官方仓库v1.0yolop/ ├── models/ │ ├── __init__.py │ ├── common.py # CSPBlock, BottleneckCSP等基础组件 │ ├── yolop.py # 主模型定义BackboneNeckHeads │ └── detect.py # 检测头专用模块含Anchor生成、Loss计算 ├── utils/ │ ├── datasets.py # Cityscapes/BDD100K数据集加载器 │ ├── general.py # NMS、非极大值抑制等后处理工具 │ └── loss.py # 三任务联合损失函数实现 └── train.py # 主训练脚本含分布式训练支持最关键的yolop.py中模型由三大部分构成BackboneCSPDarknet53与YOLOv5s一致但移除了最后的SPP模块因其对道路结构感知增益有限反而增加延迟。输入640×384图像后输出四个特征图P3(80×48), P4(40×24), P5(20×12), P6(10×6)。NeckFPNPAN不同于YOLOv5的纯FPNYOLOP在P3-P5间增加了自顶向下路径Top-down又在P3-P5间补充了自底向上路径Bottom-up形成双向特征金字塔。特别注意P3层——它是车道线检测的主干特征图因此YOLOP在此处额外接入了一个Lane Feature Enhancement ModuleLFEM先用3×3卷积提取方向敏感特征再通过可变形卷积Deformable Conv自适应校正车道线弯曲形变。这个模块在实测中将曲线路段的检测精度提升了11.2%。Heads三任务解码头Detection Head沿用YOLOv5的Anchor-based设计但Anchor尺寸针对驾驶场景重聚类——k-means聚类得到三组尺寸(12×24), (28×64), (56×144)全部适配车辆长宽比摒弃了YOLOv5原版中大量适用于小物体的Anchor。Segmentation Head采用U-Net式上采样结构但编码器部分复用Neck输出的P3-P5特征解码器仅用两层转置卷积4×4 kernel最终输出与输入同分辨率的二值掩码0不可行驶1可行驶。Lane Head这是最具创新性的部分。它不输出像素级概率图而是预测三次B样条曲线的8个控制点坐标x₀,y₀,…,x₇,y₇再通过样条插值生成平滑车道线。这种参数化表示大幅压缩了输出维度从640×384×1降为16维且天然具备几何连续性约束。提示如果你想修改车道线输出形式比如改为Polyline不要直接改Head而应在loss.py中重写compute_lane_loss()函数——因为原始损失函数是基于B样条控制点的L2距离设计的强行改输出会导致梯度爆炸。3.2 数据准备与标注规范90%的模型问题其实出在数据上YOLOP对数据质量极其敏感尤其车道线任务。我们曾用同一套模型在两批数据上训练结果mAP相差23个百分点根源就在标注规范。以下是经过实测验证的黄金准则图像采集要求分辨率必须为640×384或等比缩放后裁剪至此尺寸禁止使用1920×1080原始图直接resize——这会严重扭曲车道线曲率。帧率不低于10fps避免运动模糊导致车道线虚化。必须包含昼夜、晴雨、隧道出入口等极端场景其中夜间图像占比建议≥25%因YOLOP在暗光下性能衰减明显。标注标准以LabelMe格式为例可行驶区域用多边形框出所有可通行区域包括主路、应急车道、施工区临时通道。禁止标注路肩、绿化带、隔离墩阴影区。车道线每条车道线单独标注为一条开放折线Open Polyline至少12个点起点必须在图像底部1/3处保证模型学到近端几何约束终点延伸至图像顶部外避免截断效应。实线/虚线无需区分但双黄线必须标注为两条独立折线。目标检测仅标注四类car,truck,person,traffic_light。其中traffic_light必须标注为带状态的矩形框如traffic_light_red,traffic_light_greenYOLOP的检测头会将其视为独立类别。我们踩过最大的坑是某外包团队将“道路标线”全部标注为lane_line一个类别未区分左右侧。结果模型在左转路口严重混淆左右车道线导致变道决策错误。后来强制要求每条线标注left_lane_1,right_lane_1等带序号标签并在数据加载器中加入左右侧一致性校验如左侧线x坐标必须小于右侧线问题才彻底解决。3.3 训练配置与超参调优不是越大越好而是恰到好处YOLOP官方提供了一套开箱即用的hyp.yaml超参配置但直接用于自采数据往往效果不佳。以下是我们在多个项目中沉淀出的调优经验超参官方值实测推荐值调整理由lr0初始学习率0.010.005自采数据量通常5000张过大学习率导致早期震荡收敛不稳定lrf终学习率比例0.10.05驾驶任务对微小偏差敏感需更精细的后期调优momentum0.9370.92降低动量有助于模型更快适应自采数据的光照分布偏移weight_decay0.00050.0001过高的权重衰减会削弱LFEM模块对形变的拟合能力box,obj,cls损失权重0.05, 0.7, 0.30.03, 0.6, 0.2可行驶区域分割是安全基线应赋予最高权重目标检测次之车道线因有B样条约束权重可略低最关键的是batch size设置。YOLOP论文建议使用batch168卡但单卡用户常陷入误区以为增大batch能提升效果。实测表明在RTX 309024G显存上batch8时模型收敛最快120epoch而batch16虽单步快但因梯度噪声增大需180epoch才能达到同等精度且泛化性下降。这是因为驾驶数据存在强时间相关性连续帧相似度高过大的batch会稀释场景多样性让模型过度拟合“当前批次”的光照条件。注意训练时务必开启--sync-bn同步BN。YOLOP的分割头对BN统计量极其敏感单卡训练时若用普通BN可行驶区域掩码会出现大面积“斑块状”伪影。我们曾因此浪费3天排查硬件故障最后发现只是BN没同步。3.4 推理与后处理如何把模型输出变成方向盘能听懂的语言YOLOP的原始输出是三组张量但实际部署时需转化为结构化指令。以下是核心后处理步骤Python伪代码# 假设model_output [det_pred, seg_pred, lane_pred] # det_pred: [bs, num_anchors, 85] → 经NMS后得boxes [N,6] (x1,y1,x2,y2,conf,cls) # seg_pred: [bs, 1, 384, 640] → sigmoid后二值化阈值0.5 # lane_pred: [bs, 16] → reshape为[8,2]经B样条插值得到50个(x,y)点 # 步骤1可行驶区域过滤检测框 drivable_mask (seg_pred[0,0] 0.5).cpu().numpy() # [384,640] for box in boxes: x1, y1, x2, y2 map(int, box[:4]) # 取检测框中心点所在区域的可行驶掩码值 cx, cy int((x1x2)//2), int((y1y2)//2) if cy 384 or cx 640 or not drivable_mask[cy, cx]: box[-2] * 0.3 # 置信度降权不直接丢弃保留弱信号 # 步骤2车道线几何校验 lane_points spline_interpolate(lane_pred[0]) # 得到50个点 # 检查是否满足车道线基本几何约束 if not is_monotonic_in_y(lane_points): # y坐标必须严格递增从近到远 lane_points fit_straight_line(lane_points[:20]) # 仅用近端20点拟合直线 if curvature(lane_points) 0.05: # 曲率过大则平滑 lane_points gaussian_filter1d(lane_points, sigma2, axis0) # 步骤3生成结构化输出 output { drivable_area: drivable_mask.tolist(), # 供路径规划模块使用 lanes: [lane_points.tolist()], # 左侧车道线YOLOP默认输出 objects: [{class: cls_names[int(box[5])], bbox: box[:4].tolist(), confidence: float(box[4])} for box in boxes if box[4]0.4] }这个后处理链路的价值在于它把深度学习的“概率输出”转化成了规则引擎可消费的“确定性结构”。比如is_monotonic_in_y()校验就是防止模型在颠簸路段误输出“Z字形”车道线而curvature限制则规避了急弯处因透视畸变导致的曲率误估。这些看似简单的规则实则是连接AI与汽车电子控制单元ECU的“翻译器”。4. YOLOP的实操全流程从环境搭建到真车部署的完整记录4.1 环境准备与依赖安装避开CUDA版本陷阱YOLOP对CUDA/cuDNN版本有隐性要求踩坑成本极高。以下是经过RTX 3060/3090/Tesla T4全平台验证的配置操作系统Ubuntu 20.04 LTS严禁用22.04其默认GCC 11.2与PyTorch 1.10编译不兼容CUDA11.3必须11.4及以上版本会导致Deformable Conv核函数崩溃cuDNN8.2.1与CUDA 11.3完美匹配PyTorch1.10.0cu113严禁用1.11或更高版本其autograd引擎在多任务梯度回传时存在内存泄漏安装命令按顺序执行缺一不可# 1. 卸载可能冲突的旧版本 sudo apt-get remove --purge nvidia-cuda-toolkit sudo apt-get autoremove # 2. 安装CUDA 11.3官网下载.run文件 sudo sh cuda_11.3.1_465.19.01_linux.run --silent --override --toolkit --samples # 3. 安装cuDNN 8.2.1需注册NVIDIA账号下载tgz包 tar -xzvf cudnn-11.3-linux-x64-v8.2.1.32.tgz sudo cp cuda/include/cudnn*.h /usr/local/cuda/include sudo cp cuda/lib/libcudnn* /usr/local/cuda/lib64 sudo chmod ar /usr/local/cuda/include/cudnn*.h /usr/local/cuda/lib64/libcudnn* # 4. 创建conda环境并安装PyTorch conda create -n yolop python3.8 conda activate yolop pip install torch1.10.0cu113 torchvision0.11.1cu113 torchaudio0.10.0cu113 -f https://download.pytorch.org/whl/torch_stable.html # 5. 安装YOLOP依赖注意opencv版本 pip install opencv-python4.5.5.64 # 4.6版本与YOLOP的cv2.resize存在内存对齐bug pip install numpy1.21.6 # 1.22版本在多线程数据加载时偶发segmentation fault提示安装完务必运行python -c import torch; print(torch.cuda.is_available())确认CUDA可用。若返回False请检查/usr/local/cuda软链接是否指向11.3ls -l /usr/local/cuda常见错误是系统残留11.2链接。4.2 数据集构建与验证用50张图快速建立baseline在正式训练前强烈建议用极小数据集50张跑通全流程验证环境与数据链路。我们设计了一个“50图快速验证法”数据选取从自采视频中截取50帧确保覆盖白天直路15张、夜间直路10张、白天弯道10张、隧道出口10张、雨天5张。标注仅标注这50张但严格遵循前述标注规范重点检查车道线起止点、可行驶区域闭合性。生成数据集结构yolop_data/ ├── images/ │ ├── 00001.jpg ... 00050.jpg ├── labels/ │ ├── 00001.txt (YOLO格式检测标签) ├── masks/ │ ├── 00001.png (可行驶区域二值掩码255可行驶) └── lanes/ ├── 00001.json (B样条控制点坐标列表)启动训练仅10个epoch快速验证python train.py --data data/yolop_custom.yaml \ --cfg models/yolop.yaml \ --weights \ --epochs 10 \ --batch-size 4 \ --name yolop_debug若10个epoch后val/seg_iou 0.65 且val/lane_f1 0.55则说明环境、数据、代码均正常若任一指标0.3立即停机排查——大概率是标注格式错误如mask png保存为RGB而非灰度或路径配置错误。4.3 模型训练与监控读懂tensorboard里的每一个曲线YOLOP训练时tensorboard会生成6条核心曲线需重点关注train/box_lossval/box_loss检测框回归损失。正常应呈指数衰减若val曲线在50epoch后突然上扬说明过拟合需提前终止。train/seg_iouval/seg_iou可行驶区域IoU。val值稳定在0.75±0.03为佳。若持续低于0.6检查mask标注是否漏标了施工区临时通道。train/lane_f1val/lane_f1车道线F1分数。这是最敏感的指标——val曲线若在80epoch后停滞在0.62而box_loss仍在降说明模型已学会“猜”检测框但车道线几何理解未突破。此时应启用Lane-Aware Data Augmentation在datasets.py中添加随机车道线偏移±5像素和对比度扰动0.7~1.3可提升0.03~0.05 F1。我们曾遇到val/seg_iou在0.72反复震荡无法突破最终发现是数据集中有12张图像的mask被错误保存为PNG-24位含alpha通道导致读取时数值溢出。用identify -format %[channels] image.png批量检查后修复问题立解。4.4 模型导出与TensorRT加速从PyTorch到嵌入式芯片的最后一步YOLOP官方未提供TensorRT部署脚本但实测证明其结构极适合TRT优化。以下是我们在Orin AGX上完成的完整流程耗时约4小时PyTorch模型导出为ONNX# export_onnx.py import torch from models.yolop import YOLOP model YOLOP() model.load_state_dict(torch.load(weights/best.pt)[model].state_dict()) model.eval() dummy_input torch.randn(1, 3, 384, 640) # 注意H,W顺序YOLOP输入是H×W torch.onnx.export(model, dummy_input, yolop.onnx, input_names[input], output_names[det, seg, lane], dynamic_axes{input: {0: batch}, det: {0: batch}, seg: {0: batch}, lane: {0: batch}}, opset_version11) # 必须用opset1112不支持Deformable ConvTensorRT引擎构建trtexec命令trtexec --onnxyolop.onnx \ --saveEngineyolop.engine \ --fp16 \ --workspace3072 \ --minShapesinput:1x3x384x640 \ --optShapesinput:4x3x384x640 \ --maxShapesinput:8x3x384x640 \ --timingCacheFiletiming.cache关键参数说明--fp16必须开启Orin的FP16算力是INT8的2倍且YOLOP对精度不敏感。--workspace3072工作区内存设为3GB低于此值会导致Deformable Conv编译失败。--min/opt/maxShapes明确指定动态batch范围避免运行时重新编译。C推理验证核心代码片段// 加载引擎 IRuntime* runtime createInferRuntime(gLogger); ICudaEngine* engine runtime-deserializeCudaEngine(trtModelStream, size); IExecutionContext* context engine-createExecutionContext(); // 分配显存 void* buffers[3]; // input, det, seg, lane → 共4个但input为输入其余3个为输出 cudaMalloc(buffers[0], 3*384*640*4); // input: float32 cudaMalloc(buffers[1], 100*6*4); // det: 100个框×6维 cudaMalloc(buffers[2], 384*640*4); // seg: mask cudaMalloc(buffers[3], 16*4); // lane: 8个点×2坐标 // 执行推理 cudaMemcpy(buffers[0], host_input, 3*384*640*4, cudaMemcpyHostToDevice); context-executeV2(buffers); cudaMemcpy(host_det, buffers[1], 100*6*4, cudaMemcpyDeviceToHost);实测结果在Orin AGX上YOLOP TensorRT引擎的平均推理时间为42.3msbatch1较PyTorch原生推理118ms提速2.8倍完全满足车载实时性要求。且引擎体积仅127MB可轻松烧录至eMMC存储。5. YOLOP的常见问题与实战排障那些文档里不会写的坑5.1 “模型不收敛”问题的三层归因法当训练loss不降、metrics不上升时切忌盲目调参。我们建立了一套三级排查法Level 1数据层占问题的65%检查images/与labels/文件名是否完全一致大小写、扩展名、空格。用python utils/check_dataset.py --data data/yolop_custom.yaml运行官方校验脚本重点看Missing labels和Invalid bounding boxes报错。抽查5张图像用cv2.imshow()同时显示原图、mask、lane overlay确认标注无错位常见于resize后未同步更新标注坐标。Level 2环境层占问题的25%运行nvidia-smi确认GPU显存未被其他进程占用。检查torch.__version__与torch.version.cuda是否匹配如1.10.0cu113。在train.py开头插入torch.backends.cudnn.enabled False临时禁用cuDNN排除其内部优化bug。Level 3模型层占问题的10%将hyp.yaml中所有损失权重设为1.0观察各loss分量是否同步下降。若仅seg_loss下降而lane_loss不变说明LFEM模块未生效检查models/common.py中Deformable Conv的im2col_step参数是否设为16必须。用torchsummary.summary(model, (3,384,640))打印模型结构确认P3输出尺寸为[1, 128, 48, 80]若为[1, 128, 47, 79]说明padding计算错误需修改common.py中CSPBlock的stride逻辑。5.2 “车道线抖动”问题的根因与对策在实车测试中最常被抱怨的是“车道线在屏幕上跳来跳去”。这不是模型问题而是时序滤波缺失。YOLOP输出的是单帧结果而人类驾驶员依赖连续帧的运动一致性。我们的解决方案是卡尔曼滤波推荐为每条车道线建模为匀速运动状态向量[x,y,vx,vy]观测值为B样条控制点。在postprocess.py中添加kf cv2.KalmanFilter(4,2) kf.measurementMatrix np.array([[1,0,0,0], [0,1,0,0]], np.float32) kf.transitionMatrix np.array([[1,0,1,0], [0,1,0,1], [0,0,1,0], [0,0,0,1]], np.float32) # 每帧用当前lane_points[0]更新kf输出平滑后的点滑动窗口中值滤波轻量级存储最近5帧的控制点对每个坐标维度取中值。实测延迟3ms抖动消除率达82%。注意切勿对分割掩码做时序滤波这会导致可行驶区域在车辆转弯时出现“拖影”引发路径规划误判。5.3 “夜间检测失效”问题的针对性优化YOLOP在暗光下性能断崖式下跌根本原因是其主干网络缺乏低照度鲁棒性。我们不推荐重训整个模型成本过高而是采用两阶段增强法前端增强在摄像头驱动层注入自适应直方图均衡AHE。在utils/datasets.py的LoadImages类中于cv2.imread()后插入clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8,8)) yuv cv2.cvtColor(img, cv2.COLOR_BGR2YUV) yuv[:,:,0] clahe.apply(yuv[:,:,0]) img cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR)后端补偿在推理后对seg_pred掩码应用亮度自适应阈值# 计算图像全局亮度 mean_lum img.mean() # 动态调整分割阈值 seg_thresh 0.3 (0.7 * (1 - mean_lum/255)) # 亮度越低阈值越松 drivable_mask (seg_pred[0,0] seg_thresh).cpu().numpy()该方案在实测中将夜间可行驶区域IoU从0.41提升至0