拓冰建站拓冰建站
首页 / 资讯中心 / 正文

木材表面缺陷检测:YOLOv5数据集标注、训练调参与部署完整指南

简介这份木材表面缺陷检测数据集面向计算机视觉研究与工业质检开发者可用于训练木材表面裂纹、节疤、腐朽等缺陷识别模型。压缩包共1897个文件主要包含948张jpg原始木材图像与948个txt YOLO格式标注文件另附1个yaml类别配置文件整体约38.13MBtxt标注可直接对接YOLOV5训练流程yaml用于指定类别与路径结构精简便于快速投入使用。资源同时支持YOLO、COCO JSON、Pascal VOC XML与Darknet格式标注平均正确识别率达95.0%可减少标注格式转换与数据清洗的重复工作方便读者在多种检测框架间灵活迁移。目前已有155人学习下载适合需要高质量木材表面缺陷样本和标准标注的算法入门者及产线项目开发者。1. 木材表面缺陷检测数据集配合YOLOv5训练是木材质检从人工目检转向自动化最顺滑的一条路产线上老师傅凭肉眼盯裂纹、节疤、虫眼高速传送带下漏检率居高不下改让模型来检测稳定性和效率都能上一个台阶。我现在拆的这份数据集图片以gothong-编号为文件主名同时支持YOLO TXT、COCO JSON、Pascal VOC XML和DarkNet四种标注格式官方标称平均正确识别率95.0%。也就是说用这套标注做监督训练常规难度样本下精度能到95%左右。适合正在做木材缺陷检测毕业设计或者准备给板材产线搭视觉方案的人。接下来从标注格式一路拆到训练、调参、排错和落地迁移。2. 数据集结构与标注格式YOLO TXT、COCO JSON、VOC XML 的转换与校验拿到数据集第一步不是急着开训练而是把目录结构和标注格式吃透。这份数据的图片文件名形如gothong-618-_jpg.rf.71f7b99d495d62fae59712e60391aa9f.jpg对应的标签文件在YOLO格式下是同名.txt。rf是Roboflow平台导出的标记表示图片已经被统一缩放、划分数据集并重命名后面的哈希串是原图去重后的唯一标识。理解了这一点就知道为什么直接拿原始文件名排序是不可靠的要按照文件清单或目录配对。2.1 目录结构与文件命名隐含的信息Roboflow导出的数据集一般分成train/valid/test三个子集。每个子集内images和labels平级YOLO格式的标注文件与图片同名但扩展名为.txt。例如wood-defect-dataset/ ├── train/ │ ├── images/ │ │ ├── gothong-618-_jpg.rf....jpg │ │ └── ... │ └── labels/ │ ├── gothong-618-_jpg.rf....txt │ └── ... ├── valid/ └── test/图片本身来自连续木材板面的拍摄部分带有生产环境的光影变化。缺陷类别在标签文件夹里通过classes.txt定义顺序决定了模型输出的类别编号train.txt和valid.txt是图片路径列表data.yaml是YOLOv5直接读取的数据申明文件。目录里如果缺失某个子集训练前要自己用random_split从原图里重新划分不然验证指标没有参考意义。2.2 YOLO TXT标签格式归一化坐标与类别idYOLO格式的每个.txt文件里一行代表一个目标框五列分别是类别id、中心点x、中心点y、宽度w、高度h全部归一化到01之间。比如一个节疤框的标注可能是1 0.515625 0.476667 0.235000 0.213333 2 0.789062 0.812500 0.173438 0.136667第一列是类别编号第二、三列是中心点坐标除以图片宽高后的比例第四、五列是框宽高除以图片宽高。这种归一化坐标与图片本身分辨率解耦所以换到其它模型时不需要重新计算实际像素值。各格式最核心的区别是在坐标定义上转换时容易踩坑通常记住下面这张表就够了格式坐标系坐标定义典型框架YOLO归一化class cx cy w hYOLOv5、YOLOv8、DarkNetCOCO绝对像素x y width heightMMDetection、Detectron2VOC绝对像素xmin ymin xmax ymaxFaster RCNN原始实现2.2.1 DarkNet格式为什么和YOLO一致DarkNet框架使用的训练标签格式与YOLOv5完全相同都是归一化中心坐标区别只在于类别名文件和目录组织方式。所以摘要里标注的“支持DarkNet”可以理解为这份数据集的labels目录不需要二次转换直接挂给darknet源码即可。一般我会在DarkNet的cfg中指定classes数和data文件里的names路径其余训练流程与YOLOv5类似。2.3 转为COCO JSON与Pascal VOC XML的脚本示例如果你用的是Faster RCNN、MMDetection这类框架往往需要COCO或VOC格式。Roboflow导出的压缩包里通常已经自带这三种格式但有时我们只拿到了YOLO标注转换就得自己写。常见的做法是先读取所有.txt再把坐标换算回像素组装成COCO的annotations数组。下面这段脚本演示了核心转换逻辑import os import json from PIL import Image def yolo_to_coco(img_dir, label_dir, classes, out_json): coco {images: [], annotations: [], categories: [{id: i, name: n} for i, n in enumerate(classes)]} ann_id 1 for idx, img_name in enumerate(os.listdir(img_dir)): if not img_name.endswith(.jpg): continue img_path os.path.join(img_dir, img_name) w, h Image.open(img_path).size coco[images].append({ id: idx, file_name: img_name, width: w, height: h}) label_path os.path.join(label_dir, img_name.replace(.jpg, .txt)) if not os.path.exists(label_path): continue with open(label_path) as f: for line in f: cls, cx, cy, bw, bh map(float, line.split()) x (cx - bw / 2) * w y (cy - bh / 2) * h coco[annotations].append({ id: ann_id, image_id: idx, category_id: int(cls), bbox: [x, y, bw * w, bh * h], area: bw * w * bh * h, iscrowd: 0 }) ann_id 1 with open(out_json, w) as f: json.dump(coco, f)这段脚本里cx、cy是中心点相对坐标所以x (cx - bw/2)*w都是先反归一化再转成左上角坐标。注意COCO的bbox格式是[x, y, width, height]而VOC是xmin, ymin, xmax, ymax转换时别把顺序搞反。如果图片是那种大尺寸高分辨率的建议转换前先按指定宽度等比缩放这样后续训练预显存占用小很多。2.4 标注质量校验可视化标注框标注文件再规范也挡不住原始标注漏标或标偏。训练前我一般会随机抽几张图做可视化校验。最简单的方式是直接用OpenCV把标签画回去import cv2 def draw_yolo_boxes(img, label_txt, classes): h, w img.shape[:2] with open(label_txt) as f: for line in f: cls, cx, cy, bw, bh map(float, line.split()) x1 int((cx - bw/2) * w) y1 int((cy - bh/2) * h) x2 int((cx bw/2) * w) y2 int((cy bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(img, classes[int(cls)], (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) return img画完直接看缺陷框是不是贴合纹理变化区域。木材缺陷和背景的边缘常常比较糊如果框明显大一圈或小一圈说明标注时的包围盒策略不一致训练出来mAP会打折扣。这一步花二十分钟后面能省两个小时调参。3. 用YOLOv5训练木材缺陷模型环境、配置与训练命令标注验证没问题就能进训练环节了。这章给出一条完整可复用的命令链路从环境准备到输出权重每一步都说明关键参数的取舍避免生成一堆没意义的训练日志。3.1 数据目录组织images与labels之间的对应关系YOLOv5的train.py并不直接扫描整个数据集而是通过data.yaml中的train和val字段拿到图片路径列表。路径列表的每一行就是图片的绝对路径或相对路径YOLOv5会自动把.jpg替换成.txt找标签。所以只要保证两个目录的层级关系一致就行不需要把labels和images硬放在一起。常见的准备步骤是把原始Roboflow目录结构直接交给YOLOv5。新建项目根目录后把train/images、train/labels、valid/images、valid/labels都拷贝过去同时把data.yaml放好。注意YOLOv5要求val不能为空哪怕你只有几十张验证图也要单独留出来否则程序会在最后计算mAP时直接崩掉。3.2 编写data.yaml与模型配置文件data.yaml是训练入口的关键文件。以这段最简配置为例train: ./wood-defect/train/images val: ./wood-defect/valid/images nc: 5 # 以实际classes.txt为准 names: [crack, knot, dead_knot, blue_stain, resin] # 仅示例请用数据集中的类别名nc是类别总数names的顺序必须和classes.txt完全一致。YOLO的类别id是从0开始的训练结果里的0永远对应names[0]。这份数据集的类别名我没有逐个核对你拿到后先打开classes.txt用cat列一下再照抄进names。模型配置文件推荐直接用自带目录里的yolov5s.yaml或yolov5m.yaml。木材缺陷框往往不大用yolov5s起步足够训练速度也快。如果显存充裕再换yolov5l。要注意的是模型配置文件里的nc也需要对应修改改动量三行# yolov5s.yaml 中 nc: 5 # 改成实际类别数3.3 执行训练命令与关键超参数说明万事俱备以后直接跑python train.py --img 640 --batch 16 --epochs 100 \ --data wood-defect.yaml --cfg yolov5s.yaml \ --weights yolov5s.pt --name wood_defect \ --cache参数含义拆开来看--img输入的训练分辨率。640是YOLOv5的默认值如果缺陷目标相对整图很小提到768或896可以提升小目标召回但显存翻倍。--batchbatch size。显存不够就先降到8但要注意batch太小时BN层统计不稳定建议同时把--workers降到4。--epochs训练轮数。木材缺陷这种单场景任务100轮基本够了过多容易过拟合。--weights预训练权重。加载COCO上的yolov5s.pt能大幅加速收敛尤其适合这类样本量不大的数据集。--cache将图片一次性加载进内存。森林木材图片如果都是大尺寸且机位固定用--cache可以显著减少IO等待但内存低于16G时慎用。3.3.1 显存不够时的降级组合当batch size只能开到4时训练会很不稳定。我的做法是把--workers降到2开启--rect减少padding并且把--img降到512等模型先收敛到mAP0.8左右再用640分辨率继续微调20轮。这个流程比直接硬撑batch size要稳得多。3.4 训练日志与mAP指标解读训练完终端会打印Class、Images、Instances、P、R、mAP50等列。其中mAP500.5是指IoU阈值0.5下的平均精度是衡量“平均正确识别率”最常用的替代指标。如果mAP50在验证集上到0.95基本可以对应官方所说的95.0%正确识别率。换到现场数据集之前先别急着高兴因为分布偏移会让这个数字掉到0.8甚至更低。后面第四章专门讲怎么稳住这个数。4. 把识别率从80%拉升到95%数据增强、anchors与训练策略调优很多人下载了优秀数据集直接默认参数训练mAP常年在0.8上不去。问题往往不在网络结构而在训练配置和标注本身。这章谈三个有效方向数据增强、anchor聚类和超参调整。4.1 数据增强策略Mosaic、MixUp与HSV扰动YOLOv5默认开了Mosaic和HSV。Mosaic每次把四张图拼成一张让模型在归一化坐标上看到更多小目标对木材表面那种零散分布的裂纹很有帮助。但如果你的缺陷框已经很小Mosaic拼完会进一步缩小目标所以要控制它生效的概率。调整幅度在train.py的超参文件hyp.scratch-low.yaml里mosaic: 1.0 # 1.0表示每批都启用 mixup: 0.0 # 木材缺陷边界模糊开mixup容易把类别搞混 hsv_h: 0.015 # 色调增强木材纹理灰度差异小可稍微加大 hsv_s: 0.7 # 饱和度增强 hsv_v: 0.4 # 明度增强模拟不同光照常见做法是开局把Mosaic保持1.0到后30轮改成0.5让模型在接近真实分布的图上细调。改法是在训练命令里增加一个自定义超参文件比如hyp_wood.yaml里面只覆盖你想改的项。4.2 重新聚类anchors用小目标框换更合适的先验YOLOv5默认anchors基于COCO的80类目标矩形框偏大。木材缺陷里的死节、小裂纹往往只有十几个像素宽用默认anchors会拉低召回。YOLOv5自带anchor聚类工具直接对这份数据集的标签做k-meanspython train.py --data wood-defect.yaml --epochs 1 --cfg yolov5s.yaml \ --weights yolov5s.pt --name anchor_check --noautoanchor先跑一次让程序统计最佳anchor再把打印出来的anchors:段复制到yolov5s.yaml中覆盖原值。我一般会在训练前用--noautoanchor关掉自动聚类让它用我手动写好的先验这样复现实验结果更稳定。注意anchor的长度必须按[w, h]成对写且要归一化到输入图片尺寸下例如[10, 13, 16, 30, ...]对应的是640尺度下的像素。4.2.1 使用autoanchor的注意事项如果你让YOLOv5自动执行anchor聚类它会检查当前anchors与真实标注的召回率如果召回低于0.98就会重新聚类。聚类结果依赖随机种子不同机器跑出来的anchors略有不同所以我建议把最终采用的anchors固定进yaml避免每次训练结果都比不上。4.3 学习率与batch size的配合迁移学习场景下初始学习率太大和太小都有问题。YOLOv5默认lr00.01但batch size只有8或者4时建议降到0.001附近python train.py --img 640 --batch 8 --epochs 100 \ --data wood-defect.yaml --cfg yolov5s.yaml \ --weights yolov5s.pt --name wood_lr \ --hyp hyp_wood.yaml --cos-lr--cos-lr让学习率按余弦曲线从0.001降到接近0比step衰减更稳。如果训练曲线前20轮loss纹丝不动先把warmup_epochs从默认3加大到5给预训练权重更多适应时间。上面这些参数没有绝对标准每个数据集都要来回试几轮用TensorBoard盯曲线调整才是常态。4.4 如何验证“平均正确识别率95%”这个指标官方给出的95.0%通常是在固定划分的测试集上测试得到的。想复现这个数字需要先确认自己的划分和官方完全一致。Roboflow导出的data.yaml里自带test路径如果不小心删除了test可以用val上的结果做参考但数值会有波动。验证命令python val.py --data wood-defect.yaml --weights runs/train/wood_defect/weights/best.pt --img 640 --conf 0.25--conf是置信度阈值默认0.25调高可以降低误检调低可以提升召回。在木材质检场景漏检比误检更严重所以我通常把--conf设在0.10.15并统计置信度曲线找精度和召回曲线的交叉点再定生产阈值。5. 训练与推理中的常见坑标注错位、类别不平衡与过拟合排错数据集再干净受木材纹理等因素影响训练中也总有几条诡异日志。这一章直接以现象找原因给出排查路径。5.1 现象loss下降但mAP不涨先看标注框是否错位如果你做了可视化校验会看到某些标注框的中心点偏向纹理暗区或者宽度明显比缺陷实际边缘大。这是因为木材表面缺陷边界是渐变过渡的不同标注员对“哪里算起点”的理解不一样。解决办法是统一标注规则比如裂纹以可见黑色断裂区域外圈为准节疤以颜色突变边界为准。执行层面直接打开标签txt检查是否有坐标为负值或大于1的情况awk {if($20||$21||$30||$31) print $0} train/labels/*.txt | head如果有异常用Python批量钳制到01之间并把小于0.01的框删掉。5.2 现象某一类召回率特别低考虑类别不平衡木材数据集中裂纹和大节疤数量往往远多于虫眼或蓝变。类别不平衡会让模型整体偏向样本多的类。处理方式有三种一是重复少数类图片做过采样二是在loss上给少数类加权重三是用更细粒度的类别合并。最简单的是在--hyp超参里调整cls_pw把少数类的box loss权重加大。比如你的类别分布是{crack: 600, blue_stain: 60}那么让blue_stain的样本权重接近1.5代码上可以在数据装载器里按类别出现频率重写采样器。5.3 现象训练损失下降但验证mAP波动剧烈这种情况通常是验证集太小或数据分布和训练集重叠。Roboflow划分时用的随机分配可能导致同一块木材的不同区域同时出现在训练和验证里模型等于记住了场景。如果有可用的时间段标记最好按拍摄批次或木材批号划分。没有的话就用GroupKFold按文件名前缀分组再重新划分数据集。5.4 现象显存不足或训练中途OOM木材原图分辨率经常达到4000×3000直接用原始尺寸训练肯定爆显存。我的做法是先用脚本把长边缩放到1280再在训练时用--img 640配合--rect开启矩形训练。--rect会让同一batch内的图片高宽比保持一致减少padding造成的多余计算。但如果开启--rect后数据加载乱序需要保证每个epoch的batch划分重置YOLOv5自动处理了这点所以可以放心用。6. 从数据集到落地验证、导出与迁移到YOLOv8的快速通道最后把训练得到的权重推到实际应用里。这里只讲几个高性价比步骤。6.1 用val脚本导出不同指标的测试报告除了mAP你还需要一个逐类的置信度-召回率汇总表。YOLOv5的val.py会在输出目录生成confusion_matrix.png但想看精确数字可以用--save-json把结果导出为COCO格式的JSON然后调用pycocotools打印详细表格python val.py --data wood-defect.yaml --weights best.pt --save-json --img 640JSON里包含每个类别的AP、AR以及不同maxDets下的召回率。对照表格看是哪一类拖了后腿比单看一个95%有用得多。6.2 导出为ONNX并做单图推理产线上通常用TensorRT或OpenVINO先把PyTorch权重转成ONNX中间格式python export.py --weights runs/train/wood_defect/weights/best.pt --img 640 --include onnx导出后用ONNX Runtime推理时注意YOLOv5的输入输出是1×3×640×640和1×25200×85需要自己做NMS。如果你觉得麻烦推荐直接用官方提供的detect.py加--weights best.pt验证视频流把置信度阈值设成0.2再观察漏检率。6.2.1 ONNX输出尺寸与预处理保持一致的技巧转换时指定的--img 640必须与训练时的输入尺寸一致否则输出张量的维度会变。如果训练用了--rect导出时不要开启因为ONNX需要固定输入形状。部署端做预处理时图像缩放要使用letterbox保持长宽比并填充灰色边框这与YOLOv5的验证流程一致。6.3 迁移到YOLOv8的小样本微调新项目如果直接换到YOLOv8训木材缺陷可以把这份数据集的yaml直接复用。YOLOv8的data.yaml几乎和YOLOv5一样只需要把train和val改成本地路径。然后执行yolo train modelyolov8s.pt datawood-defect.yaml epochs100 imgsz640YOLOv8默认关闭了部分数据增强遇到木材这种低纹理目标反而比YOLOv5稳。用小样本微调时建议冻结前10层特征提取只训练最后检测头让模型先适应木材表面的颜色分布再逐步解冻。这份数据集本身就是从混合场景抽出来的直接当预训练数据用通常能在几十张新图上快速收敛。实际操作时把旧数据和新数据按7:3混合比单独用新数据效果好这是我在多种缺陷检测项目里反复验证过的做法。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门