当前位置: 首页 > news >正文

YOLOv11传送带破损检测:700张图片数据集构建与训练实战

简介:工业缺陷检测是保障产线安全高效运行的关键环节。在煤矿、港口、电厂等场景中,传送带一旦发生纵向撕裂、横向裂纹或边缘磨损,及时发现至关重要。基于深度学习的视觉检测技术,凭借YOLOv11等目标检测算法,可实现皮带表面缺陷的自动识别与早期预警。然而,实际落地中模型效果高度依赖高质量数据集,缺陷样本稀缺与标注不规范常成为瓶颈。本文针对传送带破损检测需求,探讨如何基于700张原始图片构建规范的YOLOv11数据集,涵盖采集、清洗、标注、格式转换与训练推理全流程,并总结工程实践经验,为工业视觉算法团队提供可复用的技术参考。 传送带在煤矿、港口、电厂、水泥厂这些场景里,基本就是物料运输的生命线。皮带一旦出现纵向撕裂、横向裂纹或者边缘磨损,没有及时发现的话,轻则整条产线停机,重则几百万的皮带直接报废,甚至引发安全事故。所以现在越来越多的工厂在尝试用视觉检测系统去盯皮带,让算法代替人眼做实时巡检、早期预警。但这类项目真正落地的时候,第一个卡住团队的点往往不是模型选型,而是数据集——工业现场的缺陷样本本身就少,能用的标注数据更少,模型再先进,没有高质量数据喂进去也是白搭。

这篇文章围绕一个实际项目展开:用700张传送带皮带原始图片,做成yolov11格式的标注数据集,目标是训练一个能识别传送带表面破损、撕裂、裂纹等缺陷的检测模型。我不会只给一个“数据集下载”的链接就完事,而是把从采图、清洗、标注、格式转换到训练推理的全流程拆开讲清楚,包括我实际踩过的坑和总结下来的操作经验。适合谁看?工业视觉算法工程师、做设备点检自动化的团队、还有刚学YOLO想上手一个真实项目的同学,都可以把这套流程当作一个可以直接复用的模板。

1. 项目整体设计与方案选型

1.1 为什么选yolov11而不是yolov8或更早的版本

先说模型选型。传送带破损检测属于典型的工业缺陷检测任务,对实时性和部署便利性都有要求。早期项目很多用yolov5,后来v8出来后性能进一步提升,但真正让我在近期项目中切到yolov11的,是它在几个方面的综合表现:一是主干网络和颈部结构做了优化,在相同算力下精度比v8有所提升;二是ultralytics框架的接口统一,训练、验证、导出、推理可以一条命令走完,对工业项目来说这意味着维护成本低;三是官方预训练权重在COCO上表现不错,做迁移学习的时候起点更高。

当然,不是说v8不能用。如果你的场景对延迟极其敏感、部署硬件非常老旧,v8也可能够用。但既然做的是新的数据集、新的项目,没必要回头看,直接用v11把baseline建好,后面即使要降级到v8或者以后迁移到更新的版本,数据集和标注格式都是通用的,迁移成本极低。这也是我在方案选型时的一个原则:优先选择生态完善、社区活跃、迭代路径清晰的框架,而不是某个特定版本的极致性能。

1.2 700张图片这个规模够不够用

很多人一听到数据集只有700张,第一反应是“这么少,训练出来能准吗”。这个担心有道理,但也不全对。工业缺陷检测和通用目标检测的本质区别在于:你的目标类别非常集中,场景变化范围相对有限。传送带的背景虽然各有不同,但整体结构、纹理、光照条件比开放世界的检测任务要收敛得多。我做过类似的项目,500到1000张的高质量标注图,配合合理的数据增强策略,完全能训练出一个在生产环境可用的检测模型。

关键前提是:这700张图的质量要足够高。我指的是三点:

  • 缺陷的形态要覆盖全面,纵向撕裂、横向裂纹、边缘破损、表面剥落都要有;
  • 标注要精确,框不能随便拉一个大框把整张图圈进去;
  • 正负样本比例要控制好,最好有一定比例的负样本(正常皮带图片)参与训练,降低误检率。

我在实际项目里遇到过一种情况:客户提供的视频抽帧数据有3000多张,但真正包含破损缺陷的只有不到200张,其余全是正常皮带。如果直接把3000张全塞进去训练,模型会严重偏向负样本,输出结果里几乎不报缺陷。后来我把数据集重新洗了一遍,保留缺陷样本,再按1:5到1:8的比例混入正常样本,训练效果立刻正常了。所以说,700张图不是死数字,数据分布比绝对数量更重要。

1.3 缺陷类别怎么定义才科学

标注之前必须先定类别。类别定义直接决定了标注的一致性,也影响模型的学习效果。我在传送带破损检测项目里把缺陷分为四类,这里也推荐给你参考:

类别ID类别名称形态描述典型样例
0longitudinal_tear纵向撕裂,沿皮带运行方向的裂口细长裂口,边缘不规则
1transverse_crack横向裂纹,垂直于运行方向的裂纹短粗裂纹,常出现在接头附近
2edge_wear边缘磨损,皮带侧边出现缺损边缘不齐、起毛、缺口
3surface_peel表面剥落,覆盖层局部脱落表面凹坑、露出织物层

为什么这样分?因为不同缺陷对皮带运行的影响程度和处理方式完全不同。纵向撕裂最容易导致整条皮带断裂,必须停机处理;横向裂纹可能是接头老化造成的,需要重点关注;边缘磨损一般还能坚持一段时间,但要持续监测;表面剥落往往是大面积损伤的前兆。如果你把所有这些形态统一标成“破损”一个类,模型虽然也能学,但输出信息量大大降低,现场人员看到报警后还要自己判断严重程度,效率会打折扣。

另外要注意避免类别之间的边界模糊。比如说,一个表面剥落区域旁边跟着一条细小的裂纹,很多标注员会纠结:这算两个目标还是一个目标?我的建议是:如果两个缺陷区域的间隔超过一个标注框的距离,就标成两个独立目标;如果完全粘连在一起,就按主要缺陷类型标成一个框,并在备注里记录这是复合缺陷。这个规则要提前写进标注规范文档里,否则不同标注员的标准不一致,后续模型训练效果会受影响。

2. 数据采集与预处理

2.1 采集环境对检测效果的影响有多大

传送带破损检测的数据采集,通常有两种方式:固定点位安装工业相机连续拍摄,以及巡检人员手持相机或者无人机进行周期性拍照。这两种方式采集到的图像特点差异很大,直接影响标注和训练策略。

固定点位拍摄的图像,视角稳定、光照条件可控、背景固定,模型训练起来比较容易,因为训练集和测试集之间的分布差异很小。但固定点位通常只能拍到皮带的某一小段,缺陷样本的获取效率低。巡检拍摄的优势是覆盖面广,能拍到不同类型的缺陷,而且更贴近实际巡检场景。缺点是视角、距离、光照变化很大,模型泛化能力要求更高。

我推荐的做法是两种方式都采集,但分训练集和验证集时要保证两者数据分布基本一致。也就是说,不要把固定点位拍的图全放进训练集、巡检拍的图全放进验证集,否则验证集精度看起来不错,实际上线部署时会掉得很厉害。我在项目里会把两种来源的图片混合后按比例随机划分,这样模型学到的是缺陷本身的特征,而不是某个拍摄环境的特征。

光线条件也要注意。传送带现场往往有较强的环境光、粉尘和逆光情况。采集时尽量保证皮带表面纹理清晰可见,避免光源直射镜头造成大面积反光。如果条件允许,加一个柔和光源或者调整拍摄角度,减少反光区域。对于实在无法避免的逆光图片,通过后期增强处理来补偿,而不是直接删掉——因为现场部署时模型一定会遇到这种条件,提前让模型见过这些脏数据反而更有利于上线后的稳定表现。

2.2 图片分辨率怎么选

图片分辨率是影响检测精度的关键因素之一。破损缺陷属于小目标,尤其是横向裂纹和边缘磨损,在720p的图片里可能只有几十个像素宽。检测网络在特征提取时,小目标经过多层下采样后特征几乎丢失,因此分辨率过低会直接导致漏检。

我在这个项目里的经验是:训练集图片分辨率最好不低于1280x720,推理时建议使用imgsz=1280尺度。如果原始图片是1920x1080或更高分辨率,训练时可以直接用原图resize到1280x1280,或者使用1280x640的非正方形拉伸(注意这会改变长宽比,但yolov11在检测中通常会做letterbox处理,所以训练时统一用正方形输入就好)。

这里有个权衡:分辨率高了,计算量会显著增加。在GPU资源有限的情况下,可以考虑用小分辨率先跑通流程,再在所有环节验证通过后提高分辨率进行最终训练。我的习惯是先用640x640做快速实验,确认数据、标注、配置都没有问题后,再用1280x1280正式训练,这样省时间也省算力。

2.3 图像清洗的具体标准

拿到原始图片后,不要急着标注,先做一轮清洗。这个环节看起来简单,但偷懒的话后面会花好几倍的时间来填坑。我的清洗原则是四步:

  • 去除无效图片:明显虚焦的、镜头被遮挡的、大面积过曝或欠曝的图片直接删除。这些图片即使标注了,模型也学不到有效特征,反而可能产生错误关联。
  • 去除重复图片:连续视频抽帧会产生大量几乎相同的相邻帧,保留缺陷最清晰的一帧即可。过多的相似样本会让模型对特定位置产生过拟合,而忽略缺陷本身的形态变化。
  • 检查缺陷可见程度:有些图片虽然有缺陷,但缺陷区域过小或者被遮挡,肉眼都很难判断,这类图片建议删除。标注员如果都看不清,模型更不可能学好。
  • 统一格式与命名:转成JPG格式(大小合适且通用),分辨率统一按最接近的宽度保存,文件命名用类似tear_001.jpg、crack_002.jpg的格式,方便后面的切割和标注。

命名规范建议与类别关联,但要注意不要因为文件名带类别就跳过对标签的最终核对。我踩过的一次坑是:文件重新命名后,标注软件生成的XML里的文件名和实际文件名不一致,导致后续格式转换脚本找不到对应的图片,整个流程卡了很久。所以洗完图之后,一定要检查一遍文件名的匹配情况。

3. 数据标注实操

3.1 标注工具选哪个

yolov11采用ultralytics框架,训练数据要求的是YOLO格式的txt标注文件,但标注过程不一定非得直接用txt编辑器去写坐标,那样效率太低,而且容易出错。我建议使用图形化标注工具,标完再通过脚本转换成YOLO格式。

目前常用的标注工具大致有这几类:

工具适合场景输出格式备注
LabelImg单机快速标注PASCAL VOC XML、YOLO txt老牌轻量,适合小项目
Labelme多边形标注JSON需要多边形时用,比如分割任务
X-AnyLabeling单机进阶标注VOC、YOLO、COCO等支持AI辅助标注,效率高
CVAT团队协作标注多格式导出Web版,适合多人并行标注

如果你是自己一个人做700张图的小项目,我推荐直接用LabelImg或者X-AnyLabeling。LabelImg的优势是简单直接,安装后就能上手;X-AnyLabeling的优势是内置了自动标注模型,可以先让模型粗标一遍,然后人工修正,对于缺陷不太复杂的情况效率能提升不少。如果是团队协作且图片量大,CVAT更合适,它能做到多人在线标注、任务分配和审核留痕。但要注意CVAT的部署和维护成本,小团队用起来会有点重。

3.2 标注框的边界怎么定

YOLO格式的标注框是水平矩形框,用中心点坐标和宽高表示。但传送带破损缺陷往往是不规则的,有时候是长条形撕裂,有时候是块状剥落。怎么用矩形框标不规则目标,是有讲究的。

我总结下来有三条原则:

  • 矩形框要紧贴缺陷的轮廓,框的上边、下边、左边、右边都尽量贴合缺陷的外边界,不要为了省事留太多背景。
  • 对于长条形撕裂,如果撕裂宽度很窄,矩形框会变成一条很扁的长条,这种框在训练时是可以接受的,因为网络会学习到目标的物理形态。但要注意框的宽度不能太极端,如果宽度只有几个像素,经过缩放后会很容易丢失,建议在原始图上放大确认后再标注。
  • 对于边缘不清晰的缺陷(比如表面剥落的边界比较模糊),标注时可以稍微收窄一点,宁可框略小于缺陷,也不要框得太大把很多正常纹理包进去。因为框大了,里面的负样本特征也会被当成正样本学进去,增加模型的误检倾向。

这里还要强调一个点:破损缺陷的矩形框如果出现交叉重叠(比如两个缺陷靠得很近),在YOLO格式下是允许的,一张图片里可以有多个目标的标注框,它们之间可以重叠。但重叠过多会导致训练时一个anchor同时匹配到两个目标,影响收敛效果。最佳实践是:如果两个缺陷高度重叠且边界无法区分,标注为一个框;如果边界基本清晰,就分两个框。

3.3 标注完成后的质检流程

标注完成不等于数据可用。我在项目里规定标注完成后必须执行一轮质检,通常分两个阶段。

