资讯详情

资讯详情

钢轨缺陷超声图像检测的Python实现与部署避坑

简介基于超声图像的钢轨缺陷检测系统提供完整源代码与已标注数据集面向毕业设计、课程实训及目标检测算法学习者。方案采用YOLOv5单阶段检测算法结合超声图像样本覆盖裂纹、划痕、断裂等常见缺陷识别场景包含数据预处理、数据增强、模型训练与验证等环节可帮助快速搭建自动检测系统。包体共460个文件其中256张PNG超声图像、133个txt标注、64个xml标签文件另有Python脚本与类别配置文件总大小18.43MB结构便于按图、标、码检索。已有166人学习使用资源内含可运行的工程代码与配套数据集免去自行采集和标注的繁琐工作适合直接复现实验、改进算法或作为教学实训参考。1. 拿到超声图像钢轨缺陷检测源码后先想清楚这件事再动手拿到一套“基于超声图像的钢轨缺陷检测python实现源码数据集”很多人第一反应是跑通 demo但真正把模型部署到探伤车、手持仪上才发现超声图像和自然图像差太远。钢轨内部缺陷如核伤、裂纹在 B 扫图像里只是几条模糊亮带或暗区探头耦合、钢轨晶粒噪声、轨面不平整都会让灰度分布剧烈波动。这个方向要解决的不是“识别一个物体”而是“判断轨头内部有没有危险回波”。适合正在做轨道交通检测、无损检测或工业视觉落地的工程师。接下来从超声图像原理、数据集整理、Python 训练、现场避坑一路拆到部署验证。2. 超声图像与钢轨缺陷先搞清楚图像里到底有什么在写任何训练代码之前先理解钢轨缺陷在超声图像里的表现方式以及为什么通用目标检测不能直接套。这个判断做错了后面所有代码都是在错误的信号上做算术。2.1 钢轨内部缺陷如何映射到超声图像A 扫、B 扫与灰度图钢轨探伤常用超声脉冲回波法。探头贴在轨面上发射纵波遇到缺陷界面或轨底时产生反射回波。传统探伤仪直接显示 A 扫波形横轴是声程也就是深度纵轴是回波高度。而标题里的“超声图像”一般指 B 扫或 C 扫成像探头沿钢轨纵向扫查把每一时刻的 A 扫波形按位置堆叠形成以横坐标为探头位置、纵坐标为声程、灰度或颜色为回波强度的二维灰度图。核伤、螺孔裂纹、轨底横向裂纹在这种 B 扫图像里通常表现为灰度异常区域比如强回波簇或声影区。这里的核心是缺陷区域和背景的像素关系极不稳定。同一缺陷在探头不同入射角、不同耦合状态下回波幅度可能差十几 dB反映成灰度就是一半亮一半暗。很多拿到数据集就开跑 YOLO 的人没有先看原始 B 扫波形分布导致模型学到的是探头的接触噪声不是缺陷结构。我一般会先统计一下数据集的灰度直方图和缺陷框面积分布再决定用目标检测还是图像分割。另外B 扫图像的纵轴像素和实际深度是线性相关的换算关系取决于采样频率与钢轨声速。钢轨中纵波声速大约 5900 m/s探头每发射一次返回的 A 扫波形在深度方向上按时间采样一个像素对应的深度就是声速 × 采样间隔 / 2。这个比例通常在探伤仪的配置文件里数据集里如果不给可以拿已知厚度的试块回波位置反推。知道了像素和深度的换算后面做缺陷定位和尺寸估计才不会差一截。放一个用 Python 分析超声图像灰度分布的最小脚本让大家知道第一步怎么下手import cv2 import numpy as np img cv2.imread(sample_bscan.png, cv2.IMREAD_GRAYSCALE) print(shape:, img.shape, dtype:, img.dtype) print(pixel range:, img.min(), img.max()) hist cv2.calcHist([img], [0], None, [256], [0, 256]) low_ratio (img 32).sum() / img.size high_ratio (img 224).sum() / img.size print(f低灰度占比 {low_ratio:.2%}, 高灰度占比 {high_ratio:.2%})这段代码把一张 B 扫图读成单通道灰度先看形状和像素范围再看低灰度和高灰度占比。逻辑说明超声 B 扫图多是 16 位 tif 或 8 位 png直接用深度学习库读容易拿错通道。参数说明cv2.IMREAD_GRAYSCALE强制读单通道避免把探伤仪导出的调色板图读成三通道cv2.calcHist的 bins 设为 256针对 8 位图如果源图是 16 位需要先除以 256 映射到 0-255。看过高灰度占比后你会发现自己手里的图往往两极分化很严重中间调很少。这就是超声图像的典型特征后面做归一化和增强时不能用自然图像的全局均值减方差方案而要做百分位截断这一点后面专门讲。2.2 为什么阈值分割与形态学在钢轨缺陷前翻车早期做钢轨缺陷检测传统做法是设定回波幅度阈值配合连通域分析和形态学开闭运算。对干净、无噪声的标准试块阈值法确实有效只要到现场轨面有油污、轮轴产生散射波、焊缝区晶粒粗大阈值就崩了。原因在于钢轨缺陷的回波不是稳定高亮核伤往往表现为多次反射的衰减回波灰度值介于噪声和底波之间单纯靠像素值切分会产生大量伪缺陷。深度学习模型真正解决的问题是把“回波形态”抽象成特征它看的是缺陷附近的上下文比如轨底反射波突然中断、固定位置出现等间距多次回波、裂纹波出现在螺孔周围。这些空间位置关系传统阈值法完全表达不出来。所以标题里的源码加数据集本质上是要你做一次从“信号阈值”到“学习特征”的迁移。选择 YOLO 还是分割网络取决于你要的是缺陷框还是缺陷轮廓。钢轨探伤的验收标准往往需要知道缺陷的当量尺寸和深度位置纯检测框不够用。因此后续实现流程通常是先整理超声 B 扫原始图和对应的缺陷标注再训练一个目标检测模型作为第一层粗筛对检出区域做分割或回归输出深度、当量面积。这也是为什么数据集里除了图像往往还带着标注文件。拿到手先看标注是矩形框还是多边形是像素掩码还是只有中心点这决定后面代码怎么写。缺陷类型也直接影响模型设计。钢轨伤损一般分核伤、螺孔裂纹、轨底横向裂纹、焊缝缺陷几类。核伤在轨头内部目标小、对比度弱容易漏检螺孔裂纹位置相对固定但容易和螺孔本身的反射波混淆焊缝缺陷形态更复杂往往伴有晶粒噪声。如果数据集里这几个类别混在一个模型里要确保每个类别的样本量都够否则模型容易把所有回波都学成某一个类。2.3 超声图像的前处理路线降噪、增强与 ROI 裁剪超声图像常见噪声包括晶粒散射噪声、电噪声和耦合不良导致的低通噪声。单纯使用高斯滤波可能抹掉缺陷回波常见做法是使用中值滤波保护边缘再用 CLAHE 把局部的暗区亮度拉开。这个组合在钢轨 B 扫上效果比较稳参数一般设中值滤波核取 3 或 5CLAHE 的 clipLimit 取 2.0-3.0tileGridSize 取 (8,8)。import cv2 import numpy as np def preprocess_bscan(img, med_ksize5, clip_limit2.5, tile(8, 8)): img cv2.medianBlur(img, med_ksize) clahe cv2.createCLAHE(clipLimitclip_limit, tileGridSizetile) img clahe.apply(img) return img逻辑说明先做中值滤波因为超声散斑噪声是脉冲型均值滤波容易把缺陷回波峰值拉平。再上 CLAHE它按局部区域重新分配灰度让低对比度裂纹更明显而且不会像全局直方图均衡那样把背景噪声同时放大。参数说明med_ksize如果取太大比如 9会把细小核伤的首发波也抹掉clipLimit控制对比度截断阈值越大增强越猛如果现场图像本身对比度够好可以降到 1.5。ROI 裁剪方面不要上来就整图训练。钢轨 B 扫图的顶部是轨面回波底部是轨底回波真正要关注的是轨腰和轨头区域。用像素坐标裁剪这条水平带能让模型更专注。常见做法是根据探伤仪设置里的闸门位置来裁剪如果没有先验可以统计标签框中心点的纵坐标分布取 2% 到 98% 分位作为裁剪边界。这些动作看起来不起眼但对模型收敛速度影响很大。3. 数据集准备从原始 B 扫描到可训练样本拿到源码和数据集很大概率是已经整理好的图像文件夹或一个包含原始探伤文件和标注文件的目录。第一个坑是探伤仪导出的原文件往往不是 png/jpg而是自定义二进制格式比如 RAW、DAC 文件。如果项目包里附带的是图片文件夹直接用即可但如果需要从原始信号重新生成 B 扫图就要搞清楚采样率、探头间距和像素深度。这里按“图片加 BBox 标注”的常见场景讲。3.1 数据集目录结构与标签格式VOC 转 YOLO 的转换脚本常见的数据集目录结构是images/train、images/val、labels/train、labels/val。标签最常见两种VOC XML 和 YOLO txt。XML 适合人看但训练时解析慢YOLO txt 紧凑是主流。如果拿到的是 VOC XML转 YOLO 的脚本并不复杂。注意YOLO txt 的坐标是归一化的需要除以图像宽高中心点坐标和宽高都用 0-1 浮点数类别号从 0 开始。import xml.etree.ElementTree as ET import os def voc_to_yolo(xml_path, out_txt, class_to_id): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) with open(out_txt, w) as f: for obj in root.findall(object): name obj.find(name).text box obj.find(bndbox) x1 float(box.find(xmin).text) y1 float(box.find(ymin).text) x2 float(box.find(xmax).text) y2 float(box.find(ymax).text) cx ((x1 x2) / 2) / w cy ((y1 y2) / 2) / h bw (x2 - x1) / w bh (y2 - y1) / h f.write(f{class_to_id[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}\n)逻辑说明遍历 VOC 的 object 节点提取坐标并归一化。参数说明class_to_id需要你自己维护比如{defect: 0}或{nucleus: 0, screw_crack: 1}注意除零和缺失尺寸问题图像尺寸为空时直接报错。转换完需要可视化验证把 YOLO txt 的坐标还原成像素画在原图上看框是否偏移。3.2 16 位超声图转 8 位图百分位截断比直接除法更靠谱很多超声采集卡生成的 B 扫图是 16 位灰度直接除以 256 转到 8 位会得到一张整体偏黑的图因为 16 位数据里缺陷回波的有效动态范围往往只占一小段。正确做法是按百分位截断把 1% 到 99% 分位的区间映射到 0-255。import numpy as np import cv2 def normalize_16bit(img, low_percent1, high_percent99): img np.array(img, dtypenp.float32) lo, hi np.percentile(img, [low_percent, high_percent]) img np.clip((img - lo) / (hi - lo 1e-6), 0, 1) return (img * 255).astype(np.uint8)逻辑说明先用百分位找有效灰度区间再把区间外值截断避免少量高回波把整体亮度拉低。参数说明low_percent1, high_percent99是默认值如果数据本身噪声大可以调成 2、98图像更干净不要轻易用 0 和 100因为极值往往来自电噪声。这个函数要放在 CLAHE 之前否则 16 位转 8 位时的桶效应会破坏对比度。预处理链路一旦定下来训练和推理必须保持一致否则会出现现场模型完全失效的翻车第 5 章会展开讲。3.3 数据增强小样本下怎么把一列钢轨扩成几千张钢轨缺陷样本很稀缺尤其核伤、螺孔裂纹可能整个数据集只有几百个正样本。增强策略要同时照顾自然图像和超声特性。水平翻转一般可以垂直翻转要谨慎因为图像纵轴对应深度翻转后等于把缺陷从浅部挪到深部物理上不合理。旋转角度超过 15 度也会破坏回波与轨底波的几何关系。可用的增强小幅平移、小幅旋转、亮度对比度扰动、添加高斯噪声、局部遮挡。推荐用 albumentations 库import albumentations as A train_transform A.Compose([ A.RandomCrop(height512, width512, p0.5), A.HorizontalFlip(p0.5), A.Rotate(limit10, p0.4), A.RandomBrightnessContrast(brightness_limit0.15, contrast_limit0.2, p0.5), A.GaussNoise(var_limit(20, 40), p0.3), A.CLAHE(clip_limit2.5, tile_grid_size(8, 8), p0.3), ])逻辑说明这些增强同时作用在图像和对应 bbox 上albumentations 会自动同步坐标。参数说明Rotate(limit10)限制旋转范围避免破坏缺陷形态GaussNoise模拟电噪声但方差不要太大否则模型会去拟合噪声CLAHE增强让模型见过不同对比度提高泛化。验证集和测试集不能加随机增强否则验证指标会虚高。3.4 统计类别和框尺寸分布提前发现标注问题训练之前跑一个统计脚本看看每个类别的目标数量以及框宽高比分布能发现很多隐藏问题。钢轨缺陷框通常偏长条如果数据里混入了整张图大小的标注框说明标注边界出了问题。import glob from collections import defaultdict stats defaultdict(list) for txt in glob.glob(labels/train/*.txt): with open(txt) as f: for line in f: line line.strip() if not line: continue cls, cx, cy, bw, bh line.split() stats[cls].append((float(bw), float(bh))) for cls, boxes in stats.items(): widths [b[0] for b in boxes] heights [b[1] for b in boxes] print(fclass {cls}: count{len(boxes)}, mean_w{sum(widths)/len(widths):.3f}, mean_h{sum(heights)/len(heights):.3f})逻辑说明遍历所有训练标签按类别收集归一化宽高最后打印数量和均值。参数说明如果是 YOLO 格式这五个字段缺一不可遇到空行直接跳过类别号可以是多位数split()也能正确取到。跑完之后如果某个类别数量只有几十个就要考虑过采样或类别权重。4. 用 Python 把检测模型跑起来从 YOLOv8 到分割网络标题里的“python实现源码”最常见的形态就是封装好数据处理、模型训练和推理的脚本。核心基于 PyTorch 生态。如果数据集不大优先选 YOLOv8n 或 YOLOv8s如果需要精细分割再用 U-Net。这一章讲模型选型、训练脚本、推理可视化以及为什么我会推荐“检测加分割”的混合路线。4.1 模型选型检测框、分割掩码还是检测加分割钢轨缺陷检测的最终交付物通常是“有没有缺陷、缺陷在什么深度、大概面积”。检测框只能给位置和范围面积要靠分割。但分割训练成本高而且超声图像边缘模糊标注掩码一致性差。稳妥路线是先用 YOLO 检测框做主模型在识别到缺陷框的区域内再切小 patch 做分割。如果数据集本身是掩码标注那直接训练分割模型更合理。选型还要看推理设备。探伤小车上的工控机一般只有 CPU 或低端 GPUYOLOv8n 在 CPU 上 720p 图像大约能跑到 20-30 FPS分割网络就吃力了。如果后续想部署到嵌入式设备训练时就要从一开始选择轻量主干比如 YOLOv8n 的 backbone。4.2 用 YOLOv8 训练钢轨缺陷数据集 YAML 和最小训练脚本训练 YOLOv8 只需要准备一个 YAML 文件然后调 Ultralytics API。这个 YAML 里的路径坑不少最常见的错误是绝对路径和相对路径混用。我一般会把数据集 YAML 放在项目目录下用相对路径指向 images 和 labels。# rail_defect.yaml path: ./datasets/rail_bscan train: images/train val: images/val nc: 2 names: 0: nucleus 1: screw_crack逻辑说明path是数据集根目录train和val相对于 path。如果路径错了YOLO 会报 dataset not found。nc必须和 names 数量一致。参数说明names 的键从 0 开始顺序要和标签文件的数字一致类别名不要用中文某些 Windows 环境下编码会出问题。训练脚本如下from ultralytics import YOLO model YOLO(yolov8n.pt) results model.train( datarail_defect.yaml, epochs100, imgsz640, batch16, lr00.01, devicecuda:0, patience15, exist_okTrue, )逻辑说明model YOLO(yolov8n.pt)加载 COCO 预训练权重能加速收敛如果超声图和自然图像差异太大可以从零训练改成YOLO(yolov8n.yaml)。参数说明epochs100对钢轨小样本足够太多必过拟合imgsz640是输入尺寸内存不足降到 512patience15表示 15 轮验证指标没有提升就早停这是避免过拟合的后悔药。很多人把 batch 直接设成显存上限但超声图像是灰度单通道同样显存下可以比 RGB 图跑更大 batch可以在 16 基础上加倍。训练完成后输出在runs/detect/train下先看results.png里的 PR 曲线和验证集损失不要只盯着训练 loss。4.3 推理与可视化在 B 扫图像上画缺陷框训练完成后推理脚本要简单可复用。用 model.predict 可以直接输出结果但要画缺陷框并输出像素坐标手工处理更灵活。from ultralytics import YOLO import cv2 model YOLO(runs/detect/train/weights/best.pt) img preprocess_bscan(cv2.imread(test_001.png, cv2.IMREAD_GRAYSCALE)) results model.predict(img, conf0.35, imgsz640, verboseFalse) for r in results: boxes r.boxes for box in boxes: cls_id int(box.cls) conf float(box.conf) x1, y1, x2, y2 map(int, box.xyxy[0]) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) label f{model.names[cls_id]} {conf:.2f} cv2.putText(img, label, (x1, y1 - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)逻辑说明先预处理再预测这里的preprocess_bscan就是 2.3 中封装的函数。results是一个列表每个元素对应一张图r.boxes里的坐标是相对于输入图像尺寸的可以直接画在原图上。参数说明conf0.35是置信度阈值现场可以调到 0.5verboseFalse避免推理时打印一堆日志。如果输入的是 16 位 tif不能直接传需要先转成 8 位ultralytics 不接受单通道以外输入时把单通道复制成三通道再传。推理后保存结果图和人工标注对比肉眼检查误检位置。超声图像误检通常集中在轨底反射波和螺孔周围如果误检全部打在固定结构回波上说明模型没有学会“缺陷是异常回波”这件事。4.4 分割模型兜底一个极简 U-Net 的输入输出如果需要分割最简单的落地方式是写一个 U-Net 壳子先跑通流程再加深网络。import torch import torch.nn as nn class SimpleUNet(nn.Module): def __init__(self, in_channels1, num_classes2): super().__init__() self.encoder nn.Sequential( nn.Conv2d(in_channels, 32, 3, padding1), nn.ReLU(inplaceTrue), nn.Conv2d(32, 32, 3, padding1), nn.ReLU(inplaceTrue), nn.MaxPool2d(2) ) self.decoder nn.ConvTranspose2d(32, num_classes, kernel_size2, stride2) def forward(self, x): return self.decoder(self.encoder(x))逻辑说明这是一个极简 U-Net仅用于说明输入输出。输入是单通道灰度图输出是每个像素的类别 logits。参数说明in_channels1对应灰度 B 扫num_classes2对应背景和缺陷。实际项目中这个网络太浅至少需要三层编码和跳连接否则小缺陷根本分割不出来。训练损失建议用 DiceLoss 加 FocalLoss不用纯交叉熵因为缺陷像素占比常常低于 2%直接用交叉熵会让网络把所有像素预测为背景。5. 钢轨超声检测的避坑清单现场翻车原因与排查这一章集中写踩坑。下面这些现象都来自实际运行不是玄学按“现象、原因、解决”展开。5.1 现象训练 loss 正常下降验证集 PR 很高现场推理全是误报原因训练和推理的预处理不一致。训练时做了 CLAHE、归一化、ROI 裁剪而推理脚本只是直接用 cvtColor 读图或者训练时把 B 扫图当成 RGB 三通道反复复制推理时用了灰度单通道。模型见过的是伪彩色分布推理输入变成另一个分布识别自然崩溃。解决把预处理封装成独立函数在训练数据加载器和推理脚本里共用同一份代码。16 位转换、CLAHE 参数、中值滤波核大小全部写死不要在每个脚本里各写一遍。我见过最隐蔽的问题是训练数据集里有些图是 8 位有些是 16 位归一化时没有统一推理时一张 8 位图直接传给模型效果时好时坏。拿到新数据后先跑一遍预处理函数并保存结果图人工确认训练和推理看到的图风格一致。5.2 现象同一段钢轨换一个探头或探伤仪准确率骤降原因超声图像高度依赖设备参数。探头频率不同比如 2.5MHz 和 5MHz缺陷回波形态差异很大显示亮度、压缩曲线也不同。如果数据集中只有单一设备模型过拟合到固定的灰度模式换设备就失效。解决训练集里尽量混合多设备、多探头数据。如果拿不到就在预处理阶段加入随机增益扰动模拟不同设备的回波幅度差异。推理前再做一次灰度对齐把每张图的均值和标准差拉到一个固定值。这个手段不算完美但能保一部分召回率至少不会完全瞎掉。5.3 现象类别不平衡螺孔裂纹很多核伤只有几十个核伤漏检严重原因目标检测损失里正负样本比例天然不平衡小样本类别对梯度贡献小尤其核伤本身面积小、对比度弱锚框很难命中。类别不平衡在钢轨缺陷里是常态不是特殊情况。解决不要只用默认损失权重。先统计每个类别样本数按中位数比例设置损失权重在增强阶段对稀有类别过采样复制让每个 epoch 核伤样本出现次数不低于某个阈值。如果条件允许把核伤单独训练一个专用模型不要和螺孔裂纹混在一个模型里。如果缺陷框太小先把 ROI 放大两倍再训练模型更能学到细节。5.4 现象标注框边界不一致有的标了核心回波有的标了整片声影区原因钢轨缺陷在超声图上的物理边界本身不清晰不同标注人员对边界理解差别很大。有人按首次回波高亮处标有人把声影区也包进去。YOLO 框是矩形框稍微大一圈中心点偏移一点损失就剧烈变化。解决训练前做一轮标注清洗把宽高比异常比如超过 10 的细长框挑出来人工确认。有的项目会给每个缺陷框固定偏移只标注回波核心区比如缺陷中心的 5x5mm 区域。这样做 IoU 指标会低一些但模型学到的特征更纯现场可用性反而更好。如果条件允许用分割标注替代矩形框让标注人员画核心轮廓再转成外接矩形。5.5 现象验证集 mAP 一直为 0但训练损失已经降到很低原因标签格式有问题常见的是类别号从 1 开始而不是 0或者标签文件保存成 UTF-8 带 BOM。ultralytics 读取时把 BOM 字符也当成内容整个训练集标签无法解析网络训练时实际在学“全是背景”损失照样降。解决写一个数据完整性检查脚本逐个读标签 txt检查类别最大值是否小于nc坐标是否都在 0-1 之间字段数是否为 5。也可以直接可视化叠加图像看框是否在合理位置。发现 BOM 时用open(txt, encodingutf-8-sig)重新保存。这个检查应该在训练前跑不要等训练完再后悔。6. 从源码到上线路边部署与验证的进阶做法模型训练完能出框只代表实验室阶段结束。真正上线前还有三件事要做导出轻量模型、处理探伤车实时视频流、建立现场验证指标。这是决定项目能不能交付的最后一道闸。6.1 模型轻量化与 ONNX 导出YOLOv8 训练出来的 best.pt 是 PyTorch 权重在工控机上推理有依赖重、速度慢的问题。常见做法是导出 ONNX再用 TensorRT 量化部署到探伤车的 Jetson 或 x86 盒子。导出命令很简单yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640 dynamicTrue参数说明dynamicTrue允许动态分辨率但会损失一些优化空间如果现场图像尺寸固定建议关闭 dynamic换取 TensorRT 的加速收益。导出 ONNX 后用 onnxruntime 或 TensorRT 加载可以摆脱 PyTorch 环境。注意超声原始图是单通道导出时输入 shape 可能是 [1,3,640,640]需要在预处理里把单通道复制成三通道。6.2 在探伤小车上的实时视频流处理低速手推探伤车帧率可能只有 5-10 FPS高速车载系统要求更高。如果推理速度跟不上漏检就发生了。我一般会把采集线程和推理线程分开用队列缓存最近 N 帧。推理节点只处理最新的帧不回溯旧帧。队列大小要根据帧率调整满了直接丢最老的帧保证实时性。图像处理时用 OpenCV 读入后立即复制一份避免线程间共享变量导致数据竞争。6.3 现场验证指标漏检率、误报率与最小可检缺陷模型精度不是上线依据现场验收看的是漏检率和误报率。比如标准要求钢轨焊缝区域内 5mm 以上当量缺陷不漏检误报次数每公里少于若干次。因此要在伤损验证线上跑一遍生成混淆矩阵。指标上除了 mAP更要关注召回率和误报数每公里。如果某个类别召回率不够优先调整置信度阈值和 ROI 区域再考虑增加训练样本。做这个方向这么久我最大的教训是超声图像的预处理一致性比模型结构更重要。模型不好可以换预处理不一致等于训练和推理各学各的。每接到一批新数据我都会先把图像统计、标签分布、预处理链路固定下来再开始调模型。这个习惯让我后面少踩很多坑。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →