
简介基于YOLOv8的热轧带钢表面缺陷检测完整实践包面向深度学习初学者、工业质检算法工程师及智能制造相关研究者。针对横向裂缝、纵向裂缝、块状裂缝、龟裂、坑槽等多类缺陷提供从数据集准备、模型训练、微调到推理评估的整套流程可有效支撑实际产线质量检测场景的快速复现与二次开发。资源共2000个文件以1808个txt标注与说明文件为主体搭配161个Markdown教程文档、14个Python训练/推理脚本、YAML配置文件及C部署源码整体压缩包约74.49MB结构清晰、便于按模块查阅。已有841人学习下载适合希望通过实操掌握YOLOv8目标检测并落地工业表面缺陷识别任务的读者。1. 热轧带钢缺陷检测为什么绕不开YOLOv8热轧产线上带钢表面一旦出现横向裂纹、龟裂或坑槽轧辊下几秒钟就会变成废品。传统基于灰度阈值和形态学算子的视觉检测在强光、水雾和高速运动下很难稳定握住缺陷的边界尤其对“修补裂缝”这种纹理极其杂乱的区域误检率居高不下。而YOLOv8把目标检测做成端到端的回归任务一次前向同时输出目标类别和边界框不需要额外的候选区域生成检测速度能跟上最高速度的轧线节奏这也是它能够成为工业缺陷检测落地首选的原因。这份基于YOLOv8的热轧带钢表面缺陷检测资源包含完整源码、标注好的数据集和保姆级教程覆盖从数据准备、训练调参到推理部署的全流程适合理清原理后想动手复现的工程师也适合需要快速产出原型验证的算法团队。2. YOLOv8的检测原理与热轧带钢数据集的构建2.1 从YOLOv5到YOLOv8结构上改了什么YOLOv8是Ultralytics在2023年发布的目标检测框架它没有沿用YOLOv5的C3模块而是换成了C2f结构。C2f把特征图按通道拆成两部分一部分直接传递另一部分经过多层卷积后再融合这样做最大的收益是让梯度在反向传播时有更短的路径网络深度增加的同时不会出现梯度消失尤其适合热轧带钢这种小缺陷占比高、需要深层语义信息的场景。另一个重要的改动是解耦头。YOLOv8把分类和回归分支完全分开每个分支用独立的卷积层处理而不是像YOLOv5那样在最后共享特征。工业缺陷里“横向裂缝”和“龟裂”外观差异极大解耦头能避免分类和定位任务互相干扰收敛速度更快。Anchor处理上也改成了Anchor-Free不再需要预先聚类与数据强相关的anchor尺寸对于换一个钢种就要重新聚类anchor的产线场景来说省去了一大步。2.2 缺陷数据集的结构与标注格式这份资源里的数据集覆盖八类缺陷横向裂缝、纵向裂缝、块状裂缝、龟裂、坑槽、修补网状裂缝、修补裂缝、修补坑槽。每类缺陷的图像都来自真实热轧带钢表面原始图片是灰度图已转为三通道RGB以匹配YOLO输入。标注使用LabelImg或X-AnyLabeling完成输出为YOLO格式的txt文件。images/ ├── train/ │ ├── 000001.jpg │ └── 000002.jpg labels/ ├── train/ │ ├── 000001.txt │ └── 000002.txt每个txt文件里每一行对应一个真实框格式为“类别id x_center y_center width height”其中中心点坐标和宽高都做了归一化。举个例子一行“3 0.5142 0.3187 0.1568 0.0833”代表类别id为3的缺陷可能是龟裂其中心点在图片的51.42%和31.87%位置宽度占整幅图的15.68%高度占8.33%。做数据质量检查时要格外注意这一点如果框的中心点超过1.0或小于0训练时YOLO会直接跳过该标注导致模型漏学。我一般会写一个小脚本扫描所有txt文件检查坐标是否在0到1之间、宽高是否为正值同时对照原图随机抽几百个框做可视化。这一步看似简单但对训练结果影响极大尤其是“修补网状裂缝”这类目标尺寸小且密集的样本一旦标注出现错位mAP会急剧下降。2.3 数据增强策略不只是翻转和缩放热轧带钢表面有大量重复性纹理如果只用原始图像训练模型很容易把纹理背景当成缺陷。YOLOv8内置了丰富的数据增强但默认参数对工业缺陷并不完全适用。我通常会关闭或限制mosaic的强度因为mosaic把四张图拼在一起会让小缺陷被压缩得看不见。在ultralytics的配置里可以这样调整mosaic: 0.5 mixup: 0.0 hsv_h: 0.015 hsv_s: 0.4 hsv_v: 0.4 degrees: 10.0 translate: 0.1 scale: 0.3 flipud: 0.3 fliplr: 0.5mosaic是四图拼接概率设为0.5让模型一半时间看到完整单图避免小缺陷被过度压缩mixup对工业检测利大于弊直接关掉degrees设10度因为热轧带钢缺陷方向与轧制方向有强相关性翻转过多会让模型学习到错误的方向先验flipud和fliplr保留但概率适中用来增强对上下表面不同拍摄角度的适应性。此外我还会额外加入随机光照扰动和细微高斯噪声模拟产线上水雾和氧化皮造成的反光变化。YOLOv8内置的HSV调整只能在色彩空间层面变化对灰度热轧图像作用有限所以我在训练脚本里用albumentations做了一层离线增强生成一部分亮度、对比度随机变化的图片掺进训练集。这比单纯堆数据量有效得多因为它逼着模型去关注缺陷本身的形状和纹理而不是依赖亮度分布。3. 环境配置与模型训练从零把YOLOv8跑起来3.1 CPU和GPU环境下的安装细节这份资源里给出了完整的requirements清单核心依赖是PyTorch、torchvision和Ultralytics。如果你使用的是NVIDIA显卡建议先确认驱动和CUDA版本一致。以CUDA 11.8为例安装PyTorch时用以下命令pip install torch2.1.0 torchvision0.16.0 --index-url https://download.pytorch.org/whl/cu118 pip install ultralytics8.2.0这里固定了torch和ultralytics版本避免新版本API变动导致训练脚本报错。--index-url指定了CUDA 11.8对应的预编译轮子如果你用CUDA 12.x就把cu118改成cu121。没有独立显卡的机器也不用放弃YOLOv8支持CPU训练只是速度慢很多。CPU环境安装时直接pip install ultralytics即可但注意不要安装GPU版torch否则会报“no kernel image is available”的错误。实际操作时我建议先用一个很小的子集比如每个类别50张图跑通整个流程确认数据集路径、标注格式、配置项都没问题后再用全量数据训练这样能省掉大量排错时间。3.2 数据集配置与模型容量选择Ultralytics使用YAML文件描述数据集路径和类别信息。把下面内容保存为steel_defect.yamlpath: /data/steel_defect train: images/train val: images/val test: images/test nc: 8 names: 0: lateral_crack 1: longitudinal_crack 2: block_crack 3: crazing 4: pit 5: patched_network_crack 6: patched_crack 7: patched_pitpath表示数据集根目录train和val对应相对路径。nc是类别数量必须与names中的键一致。我踩过的一个坑是resources解压后Windows和Linux的路径分隔符不同如果在Windows下训练path必须写绝对路径或正斜杠否则训练直接报Dataset not found。模型选择上热轧带钢缺陷普遍是小目标优先用yolov8s.pt或yolov8m.pt作为预训练权重。n模型速度最快但精度有限龟裂和修补网状裂缝这类纹理型缺陷很容易漏检l和x模型精度高但训练显存需求大推理速度也慢不适合高速产线。我通常先拿s跑一版看各类别AP分布再决定是否升级到m。3.3 训练命令与超参数逐项拆解训练入口很简单但参数组合决定了最终效果。我常用的训练命令如下yolo train \ datasteel_defect.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch16 \ device0 \ optimizerAdamW \ lr00.001 \ lrf0.01 \ weight_decay0.0005 \ warmup_epochs3.0 \ cos_lrTrue \ patience15 \ projectruns/train \ namesteel_exp1imgsz640是训练输入尺寸。热轧带钢的缺陷长宽比差异大如果原始图像是1280x256这种长条图直接缩放到640会让缺陷变得非常小。我一般先把原始图按长边缩放到640然后做随机裁剪到640x640这样既保留分辨率又减少背景干扰。batch16在16GB显存下比较安全显存不够就降到8。epochs100对工业检测数据集来说够用因为通常只有几千张图更久会导致过拟合。optimizerAdamW是推荐配置相比SGD收敛快在噪声较大的标注数据上更稳。学习率lr00.001是AdamW在YOLOv8中的默认值如果你的数据集非常小或类别极不平衡可以降到0.0005。cos_lrTrue让学习率按余弦曲线下降后期微调更精细。patience15表示验证集指标连续15轮不提升就提前停止这是防止过拟合的关键开关。3.4 训练日志与损失曲线怎么看训练过程中控制台会实时输出box_loss、cls_loss、dfl_loss以及准确性指标。很多人只看mAP忽视了box_loss。我习惯同时打开runs/train/steel_exp1/results.csv用pandas画损失曲线import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/train/steel_exp1/results.csv) plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(df[epoch], df[train/box_loss], labeltrain_box) plt.plot(df[epoch], df[val/box_loss], labelval_box) plt.legend() plt.subplot(1, 2, 2) plt.plot(df[epoch], df[metrics/mAP50(B)], labelmAP50) plt.legend() plt.savefig(loss_curve.png)results.csv包含每个epoch的完整指标train/box_loss是训练集回归损失val/box_loss是验证集回归损失。如果训练损失下降但验证损失上升说明过拟合需要增大weight_decay或减少epochs。如果两个损失都不降先检查数据集标注是不是有大量错误再检查学习率是否太大。另外metrics/mAP50(B)如果训练前期一直为0很可能是数据集类别编号和yaml文件对不上训练日志里会打印所有类别名称逐一核对。4. 模型评估、导出与推理部署全流程4.1 用mAP0.5和mAP0.5:0.95衡量性能训练结束后模型会保存在runs/train/steel_exp1/weights/best.pt和last.pt。best.pt是验证集指标最好的权重last.pt是最后一个epoch的权重。评估模型时直接运行验证集yolo val modelruns/train/steel_exp1/weights/best.pt datasteel_defect.yaml输出结果会打印每个类别的精确率、召回率和mAP。对于热轧带钢缺陷检测我更看重mAP0.5而不是mAP0.5:0.95因为产线上的缺陷判定只需要一个大致位置IOU要求没那么严格。但如果你是做精细的缺陷分割或测量缺陷尺寸那mAP0.5:0.95的参考价值更高。不同类别之间差异很大坑槽和横向裂缝通常AP都高龟裂和修补网状裂缝因为纹理复杂、标注边界模糊AP经常只有0.7甚至更低。这时候不要盲目调参数先回到数据集看是不是标注不一致比如不同标注员对龟裂范围的框选习惯完全不同。4.2 导出ONNX并在Python/C中推理产线部署很少直接用PyTorch因为依赖重、推理速度慢。我通常把best.pt导出为ONNX格式再用ONNX Runtime或者TensorRT推理。导出命令yolo export modelruns/train/steel_exp1/weights/best.pt formatonnx imgsz640 dynamicFalse simplifyTruedynamicFalse固定输入尺寸换取更好的优化simplifyTrue用onnx-simplifier去除冗余算子对兼容性有好处。导出的best.onnx可以用下面的Python代码推理import cv2 import numpy as np import onnxruntime as ort img cv2.imread(defect_01.jpg) img cv2.resize(img, (640, 640)) img img[:, :, ::-1].transpose(2, 0, 1) # BGR - RGB, HWC - CHW img np.ascontiguousarray(img, dtypenp.float32) img / 255.0 img np.expand_dims(img, axis0) ort_session ort.InferenceSession(best.onnx) outputs ort_session.run(None, {images: img})[0] # [1, 84, 8400]outputs的形状是[1, 84, 8400]其中84是4个坐标加80个类别概率8400是640x640输入下三个特征层的anchor总数。如果你训练时用的nc8那输出维度就是[1, 12, 8400]12对应48。这一步最容易出错很多人在解析时用错了类别维度导致完全检测不到目标我的做法是先打印模型的输入输出形状再写解算逻辑。C部署时用ONNX Runtime同样方便但要注意内存管理不要每帧重新创建Session。把Session初始化放在类构造函数里推理时只需调用Run方法这样在工业相机30帧/秒的采集下也能稳定跑满。4.3 部署中常见的坑与对策现象可能原因对策GPU推理比CPU还慢模型太小或批量太小GPU利用率不足改用TensorRT FP16或增大batch检测框偏移明显原图resize方式与训练不一致训练时用letterbox推理也要用letterbox龟裂类AP很低标注边界不一致重置标注统一框选规则导出ONNX耗时异常简化过程卡在Transpose算子关闭simplify手动优化图结构产线上漏检小目标输入分辨率过低保持原图长边640以上或使用SAHI切片推理5. 针对小目标和类别不平衡的进阶优化技巧5.1 用SAHI切片推理扳回小目标漏检热轧带钢图像分辨率很高而“坑槽”和“修补裂缝”往往只占几十个像素。把整张大图缩放到640x640后这些小缺陷在特征图上只剩一两个点。最直接的办法是提高imgsz到1280或更长但这会让训练显存和推理时间成倍增长。工程上更实用的是切片推理SAHI把测试图像切成若干patch每个patch独立推理再把结果合并。from sahi.model import Yolov8DetectionModel from sahi.predict import get_sliced_prediction model Yolov8DetectionModel.from_pretrained( model_pathbest.onnx, confidence_threshold0.25, image_size640, ) result get_sliced_prediction( imagebig_picture.jpg, detection_modelmodel, slice_height640, slice_width640, overlap_height_ratio0.2, overlap_width_ratio0.2, )slice_height和slice_width控制切片尺寸overlap_ratio让相邻切片有20%的重叠防止缺陷正好被切在边缘。合并时SAHI会做NMS去重只保留置信度最高的框。我实测过对修补网状裂缝这类细小纹理切片推理比整图检测的召回率能提高15%以上代价是单张图推理时间从15毫秒变成120毫秒左右在冷床判级环节这个速度可以接受。5.2 用类别权重和WBF融合应对不平衡数据八类缺陷在产线上出现频率差别很大坑槽几乎每卷钢都有修补类的缺陷很少见。如果直接用原始数据训练模型对少数类会产生很强的偏见。除了常规的欠采样/过采样我在YOLOv8里会手动修改损失函数里的类别权重。在训练脚本中继承默认Loss类class WeightedLoss(torch.nn.Module): def __init__(self, model, class_weights): super().__init__() self.model model self.class_weights torch.tensor(class_weights).float().cuda() def forward(self, batch, preds): loss, loss_items self.model.loss(batch, preds) cls_loss loss_items[1] # cls_loss weighted_cls (self.class_weights * cls_loss).mean() # 将加权后的分类损失替换回总损失 loss loss - loss_items[1] weighted_cls return lossclass_weights可以通过统计训练集中每个类别的样本数量按逆频率计算得到让少数类的分类损失在反向传播时获得更大的梯度。注意这种方法只调整分类损失回归损失不受影响不然会破坏框的定位精度。另一个技巧是WBF加权框融合把用不同输入尺寸640和960产生的两组预测框做加权平均减少单次预测的抖动。在验证集上看WBF能让mAP提升1到2个点且不需要重新训练。5.3 把模型嵌入产线前需要做的验证模型训练好、精度也达标后不要急着交出去。找一段没参与训练的高级取片视频按帧跑一遍统计连续多帧检测结果的稳定性。热轧现场有大量粉尘和振动单帧检测很容易出现偶尔漏检这时要加一个简单的时序滤波器如果缺陷在连续3帧中至少出现2次才判定为真实缺陷。这个逻辑用普通队列就能实现但能显著降低误报率。另外把模型部署到实际机器上时记得用TensorRT或OpenVINO做量化加速输入尺寸固定为640不要随意修改否则精度损失会超出你的预期。本文还有配套的精品资源点击获取