第一阶段是漏标检查。逐张快速浏览图片,确认每个可见缺陷都有对应的标注框。这个阶段容易出现的问题是:边缘部分的破损、对比度较低的裂纹、以及跨图片边界的目标容易被忽略。强烈建议在原始分辨率下检查,不要用缩小后的视图。

第二阶段是框精度检查。随机抽取20%以上的标注结果,放大查看框是否紧贴目标、类别标签是否与缺陷类型一致、是否存在误标(比如把油渍、水渍、皮带接头纹理当成破损)。如果抽检结果中误标率超过2%,说明标注规范执行不到位,需要让标注员修正后重新抽检。

我自己的习惯是:先标完全部图片后,隔一天再质检一遍。刚标完的时候大脑会有惯性,容易忽略自己的错误;隔一段时间再来检查,能发现很多之前没注意到的问题。这个习惯帮我在项目交付前避免过好多低级失误。

4. yolov11格式转换与数据集组织

4.1 YOLO标注格式到底长什么样

先讲清楚YOLO格式的核心规则,这是很多人第一步就搞错的地方。YOLO格式的标注文件是纯文本的txt文件,每一行描述一个目标,格式为:

class_id center_x center_y width height

其中class_id是从0开始的整数类别编号;center_x、center_y是目标中心点相对于图片宽高的比例坐标;width、height是目标宽高相对于图片宽高的比例。所有坐标值都在0到1之间,是归一化后的浮点数。

举个例子:一张宽1280、高720的图片,标注一个纵向撕裂缺陷,标注框左上角坐标为(400, 200),右下角坐标为(600, 500),那么中心点坐标是((400+600)/2, (200+500)/2) = (500, 350),相对坐标是(500/1280, 350/720) = (0.3906, 0.4861),宽是600-400=200,相对宽为200/1280=0.1563,高是500-200=300,相对高为300/720=0.4167。最终txt中的一行就是:

0 0.3906 0.4861 0.1563 0.4167

需要注意的是,如果图片经过letterboxing处理(也就是在YOLO训练时对图片进行缩放和填充),标注坐标不会改变,因为坐标是相对于整张图片的。训练时yolov11会自行处理letterbox,数据集的标注文件只需要按原图坐标计算即可。

4.2 数据集目录结构怎么组织

ultralytics框架默认的数据集目录结构是:

dataset/ ├── images/ │ ├── train/ # 训练图片 │ └── val/ # 验证图片 ├── labels/ │ ├── train/ # 训练图片对应的txt标注 │ └── val/ # 验证图片对应的txt标注 └── data.yaml # 数据集配置文件

注意,images和labels两个目录下的文件必须一一对应,同名。比如images/train/tear_001.jpg对应labels/train/tear_001.txt。如果你没有给某张图片标注任何目标(负样本),对应的txt文件应该存在但内容为空。不要省略这个txt文件,否则框架可能报错或者无法准确对齐图像和标签。

在ultralytics里,你还可以使用一个更简单的目录组织方式:只提供images路径,框架会自动从labels字段推断标签路径,但前提是目录结构严格一致。为了保险起见,我建议显式指定labels路径。

4.3 从VOC或Labelme格式转换的脚本

如果你用LabelImg标注并保存为VOC XML格式,或者用Labelme保存为JSON格式,转换到YOLO格式是必须的一步。这里我给出一份Python脚本,处理Labelme JSON转YOLO txt的场景,同时自动完成数据集划分。

