简介:目标检测在跨江桥梁养护场景中,常被用于自动识别路面裂缝、破损、积水及桥墩、拉索等资产要素。这份专题数据集由860张jpg原图与858个配套json标注文件组成,共1718个文件,压缩包约344.46MB,图像采集自真实桥梁环境,标注涵盖常见病害与专属结构元素。json文件由Labelme工具生成,包含像素级边界框与类别信息,可直接用于训练YOLO、Faster R-CNN、Mask R-CNN等目标检测模型;同时支持按训练集、验证集、测试集划分,便于交叉验证与超参数调优。资源聚焦桥梁环境下的病害与道路资产标定,兼顾通用缺陷与桥墩、拉索等特殊目标,可有效提升模型在该专项场景中的实用精度。目前已有2457人学习下载,适合计算机视觉研究者、算法工程师及桥梁监测系统开发者直接作为训练与评估的基础数据。
1. 目标检测上跨江大桥就翻车:病害和道路资产的标定数据集,才是决定训练效果的天花板
一套在公开数据集上跑出高 mAP 的目标检测模型,搬到跨江桥梁的路面巡检上,往往头几天还行,过了引桥段就开始疯狂误报——把伸缩缝当裂缝、把护栏倒影当成坑槽、把江面反光误判成积水。算法工程师第一反应是调模型,但真正卡住你的,大概率不是网络结构,而是训练数据本身:跨江桥梁路面病害和道路资产标定数据集的类别定义、标注质量和划分方式,直接决定这模型在真实桥面上能不能用。这里说的“标定”,指的是对病害和资产画框、归类的数据标定,不是相机内外参标定、激光雷达外参那套几何标定,两码事,别混淆。
这篇笔记,我按自己做过桥面巡检数据工程的路子,从采集、标定、转格式、训练到验证,把能直接抄的参数和会踩的坑讲清楚。适合正在做桥梁养护信息化、市政道路资产盘点,或者想用 YOLO 系列训自己数据集的工程师——重点是让你拿到的不是一堆“能跑”的代码,而是一套能压住现场噪声的数据标定方案。
2. 跨江桥面数据采集方案:机位、重叠率和样本长尾,先想明白再开机
2.1 采集机位怎么选:巡检车俯视还是无人机斜视
跨江桥梁的路面病害检测,主流采集方式是两种:巡检车把相机固定在车顶横梁上,垂直俯视桥面;或者无人机沿桥面航线拍摄。我的建议是,病害检测优先用俯视机位——裂缝、坑槽、车辙这些病害在垂直视角下形变最小,标注框的边界最干净。无人机斜视拍出来的裂缝宽窄不一,同一处病害在相邻两帧里的宽度能差三倍,标定的人会崩溃。
相机选型上,别用自动变焦镜头。自动对焦和变焦会在行进中不停改变等效焦距,导致后期换算像素尺寸、做拼接时全是窟窿。固定光圈、固定焦距,把快门调到 1/1000 以上,ISO 让它在 100-400 之间自由浮动即可。桥面本身是浅色沥青,跨江场景还有江面反光,测光模式建议直接用中央重点平均,别用全局平均——全局平均会被江水高光区带偏。
如果目标是病害检测,横向覆盖一条 3.75m 标准车道,建议把相机架到离地 2.5m 左右,镜头向下,视场覆盖半条车道宽度。这样单张图里病害占比合理,小裂缝也不会被压成 8 个像素。如果用无人机,保持在桥面正上方 15m 以内,速度不超过 5m/s,快门优先。
2.2 重叠率、采样间隔和光线窗口:跨江场景的现场铁律
采集不是按快门乱拍,而是按“里程触发”或“时间触发”。常见的做法是,巡检车以 40km/h 匀速行驶,用 GPS 里程计每 2m 触发一次拍摄,两张相邻图像的重叠率大约在 70% 上下。重叠率太低,同一个病害被切成两半,标注和后面做拼接都麻烦;重叠率太高,数据冗余严重,训练验证划分时很容易把同一病害的连续帧泄进两个集合里。
光线窗口是跨江桥梁独有的问题。桥面没有遮挡,正午顶光会让裂缝变浅、阴影变没,傍晚侧光又让伸缩缝的影子看起来像裂缝。我一般选在上午 9:30-11:00 或下午 14:30-16:00 采集,这时候太阳高度角适中,沥青铺装上裂缝的明暗对比最强。阴天是备选,但江面起雾时别拍,水汽会让标线边缘发虚,后期标定判断“这是标线磨损还是污渍”纯靠猜。
采集时记得在每个桥跨的起始位置拍一张带里程桩号的标识牌,作为后续分组划分的锚点。这个动作很小,但做训练验证集按桥跨分组时,它就是命根子。
2.3 病害和道路资产的类别清单:先收敛大项,再补长尾
跨江桥梁路面病害和道路资产,按我常用的做法,能合并的合并:
| 一级类别 | 细粒度条目 | 标注建议 |
|---|---|---|
| 路面病害 | 横向裂缝、纵向裂缝、网状/龟裂、坑槽、修补、车辙、桥面铺装松散 | 前四种先建类,龟裂在低分辨率下可先归为网状裂缝 |
| 标线类 | 车道线、导流线、斑马线、停止线、磨损标线 | 磨损标线单独建类,否则和“脏污”纠缠 |
| 桥梁构造 | 伸缩缝、桥面泄水孔、防抛网、护栏、灯杆 | 伸缩缝必须独立,否则必成裂缝误报的最大来源 |
| 交通设施 | 标志牌、里程碑、百米桩、诱导标、凸起路标 | 撞歪的标志牌归“标志牌”,不要建“倾斜标志”独立类 |
这四类 20 个左右类别,对第一版数据集够了。别一上来就把“裂缝宽度 3mm 以下细裂缝”和“3mm 以上粗裂缝”拆开——标注员在车拍图上量不准毫米级宽度,拆了只会让标注一致性崩掉。道路资产类别也一样,先做护栏、灯杆、标志牌这种高频且形状稳定的,再做垃圾桶、桥墩涂装剥落这种低频长尾。低频类别放进训练集只会让模型过拟合到那几十张图上,没有泛化价值。
类别定完后,写一份一页纸的标定规范,要写明每类的定义、最小框范围、遮挡时怎么处理、多目标重叠时优先级。这份规范,就是后面所有标注一致性的基石。
3. 用 LabelStudio 搭建跨江场景的标定数据集:从原始图片到 COCO/YOLO 训练数据
3.1 图片清洗与去重:先把强光照、偏色和连续重复帧清理掉
采集原始图片直接进标注,是新手最常见的浪费。跨江桥梁图片有两个典型问题:一是江面反光导致的局部过曝,相机自动曝光会把沥青路面压暗;二是连续帧高度重复,同一病害在 70% 重叠率下会出现 5 到 8 帧,全部标注既费人力又埋下数据泄漏隐患。
先跑一个清洗脚本,把模糊帧和近重复帧筛掉。模糊检测用拉普拉斯方差,阈值靠自己抽看十张图来定:
import cv2 import numpy as np import os src_dir = "raw_bridge" out_dir = "bridge_clean" os.makedirs(out_dir, exist_ok=True) skip_counter = 0 for fname in sorted(os.listdir(src_dir)): path = os.path.join(src_dir, fname) img = cv2.imread(path) if img is None: continue gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 计算拉普拉斯方差:值越小说明越模糊 lapvar = cv2.Laplacian(gray, cv2.CV_64F).var() if lapvar < 80: # 这个阈值要按自己的图抽样调整 skip_counter += 1 continue # 近重复帧检测:用前一帧的MSE,低于阈值就跳过 if "last_img" in locals(): mse = np.mean((gray.astype(np.float32) - last_gray.astype(np.float32)) ** 2) if mse < 15: skip_counter += 1 continue last_gray = gray.copy() cv2.imwrite(os.path.join(out_dir, fname), img) print(f"保留 {len(os.listdir(out_dir))} 张,跳过 {skip_counter} 张")这个脚本的逻辑是两层过滤:第一层对每一帧计算拉普拉斯方差,小于阈值认定失焦或运动模糊,直接丢弃;桥面巡检车速快,1/1000 快门也偶尔出拖影,这一层能省下很多无效标注工时。第二层用前一帧的灰度图做 MSE 对比,两帧太接近就跳过——保留的是真正“内容有变化”的帧。参数上,拉普拉斯阈值 80 和 MSE 阈值 15 是经验初值,启动前抽 30 张图看一下,总要扔掉大约 20% 的帧才正常;发现留着大量半透明的同一场景,就把 MSE 阈值调高到 25。
3.2 在 LabelStudio 里配置跨桥场景标签:画框、快捷键与多人一致性
清洗后的图放进 LabelStudio。安装和启动直接按官方 quickstart 走:pip install label-studio,然后label-studio start。项目里创建目标检测项目后,最关键的是标签配置——我建议直接把前面定的四类 20 项铺成按钮,不要用层级树,标注员点数越少越好。
用 Settings -> Labeling Interface 替换成下面的 XML 配置:
<View> <Image name="image" value="$image" zoom="true" zoomControl="true" showDefaultWatermark="false"/> <RectangleLabels name="label" toName="image" strokeWidth="3"> <Label value="横向裂缝" background="#ff0000"/> <Label value="纵向裂缝" background="#ff6600"/> <Label value="网状裂缝" background="#ffff00"/> <Label value="坑槽" background="#00ff00"/> <Label value="修补" background="#00ffff"/> <Label value="伸缩缝" background="#0000ff"/> <Label value="车道线" background="#ff00ff"/> <Label value="损坏标线" background="#800080"/> <Label value="护栏" background="#008080"/> <Label value="灯杆" background="#808000"/> <Label value="标志牌" background="#000000"/> <Label value="泄水孔" background="#ff1493"/> </RectangleLabels> </View>配置里的门道在zoom="true"和strokeWidth="3"。桥面裂缝往往只有几个像素宽,默认画框工具在缩略视图下根本点不准;开 zoom 后标注员能放大到 400%,框的边界误差才能压到 3 像素以内。strokeWidth 加大到 3,是为了让已经画好的框在深色沥青背景下不被视觉吞掉——这个细节直接影响复查效率。标签值的顺序不要随意改,后面导出 COCO 的 category_id 是按这个按钮顺序生成的,改一次顺序,之前所有标注全部错位。
多人标注时,我给每条图的右下角加一个隐藏二维码水印(标注完成前),每个标注员领 30 张图做同一条标线,回收后算 pairwise IoU,一致性低于 0.7 的人要回炉看规范。成本不高,但能挡住大部分“自由发挥式标注”。
3.3 导出 COCO 并转 YOLO:分组划分的脚本与四个边界坑
LabelStudio 支持直接导出 COCO JSON。导出后,需要按“桥跨/桩号”分组划分 train/val/test,而不能按文件随机划分——这是跨江桥面数据工程里最容易被忽略的一步。同一桥跨的连续帧背景高度相似,随机划分会让模型在验证集上捡到训练集见过的桥面纹理,现场换一座桥立刻露馅。
下面的脚本把 COCO JSON 转成 YOLO txt,并实现分组划分:
import json import os import random import shutil # 1. 读COCO标注 with open("bridge_coco.json", "r", encoding="utf-8") as f: coco = json.load(f) # 2. 构建 image_id -> file_name 与 anno 映射 img_info = {img["id"]: img for img in coco["images"]} annos_by_img = {} for ann in coco["annotations"]: annos_by_img.setdefault(ann["image_id"], []).append(ann) cat_id2name = {cat["id"]: cat["name"] for cat in coco["categories"]} # 3. 按“桥跨前缀”分组:文件名形如 bridge01_000123.jpg groups = {} for img_id, info in img_info.items(): fname = os.path.basename(info["file_name"]) prefix = fname.split("_")[0] # 取bridge01作为分组键 groups.setdefault(prefix, []).append(img_id) random.seed(42) g_keys = list(groups.keys()) random.shuffle(g_keys) # 桥跨分组:80% train,10% val,10% test n = len(g_keys) train_groups = g_keys[:int(0.8*n)] val_groups = g_keys[int(0.8*n):int(0.9*n)] test_groups = g_keys[int(0.9*n):] for split, group_list in [("train", train_groups), ("val", val_groups), ("test", test_groups)]: os.makedirs(f"bridge_dataset/{split}", exist_ok=True) os.makedirs(f"bridge_dataset/{split}/images", exist_ok=True) os.makedirs(f"bridge_dataset/{split}/labels", exist_ok=True) for g in group_list: for img_id in groups[g]: info = img_info[img_id] fname = os.path.basename(info["file_name"]) src = os.path.join("bridge_clean", fname) shutil.copy(src, f"bridge_dataset/{split}/images/{fname}") w, h = info["width"], info["height"] lines = [] for ann in annos_by_img.get(img_id, []): bbox = ann["bbox"] # COCO格式: [x, y, w, h] x, y, bw, bh = bbox # 归一化到YOLO格式 cx = (x + bw/2) / w cy = (y + bh/2) / h nw, nh = bw/w, bh/h cls_id = ann["category_id"] - 1 # YOLO类别从0开始 lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}") with open(f"bridge_dataset/{split}/labels/{os.path.splitext(fname)[0]}.txt", "w") as lf: lf.write("\n".join(lines)) print("划分完成", len(train_groups), len(val_groups), len(test_groups))脚本里最容易翻车的有四处:第一,COCO 的 bbox 是[x, y, w, h],y0 在左上角,YOLO 要的是中心点坐标加宽高,换算公式必须是cx = x + w/2,很多人直接拿 x 当 cx;第二,category_id 在 COCO 里从 1 开始,YOLO 类别从 0 开始,导出后忘减 1,训练时所有类别整体错位——最隐蔽的坑,指标看着正常,可视化才发现标签和框对不上;第三,分组键用文件名前缀,必须保证采集时同一个桥跨的文件名前缀一致,否则这步直接失控;第四,输出目录里 val 和 test 的标签也要存在,只给 train 打标签,后面验证脚本会报警。跑完脚本后,别急着训练,随便打开三张 train 图和一张 val 图,把画框结果叠加在原图上人工看一遍,这五分钟能省一天排错时间。
4. 用 YOLOv8 训练自己的跨江病害数据集:data.yaml、分辨率与断点续训
4.1 data.yaml 的写法:类别顺序必须和标定顺序一字不差
数据转好后,训练前先写data.yaml。我见过最多的训练翻车现场,就是这里类别顺序和 COCO 导出顺序不一致,模型训练全程 loss 正常,但预测时类别张冠李戴。所以 yaml 里的 names 列表,直接按第 2 章标定规范里的顺序抄,不要重新排序。
# bridge_dataset/data.yaml path: ./bridge_dataset # 数据集根目录 train: train/images # 训练图片目录 val: val/images # 验证图片目录 test: test/images # 测试图片目录 nc: 12 # 类别总数 names: 0: 横向裂缝 1: 纵向裂缝 2: 网状裂缝 3: 坑槽 4: 修补 5: 伸缩缝 6: 车道线 7: 损坏标线 8: 护栏 9: 灯杆 10: 标志牌 11: 泄水孔这里有一个取舍:如果你把“伸缩缝”单独标为一类,而不是混在裂缝里,模型在跨江桥面上会少掉 30% 以上的误报——伸缩缝的锯齿结构在视觉上就是横向裂缝的近亲,模型学不出区别的,必须靠类别定义强压。我在 2.3 节把伸缩缝独立出来,就是为这个。
4.2 训练命令与关键参数:1280 输入、mosaic 和冻结 backbone
用 ultralytics 的 YOLOv8 训练,命令行直接给:
yolo detect train \ model=yolov8m.pt \ data=bridge_dataset/data.yaml \ imgsz=1280 \ epochs=120 \ batch=16 \ device=0 \ patience=20 \ optimizer=AdamW \ lr0=0.001 \ mosaic=1.0 \ close_mosaic=10 \ workers=4 \ project=bridge_runs \ name=exp_bridge_v1 \ resume=False参数上我特别强调几个,其他的按默认走:imgsz=1280是第一优先级。桥面裂缝是典型的小目标,在 640 输入下,一条 10 米长的横向裂缝可能只剩 20 个像素宽,直接消失在特征金字塔里。提到 1280,小裂缝的有效像素翻 4 倍,代价是显存占用按平方涨——12G 的卡跑yolov8m时 batch 只能开到 8 左右。mosaic=1.0对病害这类背景杂乱的场景帮助很大,相当于把不同桥段的病害组合到一张图里,增强模型对桥面纹理不变性的建模。但要在最后 10 轮把 mosaic 关掉,即close_mosaic=10,否则模型被“拼贴感”带偏,真实桥面的检测框会抖动。resume=False一定要显式写,防止上次中断的实验把权重悄悄接回去。
4.3 训练过程中的检查点:断点续训和产物目录到底要看什么
训练开始后,每 5 个 epoch 停在终端看一眼results.csv里 val 的 mAP50 和 mAP50-95 曲线。这两个指标的走势比 loss 重要——loss 是训练集的记忆程度,mAP 才是验证集上的泛化水平。如果 mAP50 在 30 epoch 内涨到 0.6 然后停滞,大概率是类别不平衡:网状裂缝样本太少,模型学不动。这时不要盲目加 epoch,回到第 2 章把网状裂缝的样本凑到 300 张以上。
训练中断后想续,直接把resume=True加到原命令,model=bridge_runs/exp_bridge_v1/weights/last.pt。产物目录里有几个文件是每次训练完必须人工核对的:
weights/best.pt:验证集 mAP 最优的权重,部署用这个;weights/last.pt:最后一轮权重,断点续训从这里接;args.yaml:本次训练的全部参数快照,复现实验的后悔药;labels.jpg和train_batch*.jpg:标注和喂进网络的真实图片,用来检查“图像是否被错误增强”——比如 mosaic 拼出来的图把裂缝截成两半,说明增强参数太激进。
另一件值得做的事,是用最佳权重对 val 集做一次批量预测,把预测结果和 GT 拼成对比图直接看。调 mAP 数字之前,先确认一件事:模型在明亮的伸缩缝上没有框,在暗处的真裂缝上有框。这个视觉确认过了,再回头调参才有意义。
5. 跨江桥梁标定数据集的踩坑排查:漏标、错标与反光干扰的 5 个现场问题
5.1 伸缩缝被大量标成横向裂缝,训练后误报率直接失控
现象: val 集上横向裂缝的 precision 很高,但一到现场,桥面伸缩缝被框个不停;翻标注文件,发现训练数据里伸缩缝区域确实有大量“横向裂缝”的框。
原因: 标注规范没写清楚“伸缩缝独立成类”的边界。标定人员看到锯齿状缝隙就条件反射标成裂缝,因为它在视觉上太像了。而模型学的不是“这是伸缩缝”,而是“这种纹理=裂缝”,于是现场必然误报。
解决: 第一,把 2.3 节的“伸缩缝”类从规范里捞出来,在标注界面单独置顶并配一张示例图;第二,对已标的数据做一次机器筛查——凡是 bbox 中心落在伸缩缝 5px 范围内的裂缝标签,批量改为伸缩缝类;第三,在训练时,如果伸缩缝样本不足,单独对它做一次随机裁剪复制增强,保证类别平衡。我做过一次后,横向裂缝的现场误报掉了近一半。
5.2 江面反光和护栏倒影被标成“坑槽”,模型学到的是高光区域
现象: 训练收敛后,模型对桥面高光区、黑色水渍区有异常高的响应;测试集里这些区域误报成坑槽的框特别多。
原因: 坑槽的颜色是深色,江面反光造成的深色倒影也是深色,标注员在快速画框时把“边界附近的高光暗斑”顺手也标了。模型学到的是“暗色积聚=坑槽”的映射,而不是真正“铺装层局部剥落”的形态。
解决: 在标定规范里加一条铁律:路面铺装之外的区域,以及护栏、桥墩在路面上的投影区,属于“忽略区”,禁止标注。清洗脚本里顺手把这部分图片裁掉也行,但我更推荐保留原图、只约束标注区域——这样模型能见到真实的阴影纹理,但不会被错误标签污染。复查时专门按 2x 放大看暗斑,凡是边缘没有轮碾破损纹理的深色区域,一律删框。
5.3 灯杆、标志牌一图多目标,标注员只标了“最近最大的那个”
现象: 训练后,模型对“远处的灯杆”召回率极低,而现场的灯杆往往排成一排,远处那根不检,就失去资产盘点意义。
原因: 标注员在一个画面上面对 5-6 根灯杆,本能只标最醒目、最大的那一根。一张图里少标的不是一两个框,而是这类样本的分布直接被带歪——模型看到的灯杆永远是“大目标”,小尺度上的特征没学过。
解决: 在导出脚本里加一个“类别计数校验”。对每个类别设置最小标注数:护栏每图至少标 1 条连续段,灯杆必须全标(遮挡超过 90% 的除外),标志牌同理。校验脚本读 COCO JSON,把“漏标可疑图”单独导出到一个 review 目录,让标注组长人工过一遍。这比反复开会强调有用得多。
5.4 网状裂缝和龟裂的框,两个标注员画出来完全不一样
现象: 同一批龟裂图,标注员 A 画最小外接矩形,A 的框紧贴裂缝边界;B 习惯把外围“将要开裂但还没裂”的区域也包进去,两个框的 IoU 只有 0.4,一致性不达标。
原因: 龟裂、网状裂缝这类病害没有清晰边界,标准描述里说“呈网状开裂”但没说框到哪里。不同标注员对“裂缝区域”的语义边界理解不同,标注噪声直接进入训练数据,模型学出来的框一个顶俩宽。
解决: 在标定规范里把边界规则写死:外接矩形只包住已经开裂的、能看到缝口纹理的区域,周边 5px 内的松散颗粒不计入。然后做双人复核:每人抽 10% 的图,和另一个人的框算 mIoU,低于 0.65 就全组回炉。这事的本质不是模型问题,是标定标准的文本颗粒度问题——写得越具体,框越一致。
5.5 按单张图片随机划分 train/val,验证集 mAP 虚高到失去参考意义
现象: 训练完 val mAP50 0.82,但换一座跨江桥测试,掉到 0.4。调参怎么都救不回来。
原因: 划分数据集时用random_split按图片随机分,而连续帧里同一病害重复出现 5-8 次,随机划分几乎必然让同一病害同时出现在训练集和验证集。模型等于考试时见过原题,val 指标严重虚高。
解决: 用第 3.3 节的脚本,严格按桥跨/桩号前缀分组划分。最理想是训练集和验证集来自不同的桥跨,这样验证的才是模型的泛化能力。实测同一病害在 train/val 混杂时 mAP 虚高 0.15-0.25,分组后回归到正常水平。别偷懒,分组划分脚本要当成数据集的组成部分来维护,而不是一次性工具。
6. 训练完成后的验证技巧:切片推理拼回大图,才能定这份数据集能不能用
跨江桥面巡检的原图动辄 4000 像素宽,直接用yolov8m.pt跑会爆显存,而且模型训练时 imgsz=1280,大图直接喂进去会被缩放到看不到裂缝。所以验证前先做一次切片推理——把大图切成 1280x1280 的块,带重叠地推理,再拼回原坐标。
import cv2 import numpy as np from ultralytics import YOLO model = YOLO("bridge_runs/exp_bridge_v1/weights/best.pt") img = cv2.imread("val_test/bridge03_000456.jpg") H, W = img.shape[:2] tile = 1280 stride = int(tile * 0.8) # 20%重叠,防止病害被切在边缘 detections = [] # 收集所有切片的框 for y in range(0, H, stride): for x in range(0, W, stride): x1, y1 = min(x + tile, W), min(y + tile, H) tile_img = img[y:y1, x:x1] results = model.predict(tile_img, imgsz=1280, conf=0.35, verbose=False)[0] for box in results.boxes: cx, cy, bw, bh = box.xywh[0].tolist() cls = int(box.cls[0]) conf = float(box.conf[0]) detections.append((x + cx - bw/2, y + cy - bh/2, bw, bh, cls, conf))切片重叠率取 20% 是有讲究的:裂缝横穿切片边界时,如果两边各切一半,模型可能两边都检不出;重叠保证了病害至少完整出现在某一块里。推理后所有框都回填到原图坐标,NMS 再用 IoU=0.5 压一次框,我自己通常是直接用cv2.dnn.NMSBoxes做,这样同一个病害不会出双框。把叠加框后的整图存下来和原图对比,重点看三类区域:伸缩缝周边、桥面接缝、标线磨损区——这三个位置是最容易暴露标定数据集短板的。
这份数据集到底值不值得继续投入,我的判断标准很简单:在换一座跨江桥、光照不同的验证视频上,模型能否稳定检出 90% 以上的真病害,且每公里误报不超过 5 个框。如果达不到,先别急着换模型,回到样本分布和标定一致性的排查链路里找原因。数据工程最怕的是“训都训了,算了”——我吃过这个亏,后来养成的习惯是每次训练完都把 val 预测图和 GT 叠一起人工过一遍再决定下一轮方向。希望帮到你。
本文还有配套的精品资源,点击获取