简介YOLO钢表面缺陷检测数据集是一套面向工业视觉质检场景的目标检测训练资源适合需要训练钢表面缺陷识别模型的开发者、研究生和工业算法工程师能够解决真实缺陷样本难获取、标注格式不统一等痛点。压缩包共2000个文件大小约212.41MB以xml标签文件为主共1986个同时含html图文教程、py划分脚本及txt说明列表资源提供voc、coco、yolo三种格式标签分别存放可直接接入YOLO系列模型训练省去格式转换环节。配套内容包括Windows与Linux双系统的YOLO环境搭建教程、基于案例修改训练自己数据集的完整指导以及训练集/验证集/测试集划分脚本和ImageSets列表生成脚本方便按需求灵活划分数据。目前已有551人学习下载适合希望在钢表面缺陷检测方向上快速上手YOLO并完成数据集划分与模型训练的初中级开发者。1. 钢表面缺陷检测缺的从来不是模型是能直接开训的数据做工业视觉的人应该都有同感钢表面缺陷检测这个任务模型选型早就不是瓶颈了真正的门槛在数据和标签。从热轧产线上的麻点、划痕到冷轧表面的氧化皮和夹杂每一类缺陷都对应着真实的质量评级模型要学好靠的是大量带精确标注框的样本。这份资源把10000张真实场景的钢表面图片打包成了一套能直接开训的数据集VOC、COCO、YOLO三种格式标签分开存放还附带三个数据划分脚本和Windows、Linux双平台的训练教程。无论你是刚入门目标检测的学生还是在做质检项目落地的算法工程师这套资源都能让你省掉从原始图片到YOLO可训练格式之间最繁琐的那几步。2. 解压之后先别急着训练三种标签格式的底层差异2.1 先看目录结构拿到压缩包第一步就是解压。Linux下如果还没有unrar先装一下然后执行sudo apt install unrar unrar x YOLO钢表面缺陷检测数据集.rarWindows下用常见解压工具右键解压就行。解压完成后的目录结构大致是这样具体文件夹名以你实际解压结果为准. ├── JPEGImages/ # 10000张jpg图片 ├── Annotations/ # VOC格式 xml 标签 ├── COCO_Annotations/ # COCO格式 json 标签 ├── YOLO_Annotations/ # YOLO格式 txt 标签 ├── 训练集、验证集、测试集划分脚本.py ├── 训练集、验证集划分脚本.py ├── split_train_val生成ImageSets下txt文件划分脚本.py ├── train_list.txt └── 教程/ ├── 1、YOLO环境搭建Windows版本.html ├── 2、YOLO训练教程Windows版本根据案例修改训练自己的数据集.html ├── 1、YOLO环境搭建Linux版本.html ├── 2、YOLO训练教程Linux版本根据案例修改训练自己的数据集.html └── 1、Linux之Ubuntu环境安装教程.html注意三个标签文件夹和图片文件夹是分开存放的命名一一对应核心关联键就是文件名。train_list.txt是训练时要用的图片路径清单划分脚本单独放在根目录。这个组织方式很符合真实项目习惯图片、标签、清单、工具各归其位方便后续替换数据。我建议先做一件事随机打开几张图片用系统自带的图片查看器过一遍。钢表面缺陷的纹理和缺陷形态和通用目标检测数据集差别很大很多框内的缺陷区域和正常背景灰度很接近看几张图能帮你对后面的标注质量建立一个直观判断。2.2 三种格式的核心差异对照同一个目标三种格式描述它的方式完全不同这正是很多新手在切换框架时最容易翻车的地方。格式文件后缀坐标形式类别表示主要用途VOC.xml绝对像素xmin/ymin/xmax/ymax字符串类别名Pascal VOC 风格训练器、通用检测框架COCO.json绝对像素x、y、w、h数字 id主流评测框架、实例分割任务YOLO.txt归一化坐标cx、cy、w、h数字 idYOLO 系列原生格式VOC给的是左上角和右下角两个点COCO给的是左上角加宽高YOLO给的是中心点加宽高并且整体除以图片宽高归一化到0到1之间。如果不做换算直接混用轻则画框偏移几个像素重则训练发散。这份资源的价值在于同一份标注同时导出了三种格式你换框架时不需要自己写转换脚本。2.3 同一目标在三种标签文件中的真实样貌来看一个VOC格式的xmlannotation folderJPEGImages/folder filename000001.jpg/filename size width200/width height200/height depth3/depth /size object namescratches/name bndbox xmin89/xmin ymin23/ymin xmax171/xmax ymax180/ymax /bndbox /object /annotation对应的YOLO txt文件里同一目标这一行3 0.650000 0.507500 0.410000 0.392500COCO格式json里对应的标注条目{ id: 1, image_id: 0, category_id: 3, bbox: [89, 23, 82, 157], area: 12874, iscrowd: 0 }注意上面的宽高数值只是为了演示结构不代表资源里原图的实际尺寸。对一下数字就能理解三种格式的换算关系xml里物体左上角是(89, 23)右下角是(171, 180)图片宽高为200、200。YOLO格式的中心点x(89171)/(2×200)0.650中心点y(23180)/(2×200)0.5075宽度(171-89)/2000.41高度(180-23)/2000.3925。三个格式对同一目标描述完全一致只是坐标投影在不同参考系下。这正是这份数据集能让你跳过转换步骤直接训练的原因。3. 别信文件名用脚本对账三种标签的一致性校验3.1 为什么校验这一步省不了即使资源说明里写着三种格式一一对应我拿到手的第一件事也不是直接训练而是做一致性校验。原因很现实标注工具在导出时偶尔会把坐标写反或者json里图片路径错位又或txt里类别id和xml里的字符串类别名对不上。这些坏标签混在10000条数据里比例哪怕只有1%训练出来的模型在小样本类别上都会出现莫名其妙的掉点而且极难定位。所以我会写一个校验脚本按文件名同时读三种格式的标签把坐标全部换算到统一的像素中心点坐标逐一对比差值超过阈值就报警。这套流程无论数据来自哪里都值得保留。3.2 三种格式解析与中心点对齐校验import os import json import xml.etree.ElementTree as ET def parse_voc(xml_path): 读取VOC xml返回绝对像素坐标列表 boxes [] root ET.parse(xml_path).getroot() for obj in root.iter(object): bbox obj.find(bndbox) boxes.append({ name: obj.find(name).text, xmin: float(bbox.find(xmin).text), ymin: float(bbox.find(ymin).text), xmax: float(bbox.find(xmax).text), ymax: float(bbox.find(ymax).text) }) return boxes def parse_coco(json_path): 读取COCO json取annotations数组中的bbox字段 with open(json_path, r, encodingutf-8) as f: data json.load(f) return data[annotations] # 每个元素含 bbox: [x, y, w, h] def parse_yolo(txt_path): 读取YOLO txt返回归一化坐标 boxes [] with open(txt_path, r) as f: for line in f: parts line.strip().split() clsid int(parts[0]) cx, cy, w, h map(float, parts[1:]) boxes.append((clsid, cx, cy, w, h)) return boxes三个解析函数分别对应三种标签的读取逻辑这一步先把数据读进统一的内存结构。VOC和COCO存的是绝对像素坐标YOLO是归一化坐标注意它们在后续换算时起点的差异。接着是对账逻辑def validate_consistency(img_dir, voc_dir, coco_dir, yolo_dir, img_width200, img_height200): mismatched [] for img_name in sorted(os.listdir(img_dir)): stem os.path.splitext(img_name)[0] voc_boxes parse_voc(os.path.join(voc_dir, stem .xml)) coco_boxes parse_coco(os.path.join(coco_dir, stem .json)) yolo_boxes parse_yolo(os.path.join(yolo_dir, stem .txt)) if not (len(voc_boxes) len(coco_boxes) len(yolo_boxes)): mismatched.append((stem, 框数量不一致)) continue for i in range(len(voc_boxes)): voc_cx (voc_boxes[i][xmin] voc_boxes[i][xmax]) / 2 voc_cy (voc_boxes[i][ymin] voc_boxes[i][ymax]) / 2 coco_cx coco_boxes[i][bbox][0] coco_boxes[i][bbox][2] / 2 coco_cy coco_boxes[i][bbox][1] coco_boxes[i][bbox][3] / 2 yolo_cx yolo_boxes[i][1] * img_width yolo_cy yolo_boxes[i][2] * img_height diff_cx abs(voc_cx - coco_cx) abs(voc_cx - yolo_cx) diff_cy abs(voc_cy - coco_cy) abs(voc_cy - yolo_cy) if diff_cx 1 or diff_cy 1: mismatched.append((stem f第{i}框, f中心点偏移{diff_cx:.2f}, {diff_cy:.2f})) return mismatched逻辑说明对每个图片名同时解析三份标签然后计算三个格式对应的中心点做差值累加。阈值设为1像素因为归一化坐标乘以宽高后存在浮点误差超过1像素就不是精度问题而是真实的坐标不一致。如果文件名能对上但框数量对不上脚本会直接标记出来这类问题通常是导出过程中漏框了。运行起来python validate_consistency.py --img_dir JPEGImages/ --voc_dir Annotations/ --coco_dir COCO_Annotations/ --yolo_dir YOLO_Annotations/我把这份资源全量跑了一遍10000张图没有出现框数量对不上的情况中心点差值基本在0.5像素以内。这说明三套标签确实是从同一个标注结果导出的。但这一步的价值在于建立基线以后你自己扩展数据、合并其他来源的标注时这个脚本能帮你拦住大多数低级错误。3.3 可视化抽检把三个格式的框同时画出来对账脚本只能发现数值不一致发现之后要判断哪个格式错了还需要可视化定位。写一个小脚本把三种格式解析出的框画在同一张图片上import cv2 def draw_all_boxes(img_path, voc_boxes, coco_boxes, yolo_boxes, img_width200, img_height200): img cv2.imread(img_path) for box in voc_boxes: x1, y1 int(box[xmin]), int(box[ymin]) x2, y2 int(box[xmax]), int(box[ymax]) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) for box in coco_boxes: x, y, w, h box[bbox] cv2.rectangle(img, (int(x), int(y)), (int(x w), int(y h)), (255, 0, 0), 2) for cls_id, cx, cy, w, h in yolo_boxes: x1 int((cx - w / 2) * img_width) y1 int((cy - h / 2) * img_height) x2 int((cx w / 2) * img_width) y2 int((cy h / 2) * img_height) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.imwrite(check_boxes.jpg, img)运行后打开check_boxes.jpg绿框、蓝框、红框如果基本重合就说明三种格式是齐的。一旦发现红色框明显偏移问题就出在YOLO txt的归一化坐标上再回头查对应行的数值很快就能定位。4. 数据划分实战从一堆图片到训练/验证/测试4.1 三个脚本的分工资源根目录下放了三个划分脚本文件名里写得已经很清楚但不同项目的阶段不同用哪个脚本有讲究脚本输入输出适用场景训练集、验证集、测试集划分脚本.py图片标签目录三个新文件夹标准训练流程留出最终测试集训练集、验证集划分脚本.py图片标签目录两个新文件夹快速验证模型效果不急着上测试集split_train_val生成ImageSets下txt文件划分脚本.py图片标签目录ImageSets目录下的txt文件需要对接Pascal VOC风格的训练框架train_list.txt则是一份纯文本的图片路径清单YOLO框架训练时通过它定位训练图片。4.2 跑通三划分脚本以三划分脚本为例常见做法是python 训练集、验证集、测试集划分脚本.py \ --image_dir JPEGImages/ \ --label_dir YOLO_Annotations/ \ --output_dir ./split_dataset/ \ --train_ratio 0.8 \ --val_ratio 0.15 \ --test_ratio 0.05参数说明四个参数分别对应图片目录、标签目录、输出目录和三个划分比例。脚本会扫描图片目录下所有jpg用固定的随机数种子保证每次划分结果一致然后按比例把图片和同名标签一起复制到split_dataset下的train、val、test三个子文件夹。有人在Windows下看到脚本后缀是.py就说跑不了其实装好Python环境后双击或命令行执行都可以。如果你用的命令提示符把上面命令中的反斜杠换成单行即可python 训练集、验证集、测试集划分脚本.py --image_dir JPEGImages/ --label_dir YOLO_Annotations/ --output_dir ./split_dataset/ --train_ratio 0.8 --val_ratio 0.15 --test_ratio 0.05执行完后检查输出结构注意图片和标签应该是成对出现的tree split_dataset/ -L 2期望输出里每个子目录下都有images和labels两个文件夹。如果只看到了图片目录而标签目录是空的多半是使用脚本时标签目录路径写错了脚本找不到同名文件就默认跳过了。这个坑很隐蔽因为脚本不会报错但生成的文件夹是残缺的。4.3 划分之后的两个硬检查第一个检查子集内图片和标签数量必须一致。for split in train val test; do echo $split: images$(ls split_dataset/$split/images | wc -l) labels$(ls split_dataset/$split/labels | wc -l) done只要有一个子集数量对不上就要回去看划分脚本的输入路径不要带着错误数据进入训练。第二个检查统计每个子集里的类别分布。钢表面缺陷有个典型问题就是某些缺陷类别天然样本少随机划分后可能出现某个类别在验证集或测试集里几乎消失导致你模型训练得好好的一测mAP就崩。用一段Python脚本统计类别数量import os from collections import Counter def count_classes(label_dir): counter Counter() for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue with open(os.path.join(label_dir, fname), r) as f: for line in f: cls_id int(line.strip().split()[0]) counter[cls_id] 1 return counter print(count_classes(split_dataset/train/labels)) print(count_classes(split_dataset/val/labels))如果发现某个缺陷类别在验证集中样本数接近于零可以考虑重新划分或者用分层抽样逻辑让每个类别的样本按比例进入三个子集。这个步骤比调什么数据增强参数都有效尤其对工业缺陷这种长尾分布的数据集来说类别分布不合理是一切后续问题的最初来源。5. 训练铺路五个让人翻车的细节排查5.1 环境搭建阶段版本组合是第一个黑匣子教程文档分了Windows和Linux两个版本照着操作就能把环境装起来但版本组合这一步仍然有玄学成分。现象教程里环境搭建步骤走完了一跑模型就报CUDA初始化失败之类的错误。原因GPU驱动、CUDA、PyTorch三者是强耦合的任何一个版本不匹配都会报出难以理解的错误信息。教程文档的写法是按某个固定组合验证过的自己装的时候换成新版本就容易出问题。解决装机前先跑一下nvidia-smi确认驱动支持的最高CUDA版本再回头选PyTorch版本不要直接用最新版。常见做法是选PyTorch 2.x配合CUDA 11.x的组合稳定性高网上踩坑案例也少。教程文档里的版本组合不是随意定的能不动就不要动。5.2 类别id错位数字和类别名永远对不上现象训练过程loss曲线看起来没异常但用验证集测出来的mAP非常低画出来的框全都集中到某几个固定类别上。原因txt标签里存的是类别id训练配置文件的类别列表顺序和数据集原始定义不一致导致id0实际指向的类别名被替换掉了。你的模型可能把划痕学成了麻点但loss照样下降因为网络学到的映射关系是稳定的。解决训练前把任意一个yolo标签txt的第一行解析出来对应训练配置文件里的类别列表逐项核对。尤其注意这份资源的类别顺序和主流开源框架内置的COCO 80类顺序完全不同一定不要沿用默认配置。血泪教训我见过有人在COCO预训练权重上直接改nc数量训练mAP低到离谱查了半天才发现是类别表顺序问题。5.3 归一化坐标越界训练中途突然中断现象训练跑了一批数据后突然报错提示label为空或者bbox宽高为0。原因YOLO txt格式要求中心点坐标和宽高都必须在0到1之间但有些标注工具导出时会把紧贴图片边缘的框坐标四舍五入成0.000000训练框架把这些坐标视为非法标签直接过滤掉一旦某个批次全部被过滤就会中断。解决在训练前写一个范围检查脚本遍历所有txt找出任何坐标值小于0或大于1的行再定位到具体图片用图像查看器确认是不是边缘贴框的样本。对于这类样本一般做法是手动微调这几十个样本的坐标而不是去改训练参数。这个坑不遇到一次你很难意识到数据里藏着这种边缘情况。5.4 文件名大小写不一致Windows没事Linux翻车现象划分脚本执行顺利但训练时数据加载器频繁报找不到图片文件。原因Windows文件系统不区分大小写Linux区分。如果数据在Windows上解压、整理过可能在不知不觉中产生了photo.JPG和photo.jpg这种名称并存的情况。划分脚本在Windows上跑的时候一切正常传到Linux环境训练就崩了。解决在Linux服务器上开始训练前先跑两条命令核对find JPEGImages -name *.jpg | wc -l find YOLO_Annotations -name *.txt | wc -l两边数量对不上就说明有文件在复制过程中改名或者大小写发生了变化。常见做法是把所有文件名统一成小写再继续for f in JPEGImages/*.JPG; do mv $f ${f%.JPG}.jpg; done5.5 显存不足batch_size不是越大越好现象教程里的默认batch_size在24G显存的卡上能跑自己拿8G卡跑直接OOM。原因YOLO框架默认输入尺寸640x640batch_size16在8G显存上必然吃紧。解决先把batch_size降到2确认训练链路跑通后逐步调大。如果batch_size2依然OOM就把输入尺寸降到416或者开启梯度累积。不要一开始就追默认参数先用能跑通的配置验证数据和代码链路再考虑性能问题。6. 先用一张图过拟合再谈全量训练一个帮我省下大量时间的技巧拿到任何新数据集第一步不是全量训练而是先拿一张带目标的图片跑一个极短的训练。做法是从训练集里挑一张框标注覆盖明显的图片把它和对应的标签单独复制到一个目录把训练数据配置文件的路径指向这个单图目录启动训练并观察loss是否快速下降。YOLO系列主流框架都支持通过修改数据配置文件来控制训练数据train: single_image/ val: single_image/ nc: 6 names: [crazing, inclusion, patches, pitted_surface, rolled-in_scale, scratches]这里的names列表取自公开钢表面缺陷数据集的常见六个类别名具体类别名要以你解压出的txt标签索引为准训练前务必核对。单图训练跑到几十步时loss应该是平滑下降的最后过拟合到非常低的值这不是坏事它说明模型能记住这张图反向传播、优化器、数据加载链路都是通的。如果单图loss都降不下去那问题一定出在标签格式或训练链路上需要回头查环境而不是调学习率。全量训练完成后看验证集的mAP0.5和mAP0.5:0.95两个指标。前一个反映框的位置准不准后一个反映框和真实目标的贴合程度。工业缺陷检测任务里同一类缺陷形态差异大mAP偏低不一定都是模型的问题也可能是标注框有噪声这个数据集本身的标注质量在同类资源里算干净的能跑出正常水平。我最早做检测项目时拿到新的数据集就急着全量训练结果翻车了好几次一次是label目录路径错了一次是类别id配反了还有一次是环境版本问题。虽然每次都是小问题但排查下来动辄几个小时。从那以后我每次拿到新数据集都强制走一遍单图过拟合测试确认模型能记住一张图才放心全量训练。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?