import json import os import random import shutil from pathlib import Path # 配置路径 labelme_json_dir = Path("path/to/labelme_jsons") image_dir = Path("path/to/images") output_dir = Path("path/to/dataset") train_ratio = 0.8 # 类别映射 class_map = { "longitudinal_tear": 0, "transverse_crack": 1, "edge_wear": 2, "surface_peel": 3 } def convert_labelme_json(json_path, image_width, image_height): """将单个Labelme JSON转换为YOLO格式的字符串列表,每行一个目标""" with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) yolo_lines = [] for shape in data["shapes"]: label = shape["label"] if label not in class_map: continue points = shape["points"] # Labelme的点集,通常为[左上, 右下]或任意多边形 xs = [p[0] for p in points] ys = [p[1] for p in points] x_min, x_max = min(xs), max(xs) y_min, y_max = min(ys), max(ys) # 计算归一化坐标 cx = ((x_min + x_max) / 2) / image_width cy = ((y_min + y_max) / 2) / image_height w = (x_max - x_min) / image_width h = (y_max - y_min) / image_height yolo_lines.append(f"{class_map[label]} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") return yolo_lines def main(): # 创建输出目录 for split in ["train", "val"]: (output_dir / "images" / split).mkdir(parents=True, exist_ok=True) (output_dir / "labels" / split).mkdir(parents=True, exist_ok=True) # 获取所有JSON文件 json_files = list(labelme_json_dir.glob("*.json")) random.seed(42) random.shuffle(json_files) split_idx = int(len(json_files) * train_ratio) train_files = json_files[:split_idx] val_files = json_files[split_idx:] for json_path, split in [(f, "train") for f in train_files] + [(f, "val") for f in val_files]: # 从JSON中解析图片宽高 with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) image_w = data["imageWidth"] image_h = data["imageHeight"] img_name = Path(data["imagePath"]).name src_img_path = image_dir / img_name if not src_img_path.exists(): print(f"警告:图片不存在 {src_img_path}") continue # 拷贝图片到对应split dest_img_path = output_dir / "images" / split / img_name shutil.copy(src_img_path, dest_img_path) # 生成标注txt yolo_lines = convert_labelme_json(json_path, image_w, image_h) txt_name = json_path.stem + ".txt" dest_txt_path = output_dir / "labels" / split / txt_name with open(dest_txt_path, "w", encoding="utf-8") as f: f.write("\n".join(yolo_lines)) # 生成data.yaml yaml_content = f""" path: {output_dir.resolve()} train: images/train val: images/val names: 0: longitudinal_tear 1: transverse_crack 2: edge_wear 3: surface_peel """ with open(output_dir / "data.yaml", "w", encoding="utf-8") as f: f.write(yaml_content) print("转换完成!") print(f"训练集图片数: {len(train_files)}") print(f"验证集图片数: {len(val_files)}") if __name__ == "__main__": main()

这个脚本核心逻辑并不复杂,但有几点提醒:第一,如果某些图没有缺陷,Labelme JSON中的shapes为空数组,脚本不会生成任何YOLO行,最终txt内容为空——这是正常的,不要删除这个txt,保留空文件即可。第二,如果你的标注工具(比如LabelImg的VOC模式)输出的是XML,你需要把XML解析代码换成xml.dom.minidom或lxml来读取,VOC的bndbox节点里存的是xmin、ymin、xmax、ymax,计算归一化坐标的公式一样。

4.4 数据增强策略与注意点

训练YOLO模型时,ultralytics框架默认已经开启了不少数据增强策略,包括随机翻转、HSV色域扰动、马赛克增强(Mosaic)、随机透视变换等。这些默认策略对小数据集非常友好,相当于免费扩充了训练多样性和样本数量。

但是传送带缺陷检测有一个特殊点:缺陷形态和纹理高度相关,有些增强操作需要谨慎。比如随机透视变换在通用目标检测里效果不错,但对于传送带这种表面有规律纹理的目标,透视变换可能会把纹理的走向扭曲,反而让模型学到不真实的缺陷形态。我的经验是,在数据量不太充足的情况下,保守使用几何类增强,可以关闭或降低透视变换强度,同时加强HSV颜色扰动和随机翻转。

另外,Mosaic增强是yolov11训练中默认开启的,它会把4张图拼接成一张,对提升小目标检测能力很有帮助。但Mosaic生成的图片中,目标框会被裁剪和拼接,如果缺陷本身比较小,拼接后缺陷可能会被切碎导致难以识别。ultralytics中可以通过ultralytics.cfg配置文件里的mosaic参数控制开启概率,训练时如果发现小缺陷的召回率一直上不去,可以考虑关掉Mosaic再试一轮,对比效果。

5. 基于yolov11的训练与推理

5.1 环境搭建和常用指令

环境配置这块其实是很多新手最头疼的。在这里把关键步骤列出来,照着操作即可。我用的是Anaconda + Python 3.10 + CUDA 11.8的组合,这个组合目前跑yolov11非常稳定。

# 创建虚拟环境 conda create -n yolo11 python=3.10 -y conda activate yolo11 # 安装PyTorch(根据你的CUDA版本选择合适的安装命令) # CUDA 11.8 版本 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装ultralytics(yolov11的官方框架) pip install ultralytics # 验证安装 yolo version

安装完成后,可以用一行命令快速检测一张测试图片,验证环境是否正常:

yolo predict model=yolo11n.pt source='test.jpg'

如果这一步能正常输出检测结果图片,说明环境没问题,可以开始训练了。我建议新手把ultralytics的文档存下来,遇到参数不确定的时候直接查文档,比在群里问人效率高得多。

5.2 准备data.yaml文件

