下面给你一个针对后视镜折叠场景的可落地方案,目标是在缺少标注的前提下优先提升 FSD 分支效果,并尽量不破坏 PSD/RM 的现有性能。方案分为数据、训练、评估与落地四个部分,尽量贴合你现在的工程结构(train2.py 多任务训练)。
1. 数据策略:用"几何+纹理+遮挡"三类增强模拟后视镜折叠
后视镜折叠导致视野变窄,车辆本体遮挡出现在左右两侧,并形成"粉色块+黑色车体遮挡"的结构。针对这一特性,建议分层做增强:
1) 几何裁剪模拟视野变化(最关键)
- 左右裁剪或缩放重映射:从正常俯视图裁掉两侧区域,模拟"视野缩小"。
- 拼接遮挡:用"车辆轮廓遮挡块"覆盖左右(模拟后视镜折叠后的车体遮挡区域),遮挡区域可用固定模板或随机多边形。
- 车辆本体遮挡:在图中间加入大面积黑色块(模拟车体),遮挡与场景中真实车辆比例相近。
2) 纹理与颜色扰动
- 亮度、对比度、色温变化
- HDR 模拟:局部过曝/欠曝
- 黑色块添加轻微纹理噪声(避免模型过度依赖"纯黑")
3) FSD 专项增强(仅对 FSD 分支强制)
- 对遮挡区域生成"不可行驶"mask(或忽略区域)
- 对遮挡边缘随机扩张/腐蚀,提高边界鲁棒性
2. 训练策略:多任务不动,FSD 增强优先
1) 保持多任务结构,但提高 FSD 权重
- loss 权重中提升 FSD 的权重,例如:FSD:PSD:RM = 3:1:1
- 或前期 FSD 权重大,后期逐步回调至均衡
2) 冻结 PSD/RM backbone 的低层
- 若共享 backbone:冻结前几层(或使用低学习率)
- FSD 分支学习率可略大(如 2x)
3) "两阶段微调"
- 阶段1:只用增强数据训练 FSD(其他分支冻结)
- 阶段2:正常多任务训练,加入少量增强数据混合
3. 标注缺失情况下的伪标签策略(可选)
如果你有未标注后视镜折叠图:
-
用原模型推断 FSD,生成伪标签
-
只保留高置信度区域(比如置信度 > 0.7)
-
伪标签区域与遮挡增强混合训练
这种方法可以让 FSD 更快适应新场景。
4. 评估与验收指标
为了快速验证 FSD 改进效果,建议:
- 用 20~50 张折叠场景图人工粗标(只需 FSD)
- 评估指标:mIoU、F1、边界误差
- 特别观察:
- 车辆两侧遮挡边界是否被误判为可行驶
- 中央车体区域是否被正确屏蔽
- 粉色块边缘是否稳定
推荐的最小实现路线(低成本)
- 做遮挡+视野裁剪增强(最关键)
- FSD loss 权重提高
- 训练 1~2 个 epoch 观察 FSD 提升趋势
- 视效果决定是否引入伪标签
如果你希望,我可以进一步结合 train2.py 的具体训练流程,帮你:
- 指出具体插入数据增强的位置
- 给出 FSD loss 权重修改建议
- 帮你写出可执行的增强代码模块
你只要告诉我现在的 train2.py 数据加载与增强结构即可。
关于 训练策略,因为我的三个分支是共用backbone的,然后三个任务分别使用三个不同的头去输出,这样的话,有什么好的训练方案吗? @yolov5s_custom_seg_big.yaml
你这个结构(共享 backbone + 多头输出)是标准多任务范式,完全可以做"阶段式微调 + 任务权重动态"来优先适配 FSD,同时尽量不损伤 PSD/RM。结合你现在的 yolov5s_custom_seg_big.yaml,建议如下(从可实施到进阶):
1) 最稳妥的训练策略(推荐)
阶段 A:只优化 FSD
- 冻结 backbone 的前半部分(低层特征保稳定),只训 FSD 相关头与高层 backbone。
- PSD/RM 头不更新或极低学习率。
- 目的:让模型快速适应"后视镜折叠"对可行驶区域的改变。
阶段 B:多任务联合,FSD 权重更大
- 恢复多头训练,但 FSD loss 权重大(例如 3:1:1 或 4:1:1)。
- 继续保持 PSD/RM 的小学习率,避免退化。
2) 任务权重与梯度冲突处理
多任务下常见问题是"任务互相抢 backbone 的梯度":
简单有效做法
- 固定权重:loss = 3*FSD + 1*PSD + 1*RM
- 或使用 前期 FSD 权重大,后期平衡(warmup 调整)
进阶做法(如有实现成本)
- GradNorm:按任务学习难度自动调 loss 权重
- PCGrad:在反向传播时消除任务冲突梯度
(这两种要改训练代码,效果通常优于手动权重)
3) 共享 backbone 下的稳定技巧
1) 任务专用 BN
- 共享卷积,但 BN 分支独立
- 可显著减少任务间分布冲突(尤其折叠场景分布变化大)
2) Adapter / 插拔层(成本低)
- 在 backbone 高层加一个 FSD 专用轻量 adapter(1×1 Conv 或小 MLP)
- FSD 走 adapter,PSD/RM 走原 backbone
4) 数据混合策略(非常关键)
- FSD 使用"折叠增强数据 + 原始数据混合"
- PSD/RM 只用原始或轻度增强数据
这样能防止 PSD/RM 被折叠增强污染。
5) 如果只能做最少改动的方案
- 冻结 backbone 前半段
- FSD loss 提高到 3 倍
- 折叠增强只喂给 FSD
这三个动作成本最低、效果通常最明显。
如果你愿意,我可以直接帮你改 train2.py 的 loss 权重、冻结策略,并加一个 FSD 专用的数据增强开关。只需要你告诉我:
- loss 权重目前在哪里定义
- backbone/head 在训练中如何冻结
- 数据增强在哪个类/函数里做
已按你的要求把"后视镜折叠粉色色块"增强接入到检测(PSD)、FSD分割、RM分割三条分支,并提供了可配置车辆位置的入口。
关键实现位置:
- 新增统一配置与工具:utils/mirror_fold.py
- 检测数据增强与标签过滤:utils/datasets.py
- FSD/RM 分割图像与mask同步增强:SegmentationDataset.py
你需要配置的地方
在 utils/mirror_fold.py 里配置 4 种分辨率的车辆位置:
MIRROR_FOLD_CAR_BOXES = {
(width, height): (x1, y1, x2, y2),
}
说明:
- (x1, y1, x2, y2) 是车辆黑色区域在原图上的像素坐标
- 粉色色块会自动在车辆左右两侧,从车头到车尾(y1~y2)延伸到图像边缘
如果某些分辨率没填,默认不会应用(也可启用比例兜底 MIRROR_FOLD_CAR_BOX_RATIOS)。
标签处理策略(已实现)
- FSD:粉色色块区域 → 视为可行驶(FSD_PINK_VALUE=1)
- RM:粉色色块区域 → 视为背景(RM_PINK_VALUE=0)
- PSD:粉色色块区域内的目标 → 删除(按 bbox 中心点判断)
> 如果你的 FSD/RM 类别 id 不一致,只需修改 utils/mirror_fold.py 里的 FSD_PINK_VALUE、RM_PINK_VALUE。
额外说明
- 现在默认 MIRROR_FOLD_PROB=1.0,即训练中每张图都强制应用。
- 如果你希望以概率方式混合真实/模拟数据,可调成 0.5 等。
如果你愿意,我可以继续帮你:
- 自动统计每种分辨率对应的车辆位置(从样例图自动估计)
- 在训练日志里打印当前生效的分辨率与车辆位置
- 做一个可视化预览脚本,快速验增强效果
只要把你 4 种分辨率对应的车辆坐标告诉我即可。
详细解释下对于每一个分支的训练,你都是怎么实现模拟数据的
已按"分支维度"说明三条训练里模拟数据的具体实现方式,并标出关键代码位置。
统一配置与粉色遮挡生成
所有分支共用 utils/mirror_fold.py 的配置和工具函数:
- 配置不同分辨率的车辆黑色区域
- 生成粉色遮挡区域(车头~车尾高度,左右延伸到边缘)
- 控制启用与概率
mirror_fold.pyLines 1-64
MIRROR_FOLD_CAR_BOXES = {
(width, height): (x1, y1, x2, y2),
}
MIRROR_FOLD_ENABLE = True
MIRROR_FOLD_PROB = 1.0
FSD_PINK_VALUE = 1
RM_PINK_VALUE = 0
def get_car_box_for_shape(width: int, height: int) -> Optional[Tuple[int, int, int, int]]:
...
def build_pink_mask(width: int, height: int, car_box: Tuple[int, int, int, int]) -> Optional[np.ndarray]:
...
def should_apply_mirror_fold() -> bool:
return MIRROR_FOLD_ENABLE and random.random() < MIRROR_FOLD_PROB
PSD(检测分支)
实现位置:utils/datasets.py 的 LoadImagesAndLabels_v5face.getitem
流程:
- 正常加载图像与检测标签(含 letterbox/mosaic/mixup)
- 在几何增强前插入折叠模拟:
- 计算车体框在当前图上的位置
- 生成粉色遮挡
- 删除落在粉色区内的检测框(按 bbox 中心点判断)
关键代码:
datasets.pyLines 189-240
def _mirror_fold_box_for_letterbox(orig_hw, resized_hw, ratio, pad):
...
def _apply_mirror_fold_det(img, labels, car_box):
...
img[pink_mask] = MIRROR_FOLD_PINK_COLOR_BGR
...
keep = ~pink_mask[cy, cx]
return img, labels[keep]
datasets.pyLines 992-1088
if self.augment and should_apply_mirror_fold():
if mosaic:
car_box = get_car_box_for_shape(w, h)
else:
car_box = _mirror_fold_box_for_letterbox((h0, w0), (h, w), ratio, pad)
if car_box is not None:
img, labels = _apply_mirror_fold_det(img, labels, car_box)
效果:PSD 在粉色区域"看不到任何东西",训练时这些区域中的目标自动被过滤掉。
FSD(可行驶区域分割)
实现位置:SegmentationDataset.py 的 CustomSegmentation.getitem
流程:
- 读图 + 读 mask
- 若训练阶段且启用折叠增强:
- 生成粉色遮挡
- 图像粉色覆盖
- mask 粉色区域直接置为 FSD_PINK_VALUE=1
关键代码:
SegmentationDataset.pyLines 787-855
if self.mode == 'train' and should_apply_mirror_fold():
img_np = np.array(img)
mask_np = np.array(mask)
h, w = img_np.shape[:2]
car_box = get_car_box_for_shape(w, h)
if car_box is not None:
pink_mask = build_pink_mask(w, h, car_box)
if pink_mask is not None:
img_np[pink_mask] = MIRROR_FOLD_PINK_COLOR_RGB
mask_np[pink_mask] = FSD_PINK_VALUE
img = Image.fromarray(img_np)
mask = Image.fromarray(mask_np)
效果:FSD 学到"粉色遮挡区=可行驶"。
RM(路面标识分割)
实现位置:SegmentationDataset.py 的 RMSegmentation.getitem
流程同 FSD,但 mask 粉色区域置为背景:
SegmentationDataset.pyLines 1004-1015
if self.mode == 'train' and should_apply_mirror_fold():
img_np = np.array(img)
mask_np = np.array(mask)
h, w = img_np.shape[:2]
car_box = get_car_box_for_shape(w, h)
if car_box is not None:
pink_mask = build_pink_mask(w, h, car_box)
if pink_mask is not None:
img_np[pink_mask] = MIRROR_FOLD_PINK_COLOR_RGB
mask_np[pink_mask] = RM_PINK_VALUE
img = Image.fromarray(img_np)
mask = Image.fromarray(mask_np)
效果:RM 学到"粉色遮挡区=无路面标识"。
小结(每个分支的模拟方式)
- PSD:粉色遮挡 + 删除遮挡区域内目标
- FSD:粉色遮挡 + mask 设为可行驶
- RM:粉色遮挡 + mask 设为背景
如果你希望:
- 让 PSD 也保留"遮挡区域"但将目标缩小/裁剪
- 让 FSD 粉色区域是"ignore"而不是可行驶
我可以继续帮你改。
删除落在粉色区内的检测框(按 bbox 中心点判断)和训练时这些区域中的目标自动被过滤掉,是怎么实现的?
实现就在 utils/datasets.py 的 _apply_mirror_fold_det。逻辑是:先生成粉色遮挡布尔 mask,然后用 bbox 中心点坐标索引 mask,落在粉色区域的框被过滤掉。
datasets.pyLines 224-240
def _apply_mirror_fold_det(img, labels, car_box):
h, w = img.shape[:2]
pink_mask = build_pink_mask(w, h, car_box)
if pink_mask is None:
return img, labels
img[pink_mask] = MIRROR_FOLD_PINK_COLOR_BGR
if labels is None:
return img, labels
labels = labels if isinstance(labels, np.ndarray) else np.array(labels)
if labels.size == 0:
return img, labels
cx = ((labels[:, 1] + labels[:, 3]) * 0.5).round().astype(int)
cy = ((labels[:, 2] + labels[:, 4]) * 0.5).round().astype(int)
cx = np.clip(cx, 0, w - 1)
cy = np.clip(cy, 0, h - 1)
keep = ~pink_mask[cy, cx]
return img, labels[keep]
要点:
- pink_mask[cy, cx] 表示 bbox 中心是否落在粉色区
- keep = ~pink_mask[cy, cx] 只保留不在粉色区的框
- labels[keep] 就是"自动过滤掉"后的检测目标
已加好"预处理后可视化保存"的功能,三条分支都会把预处理后的图像保存,并且把标签画在图上。你只需打开开关即可。
如何启用
在 utils/mirror_fold.py:
- 把 MIRROR_FOLD_DEBUG_SAVE = False 改为 True
- 可选调整保存目录、数量与透明度
mirror_fold.pyLines 1-40
MIRROR_FOLD_DEBUG_SAVE = False
MIRROR_FOLD_DEBUG_DIR = "runs/mirror_fold_debug"
MIRROR_FOLD_DEBUG_MAX = 200
MIRROR_FOLD_DEBUG_EVERY = 1
MIRROR_FOLD_DEBUG_ALPHA = 0.45
保存路径示例:
- 检测:runs/mirror_fold_debug/det
- FSD:runs/mirror_fold_debug/fsd
- RM:runs/mirror_fold_debug/rm
PSD 检测分支:保存带框图
在 utils/datasets.py 的 LoadImagesAndLabels_v5face.getitem 中:
- 完成所有增强(含 mirror_fold、随机透视、HSV)后
- 绘制 bbox(按当前的 xyxy 像素坐标)并保存
关键代码:
datasets.pyLines 1068-1088
debug_path = get_debug_save_path("det", self.img_files[index], "jpg") if self.augment else None
if debug_path:
debug_img = _draw_det_labels_xyxy(img, labels)
cv2.imwrite(debug_path, debug_img)
绘制框逻辑:
datasets.pyLines 224-240
def _draw_det_labels_xyxy(img, labels):
...
cv2.rectangle(out, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.putText(out, str(cls_id), (x1, max(0, y1 - 4)), ...)
FSD 分割分支:保存叠加 mask 的图
在 SegmentationDataset.py 的 CustomSegmentation.getitem:
- 训练阶段完成 _sync_transform
- mask 处理完成后保存
- mask 用透明度叠加在图上
关键代码:
SegmentationDataset.pyLines 857-885
mask[mask == 127] = -1
mask[mask==255] = -1
_save_seg_debug("fsd", img, mask, imagepath)
RM 分割分支:保存叠加 mask 的图
在 SegmentationDataset.py 的 RMSegmentation.getitem:
- 训练阶段处理完 mask 后保存
关键代码:
SegmentationDataset.pyLines 1187-1196
mask[mask == 127] = -1
mask[mask == 14] = 0
mask[mask == 15] = 0
mask[mask==255] = 7
_save_seg_debug("rm", img, mask, imagepath)
如果你希望:
- 只保存经过后视镜折叠增强的样本
- 或加上"原图 vs 预处理图对比拼接"
我可以继续帮你扩展。
下面给你一个2页 PPT 的汇报结构,聚焦"用数据增强解决后视镜折叠数据不足",简洁可直接套用。
第1页:问题与思路(Why)
标题:后视镜折叠场景数据不足的挑战与方案
- 现象:后视镜折叠导致视野缩窄,车辆两侧出现粉色遮挡区
- 影响:FSD 误判明显,PSD/RM 也受遮挡干扰
- 困难:缺少折叠场景标注数据
- 方案:基于现有数据构造"折叠模拟增强",用伪场景替代真实标注
- 目标:快速适配新场景,同时保持原有分支性能
图示建议:一张正常图 + 折叠示例图(粉色遮挡)对比
第2页:算法实现(How)
标题:后视镜折叠增强策略与标签规则
- 视觉增强(图像层)
- 根据不同分辨率配置车辆位置
- 生成粉色遮挡块:从车头到车尾,左右延伸到图像边缘
- 可控概率/数量,混合原始数据训练
- 标签适配(任务层)
- PSD:遮挡区域内目标删除(避免错误监督)
- RM:粉色区视为背景(无路面标识)
- FSD:粉色区视为可行驶(无遮挡、无标识)
- 训练策略(简述即可)
- 三分支一起训练,保持任务一致性
- 保留原有增强,叠加折叠模拟
图示建议:
- 一张"增强后图像 + PSD框 + FSD/RM mask叠加"
- 用箭头标注 "粉色区 → 标签规则"
如果你愿意,我可以帮你把这两页 PPT 的文字排版直接写成可用模板(标题+要点+图示说明),或者帮你做一版更"报告风"的表述。
帮你做一版更"报告风"的表述。我又让同事帮我采集一部分带有粉色色块的数据去标主,但是大头还是在我的数据增强这边。我想体现出模型从数据采集到训练验证的全流程
下面是更"报告风"的 2 页 PPT 文案,强调"少量真实采集 + 大量增强模拟"的闭环流程,并覆盖"采集→标注→训练→验证"的全流程。你可以直接放到 PPT 里。
第1页|项目背景与数据策略
标题:后视镜折叠场景适配:数据不足下的双轨方案
问题背景
- 后视镜折叠后视野发生结构性变化,模型输入出现粉色遮挡区
- 现有训练数据主要来自正常场景,泛化能力不足
数据策略(双轨并行)
- 真实采集 + 少量精标:同事补采一批折叠场景,作为真实锚点数据
- 增强模拟为主:基于原始数据构造"粉色遮挡"场景,扩大覆盖
核心目标
- 用较低标注成本完成模型适配
- 兼顾 FSD 强化与 PSD/RM 稳定性
第2页|全流程闭环与落地路径
标题:采集-标注-训练-验证全流程闭环
数据准备
- 原始数据:正常俯视图数据(主干数据)
- 真实折叠数据:小批量人工标注
- 模拟数据:基于车辆位置生成粉色遮挡区域
训练流程
- 三分支统一训练,增强样本与真实样本混合
- 任务标签规则同步适配:
- PSD:遮挡区目标过滤
- RM:遮挡区视为背景
- FSD:遮挡区视为可行驶
验证与评估
- 真实折叠样本作为重点评估集
- 关注指标:FSD 可行驶区域完整性、遮挡区误报率、PSD/RM 稳定性
落地输出
- 算法在"折叠输入"下稳定输出三分支结果
- 支持后续持续采集 → 迭代优化
如果你需要,我还可以给你补一页"结果展示页"(指标提升 + 可视化对比),或者直接帮你排成 PPT 页面的版式草图。