训练前需要先写好data.yaml,告诉框架数据集在哪、类别是什么。这个文件是整个训练流程的入口,写错了训练直接报错或者效果很差。

# data.yaml path: /home/user/dataset # 数据集根目录的绝对路径 train: images/train # 相对path的训练图片目录 val: images/val # 相对path的验证图片目录 # test: images/test # 测试集目录,可选 names: 0: longitudinal_tear 1: transverse_crack 2: edge_wear 3: surface_peel

注意path字段建议写绝对路径。写成相对路径的时候,ultralytics会基于当前工作目录去匹配,容易出现找不到图片的情况。还有一个容易踩坑的地方是:训练时如果你把数据集放在别的目录下,但data.yaml里的path写的是之前的路径,训练会直接报错提示找不到图片。所以每次数据集移动位置后,记得同步更新data.yaml里的path。

5.3 训练命令与关键参数

数据准备好了,就可以开始训练。这是我实际用来训练传送带破损检测模型的命令:

yolo detect train \ model=yolo11s.pt \ data=data.yaml \ imgsz=1280 \ epochs=200 \ batch=16 \ patience=30 \ project=runs/detect \ name=conveyor_belt_tear \ device=0 \ optimizer=AdamW \ lr0=0.001 \ weight_decay=0.0005 \ val=True

参数说明:

  • model:这里指定的是yolo11s.pt预训练权重,与从头训练使用yolo11s.yaml不同。使用预训练权重做迁移学习,训练速度更快、收敛更稳定。
  • imgsz:输入图片尺寸,我选择了1280。前面说过,破损缺陷是小目标,大输入尺寸有助于保留更多细节。如果你的GPU显存不够(低于8GB),可以先降到640跑通流程,后续资源充足了再上1280。
  • epochs:200轮。工业数据集通常epochs不用太多,配合早停机制可以自动停止。
  • patience:30轮验证集指标没有提升就早停。这个参数防止过拟合并节省时间。
  • batch:16,根据显存调整。如果OOM,就降到8或者4。
  • optimizer:我习惯用AdamW,收敛快,适合中小数据集。如果是大数据集,SGD也能用,两者差距不算大。
  • lr0:初始学习率0.001。对迁移学习来说,这个值比较稳妥,不会因为太大导致原有特征被破坏。

训练过程中,终端会实时打印每个epoch的loss、P、R、mAP50、mAP50-95等指标。如果loss一直在降,mAP也在稳步上升,说明训练正常,不用人为干预。直到patience触发或者epochs跑完,训练结束,最佳权重保存在runs/detect/conveyor_belt_tear/weights/best.pt。

5.4 如何判断模型效果是否合格

训练结束后,很多人只看一个mAP50就觉得万事大吉,这是不对的。工业缺陷检测场景里,我更关注两类指标:召回率(Recall)和误检率(Precision的互补项)。漏检一个破损可能导致整条皮带报废,而误检过多会让人失去对报警系统的信任。

我在实际项目中的判断标准是:

  • mAP50 达到 0.85 以上,说明整体检测精度可以接受;
  • 召回率不低于 0.90,确保绝大多数破损能被发现;
  • 误检率控制在 1% 以内,也就是每100个正常画面中不超过1次假报警。

如果这些指标没达到,先不要急于调参,而是回到数据本身问三个问题:缺陷样本数量是否足够?标注框是否准确?类别定义是否清晰?我遇到过很多次模型精度上不去,最后发现是标注阶段某个类别的框画得太松、包含了过多背景导致的。重新修正标注后,同样配置的模型指标能提升五六个百分点。

5.5 推理结果保存与部署

训练完成后,需要将模型应用到实际推理。yolov11推理命令非常简洁:

yolo predict \ model=runs/detect/conveyor_belt_tear/weights/best.pt \ source=test_images/ \ conf=0.25 \ save=True \ save_txt=True

conf参数是置信度阈值,低于这个值的预测结果会被过滤掉。在缺陷检测场景中,阈值设置取决于你对漏检和误检的容忍度。如果你更怕漏检,把conf降到0.15甚至0.1,但误检会相应增加;如果你更怕误检干扰操作人员,可以设到0.35以上。建议在验证集上做一次阈值扫描,选择Precision和Recall平衡点对应的阈值作为默认值。

save=True会保存标注了检测框的图片,save_txt=True会把检测结果导出为txt文件。txt的每一行格式是:类别ID、置信度、x1、y1、x2、y2(像素坐标),这是后续部署时做业务逻辑处理最常用的格式。

部署到实际生产环境时,我推荐将模型导出为ONNX再使用TensorRT推理,速度和精度都能得到优化。导出命令:

yolo export model=best.pt format=onnx imgsz=1280

导出ONNX后,可以用onnxruntime或TensorRT部署到NVIDIA Jetson系列设备或GPU服务器上。如果是现场没有GPU、只有CPU控制器的情况,ONNX Runtime的CPU推理也可以跑,但速度会明显慢一些,需要根据皮带运行速度评估是否满足实时性要求。

6. 常见问题与排查技巧实录

6.1 标注文件与图片对不上

我碰到过的最典型的问题是:训练时报错“Found no valid images for the indicated train split”或者提示缺少labels文件。这种问题多半是目录结构不对或文件名不匹配。

排查步骤很简单:

  1. 打开data.yaml,确认path指定的是数据集根目录;
  2. 检查images/train和labels/train下的文件是否一一对应;
  3. 确认图片是jpg、png等常见格式,标签是txt,且两者文件名(不含扩展名)完全一致;
  4. 检查txt内容是否为空文件,空文件是允许的,但如果txt不存在,训练时就会跳过对应图片。

还有一个坑:Windows下数据集路径带中文或者空格,可能导致读取失败。解决办法是尽量用英文字符命名所有目录和文件。

6.2 训练时loss不降或mAP为0

loss不降这个问题的排查顺序是:

  • 检查标注是否可靠:随机抽取20张图,用可视化脚本把标注框画到图片上,肉眼确认框和类别没有明显错误。
  • 检查类别映射是否一致:比如标注时类别0是longitudinal_tear,data.yaml里names[0]也必须对应longitudinal_tear,否则模型学习的标签语义就乱了。
  • 检查学习率是否合适:初始学习率太高会导致loss震荡不收敛,太低会收敛极慢。按我给出的命令,lr0设0.001通常不会有问题。
  • 检查是否存在标签全部为空的情况:如果训练集中大量图片没有标签,模型容易偏向预测“没有目标”,导致P、R都很低。

mAP为0(或者一直很接近0)还有一种常见情况:验证集里某个类别在训练集里一个样本都没有。比如训练集里的edge_wear只有3个样本,但验证集里却有20个,模型在训练时几乎没见过这个类,自然无法识别。解决方法是按类别分层划分数据集,确保每个类别在训练集和验证集中的比例大致相同。

6.3 小目标破损漏检严重

漏检是传送带检测项目里最头疼的问题。如果你发现纵向撕裂这种长条形小目标容易被漏检,可以从三个方向优化:

  • 提高输入分辨率:imgsz从640提升到1280,通常能立竿见影地改善小目标检测效果。
  • 增加小目标样本:不要只拍整条皮带的远景图,凑近拍一些缺陷特写,让模型看到更多“近距离”的缺陷形态。
  • 调整预测置信度阈值:推理时把conf调低,例如从0.25降到0.15,召回率会上升,代价是误检增加,需要结合业务取舍。

6.4 把皮带正常纹理误判为破损

误检问题通常源于训练数据中缺少“难负样本”。模型没见过长得像裂纹的正常纹理,自然容易误判。解决方法很直接:往数据集中加入一定比例的负样本图片(正常皮带、有接头纹理的、有油渍水渍的),这些图片的标注txt文件为空。模型在训练中会看到“这些区域虽然没有标注框,但它们是正常的”这一信息,从而降低误检率。

负样本比例不需要太高,占到训练集的10%到20%就够。我从一个项目中得到的经验是:加入15%的正常皮带图片后,误检次数从每100帧七八次降到了每100帧不到一次。

6.5 显存不足怎么办

如果你用的是8GB显存的显卡,训练1280x1280输入、batch=16很容易爆显存。解决办法有几种:

  • 调小batch,比如batch=4或2;
  • 使用梯度累积功能,ultralytics中可以通过batch=16和nbs=64来实现等效大batch效果;
  • 降低输入尺寸,先用640训练,验证流程正确后再根据显存能力尝试更高分辨率;
  • 使用更小的模型版本,比如yolo11n.pt代替yolo11s.pt,参数量更少,训练显存占用更低。

6.6 结果输出坐标怎么用到业务系统里

最后补充一个容易被忽略的点:推理输出的坐标是像素坐标,但在实际业务系统中(比如监控大屏、报警系统、控制PLC),可能需要换算成实际物理坐标或者归一化坐标。yolov11的detect输出的是像素坐标(左上角和右下角),如果你需要的是归一化坐标,用输出坐标除以图片宽高即可。

我在项目里会把检测结果写入数据库并实时推送到监控看板,字段包括时间戳、摄像头ID、缺陷类别、置信度、检测框坐标和对应的截图路径。这样现场人员能快速定位问题,同时为后续分析提供数据支撑。

7. 后续可以怎么扩展

用到这个程度,baseline已经立住了。但如果想进一步提升效果,或者把这个检测能力复制到其他产线、其他设备上,有两条扩展路径值得考虑:

一条是缺陷定位的精细化升级。目前是检测框定位,只能告诉你破损大概在哪个区域。如果需求是要知道破损的精确面积、形态、长度,建议升级到实例分割,用yolov11-seg训练多边形分割模型。标注时需要用多边形勾画缺陷轮廓,而不是用矩形框。这样做的好处是不仅能检测缺陷,还能输出缺陷的面积和周长信息,对评估损坏程度非常有价值。

另一条是多点位巡检和连续监测。单张图片的检测只能发现“当前画面里有没有破损”,但如果要评估破损的扩展速度,需要把检测结果按时间序列关联起来。比如每10分钟对同一位置拍照检测,将检测框位置对齐后计算缺陷面积变化趋势,就能实现破损扩展示警。这个方向结合时序数据分析,能做出更有业务价值的功能。

我做这个项目时最大的体会是:工业视觉项目的瓶颈往往不在算法,而在数据质量。700张图听起来不多,但是如果把采集、清洗、标注、质检每一步都做扎实,训练出来的模型完全能拉到现场用。反过来,数据集质量不过关,哪怕给一万张图、用最牛的模型,效果也未必好到哪里去。

最后再分享一个小技巧:训练后把best.pt在训练集上做一次回验,看看模型能不能完美检测出所有训练样本。如果训练集上都有漏检,说明标注有错或者数据增强过度;如果训练集全对但验证集效果差,说明存在过拟合,需要增加数据或者正则化强度。这个简单的回验操作,能帮你快速定位大部分训练效果不佳的原因。

本文还有配套的精品资源,点击获取

http://www.cnnetsun.cn/news/4220171.html

相关文章:

  • STM32F103 SPI驱动GC9306 TFT屏幕:从时序解析到图形优化实战
  • 大模型知识蒸馏实战:从原理到代码与行业影响分析
  • STM32 DMA实战避坑指南:从配置到稳定运行的全链路解析
  • Linux中断亲和性优化:从硬件中断到用户进程的三级协同
  • Java CDS类加载污染警告根因与实战修复指南
  • 毕业设计实战:基于J2EE的停车场管理系统开发详解
  • STM32低功耗设计实战:从电源域切割到μA级功耗优化
  • 微软测试工程师面试全流程与自动化测试实战
  • STM32 IIC通信从入门到精通:硬件配置、软件模拟与深度调试实战
  • NoC片上网络:SoC互连的底层革命与工程实践
  • Slint + Rust:声明式UI编译器如何实现零运行时桌面GUI
  • 农业建模三阶法:pandas清洗、statsmodels可解释建模与sklearn异常识别
  • Redis客户端全解析:从命令行到SDK与可视化工具实战指南
  • 数学建模实战:基于混合整数规划的洗衣房资源调度优化
  • 煤矿冲击地压预测建模实战:从数据清洗到LightGBM模型调优
  • Android PendingIntent FLAG_IMMUTABLE与FLAG_MUTABLE本质解析
  • 微信分享卡片失效原因与稳定配置全指南
  • Tank OS:基于bootc与OpenClaw的AI智能体一体化部署方案
  • 从IMU噪声到Q矩阵:ESKF过程噪声协方差的物理推导与工程实践
  • 美赛A题解题复盘:从动力系统建模到Python数值模拟的完整实践
  • 软件测试面试200问:从入门到精通全解析
  • AI Agent基础设施全景解析:从核心模块到生产级应用实战
  • 边缘AI时代,IoT设备DRAM选型与低功耗设计指南
  • SQL注入实战:从手工探测到Burp Suite工具利用与防御
  • 有限元与泊松分布在神经外科手术导航中的数学建模与算法实现
  • 基于HTML5 video标签的JavaScript本地视频播放器开发指南
  • 2026网络安全行业求职与学习指南
  • 基于Daisy Seed的桌面级数字音频效果器开发全解析
  • MIPI CSI-2错误处理:分层响应与D-PHY协议协同设计
  • 双非学子预推免逆袭985:策略、准备与面试实战指南