简介一套基于YOLO的实时物体检测工程面向计算机视觉开发者与工业质检场景围绕齿条、螺栓、螺母和裂缝检测等常见工业目标提供了从网络搭建到推理实现的完整代码。压缩包内共有2000个文件其中1903个txt多用于存放数据标注或配置信息49个c源文件和46个h头文件覆盖了数据加载、图像处理、网络构建与检测层等关键模块另有cpp与md文档辅助说明整个包大小约199.17MB。目前已有67人学习下载对于想快速理解YOLO原理或开展工业检测项目的人来说是一份实用的参考资源。资源内容包含YOLO网格划分、边界框回归、置信度计算、多尺度检测等核心实现并配有说明文档读者可以对照源码研究训练策略与推理流程也能直接迁移到类似的目标检测任务中。整体结构清晰文件分类明确适合作为二次开发的基础。1. 从“能检测”到“敢上线”YOLO 做齿条、螺栓、螺母与裂纹检测先想清楚这几件事这个标题看上去更像一个工业视觉项目的数据集命名yolo实时物体检测_齿条、螺栓、螺母_yolo real-time object detection_crack, b。拆开看任务很直白——用 YOLO 在实时画面里同时检测齿条、螺栓、螺母这三类机械零件并且把零件表面的裂纹crack也框出来。这类需求在装配防错和质检工位很常见但别以为有预训练模型就能直接跑齿条和螺栓外形接近螺母尺寸小裂纹更是典型的小目标背景里一点油污和阴影都能让误检率爆表。真正决定项目能不能上线的是数据标注、切图策略和置信度门限怎么设。这篇文章按我实际做质检项目的顺序把数据准备、YOLOv8 训练、实时推理、边缘部署和踩坑记录完整讲一遍适合拿 YOLO 做工业缺陷检测或装配防错的工程师照着复现。2. 数据准备与标注小目标裂纹和螺母样本决定模型上限的 70%很多人拿到标注好的数据集就直接yolo train等模型反复漏检才开始怀疑网络结构。实际项目中齿条、螺栓、螺母和裂纹的检测难点几乎全在数据侧裂纹在整张图里可能只有十几个像素螺母和螺栓的六角头在灰度图里长得差不多现场光照一变模型就乱。这一章先把数据关过掉。2.1 采集与切图别让裂纹在 imgsz640 里只剩 5 个像素工业相机往往直接输出 4000x3000 甚至更高分辨率的原图。如果整张图缩到 640x640 再送进 YOLO一条真实宽度 30 像素的裂纹会变成不到 5 个像素无论什么模型都学不到细节。所以采集后的第一件事不是标注而是切图。常见做法是把原图切成 640x640 的块相邻块保留一定重叠避免目标刚好卡在切图边界上被截断。切图脚本我一般这样写import cv2 from pathlib import Path src_dir Path(raw_images) out_dir Path(crops) out_dir.mkdir(exist_okTrue) CROP_SIZE 640 # 和训练 imgsz 保持一致 OVERLAP 64 # 重叠像素防止裂纹被切碎 for img_path in src_dir.glob(*.jpg): img cv2.imread(str(img_path)) h, w img.shape[:2] step CROP_SIZE - OVERLAP for y in range(0, h - CROP_SIZE 1, step): for x in range(0, w - CROP_SIZE 1, step): crop img[y:y CROP_SIZE, x:x CROP_SIZE] name f{img_path.stem}_x{x}_y{y}.jpg cv2.imwrite(str(out_dir / name), crop)切图参数有三个值得说明。CROP_SIZE必须和训练尺寸一致这样标注框在归一化时不会跨尺度OVERLAP建议取 32~64重叠太小裂纹或螺栓头部容易被切成两半重叠太大又会让同一目标出现在过多训练图里变相降低数据多样性。切完后建议顺手删掉那些完全没有标注目标的空白块否则大量空白图会让模型把背景学得太深推理时一看到相似背景就乱报。如果你切完发现裂纹平均宽度还是小于 10 像素不要急着训练。要么把相机离近一点重新采集要么采用多尺度切图把原图分别切成 640 和 416 两份小尺寸图负责让模型看到更大范围的齿条轮廓大尺寸图负责保留裂纹细节。这个方法比对整图做超分辨率更实在。2.2 用 LabelImg 标出齿条、螺栓、螺母与 crack类别设定与边界框规范标注工具我习惯用 LabelImg保存成 YOLO 格式每张图对应一个 txt 文件每行是class x_center y_center width height坐标统一归一化到 0~1。类别建议直接用英文命名避免后续推理脚本里中文路径出问题names: 0: rack 1: bolt 2: nut 3: crack这里有个容易犯错的地方齿条是长条形零件螺栓也是长条形很多标注员会把螺栓头部和螺杆一起框齿条恨不得一整个框完。结果就是 rack 和 bolt 的宽高比高度重合模型分不清。我的标注规范是——螺栓只框六角头不框螺杆齿条标完整轮廓但不要把背景阴影包进来裂纹必须有明确的断裂纹理才允许标背景划痕和油渍一律不标。标完之后检查一下小目标比例。写个简单脚本统计每个标注框的像素尺寸from pathlib import Path labels_dir Path(labels) IMG_SIZE 640 for label_file in labels_dir.glob(*.txt): with open(label_file) as f: for line in f: cls, xc, yc, bw, bh map(float, line.split()) bw_px bw * IMG_SIZE bh_px bh * IMG_SIZE if bw_px 10 or bh_px 10: print(f{label_file.name}: class {int(cls)} box size {bw_px:.1f}x{bh_px:.1f}px)如果打印出大量box size 10px说明切图粒度不够裂纹和螺母在 640 的图上太小。YOLO 对小目标并非完全无能为力但 10 像素以下的框即使能检测到定位精度也会很差NMS 阶段很容易被误滤掉。所以这个统计结果就是切图策略是否要调整的依据。2.3 用 YOLOv8 训练自己的数据集Anaconda 环境配置与损失函数观察点数据准备好后先搭训练环境。YOLOv8 对 Anaconda 环境配置要求不高关键是把 Python 版本和 PyTorch 版本对上避免后面导出 ONNX 时算子报错。我的习惯是单独建一个环境不让它污染其它项目conda create -n yolo python3.10 -y conda activate yolo pip install ultralytics opencv-python如果你的电脑是 NVIDIA 显卡先确认 CUDA 驱动能用再装对应版本的 PyTorch。装完后python -c import torch; print(torch.cuda.is_available())必须返回 True否则训练速度会慢到让人怀疑人生。数据集目录按 YOLO 的约定组织datasets/parts/ images/train/ images/val/ labels/train/ labels/val/ data.yamldata.yaml 内容如下path: datasets/parts train: images/train val: images/val nc: 4 names: [rack, bolt, nut, crack]然后启动训练yolo detect train datadata.yaml modelyolov8n.pt epochs150 imgsz640 batch16 close_mosaic15这里close_mosaic15很多新手会忽略。YOLOv8 默认训练过程会开 mosaic 数据增强把四张图拼成一张。对齿条、螺栓这类大尺寸目标是好事但对裂纹这种小目标mosaic 拼图会让裂纹在最终图里占的像素比例更小模型学不到细节。所以最后 15 个 epoch 把 mosaic 关掉让模型回归真实的图片分布。训练过程中看 results.png 里的 box_loss、cls_loss、dfl_loss。裂纹检测的 box_loss 通常下降得比通用场景慢因为小目标框的回归更难这是正常的。真正需要警惕的是 cls_loss 反复震荡后面避坑清单详细说。3. 训练参数与置信度门限让 YOLO 在“多检”和“漏检”之间找到平衡模型训练好只是第一步部署到现场后你会发现同一套权重在不同的置信度门限下表现完全不一样。门限调高了漏检调低了误检这是实时检测最磨人的阶段。3.1 模型选型YOLOv8n 还是 YOLOv8s先按部署硬件决定YOLOv8 官方提供了 n、s、m、l、x 等尺度工业场景我基本只用 n 和 s。YOLOv8n 参数量最小在 Jetson Nano、RK3588 这类边缘设备上能跑到实时适合螺母和螺栓这种轮廓清晰的目标YOLOv8s 精度更高对裂纹这类低对比度小目标更友好但需要工控机有独立显卡否则推理帧率上不去。模型体积/计算量适合部署环境裂纹检测表现YOLOv8n最小适合边缘盒子Jetson Nano / RK3588能检细裂纹容易漏YOLOv8s中等适合普通工控机桌面级 GPU裂纹和螺母精度都更好YOLOv8m较大训练慢高性能工控机精度提升有限不建议我一般先用 YOLOv8n 跑通整个流程确认标注和数据没问题后再换成 YOLOv8s 看 mAP 提升幅度。不要一开始上 m 或 l工业现场对延迟敏感模型太大会让后续 TensorRT 转换和调优都很被动。3.2 必调参数imgsz、batch、epochs、mosaic 与 close_mosaic训练参数里imgsz 是最值得花时间的。通用目标检测模板写 640我们直接拿来用可能裂纹只有几个像素。如果显存允许把 imgsz 提到 800 或 960裂纹检测的召回率会有肉眼可见的提升。相应的 batch 要降下来否则 24GB 显存都扛不住。我常用的一组起手参数yolo detect train \ datadata.yaml \ modelyolov8s.pt \ epochs200 \ imgsz800 \ batch8 \ lr00.005 \ close_mosaic20 \ patience30epochs 设 200 但配合patience30连续 30 轮没提升就自动停省得死等。lr00.005比默认的 0.01 略低因为工业数据量通常只有几百到几千张学习率太高容易震荡。如果训练到一半 loss 稳住了可以手动调低 lr。还有一个容易忽视的点如果你用的预训练权重是 COCO 的 yolov8s.pt它学到的“密集物体”特征和你们产线的工件完全无关。这不是坏事迁移学习能加速收敛但前几个 epoch 的损失下降会显得很猛别高兴太早要看 50 轮之后是否还在合理下降。3.3 置信度门限和 NMS IoU实时检测误检率的两个总开关推理时有两个参数直接决定现场效果conf和iou。conf是置信度门限小于这个值的检测结果会被丢弃iou是 NMS 阶段判断两个框是否重叠的阈值。在测试图片上调参工具链已经很成熟from ultralytics import YOLO model YOLO(runs/detect/train/weights/best.pt) results model.predict( sourcetest.jpg, conf0.4, iou0.5, imgsz800, ) for r in results: boxes r.boxes for box in boxes: cls int(box.cls.item()) conf box.conf.item() print(fclass {cls}, confidence {conf:.2f})如果现场误检多把conf往上调比如 0.5 或 0.6。但要注意裂纹的置信度天然低于螺栓和螺母因为它的纹理变量太大一条轻微裂纹的置信度可能只有 0.35。这时候盲目调高 conf 会把最需要检出来的缺陷全滤掉。我的做法是分场景区分对待如果这个工位只负责装配防错只关心有没有螺栓和螺母conf 调到 0.5 没问题如果同时承担裂纹质检conf 先放到 0.3再用 NMS IoU 把重叠框压下来。iou一般保持 0.5改低会让相近目标输出多个框改高又会把螺母和螺栓的框合并成一个导致漏检。4. 实时推理与边缘部署把模型跑到摄像头和 RTSP 流上训练完只是实验室阶段真正考验人的是把模型接到产线摄像头的 RTSP 流上在持续输入、光照变化、帧率波动的环境里稳定运行。4.1 用 OpenCV 接视频流按帧推理并绘制检测框最常见的部署形态是一台工控机通过网口接工业相机或海康/大华的 RTSP 流。OpenCV 的 VideoCapture 可以直接拉流配合 YOLO 推理并绘制结果import cv2 from ultralytics import YOLO model YOLO(best.pt) cap cv2.VideoCapture(rtsp://192.168.1.64:554/stream1) cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) frame_id 0 while True: ret, frame cap.read() if not ret: print(Failed to read frame) break # 每两帧推理一次留出时间给后续处理 if frame_id % 2 0: results model.predict(frame, conf0.4, iou0.5, verboseFalse) annotated results[0].plot() cv2.imshow(parts detect, annotated) frame_id 1 if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这个脚本里有几个现场参数要留意。CAP_PROP_BUFFERSIZE设为 1 很关键如果不设网络流会把解码失败的帧缓存下来推理线程跟不上时延迟会越来越大最后画面比实际晚好几秒这是高速运动工件的大忌。跳帧也是常见做法如果模型推理要 30ms相机是 25fps理论上能跑满但加上绘制和显示通常每 2~3 帧取一帧更稳定。4.2 边缘设备Jetson/RK3588上的精度——速度权衡很多产线工位没有独立显卡边缘设备是主流。在 Jetson 或 RK3588 上跑 YOLOv8第一原则是别直接用 Python 加载 PyTorch 权重太慢了。第二原则是接受精度衰减。我一般会先在电脑上训练导出 ONNX再在设备上用 TensorRT 或 RKNN 转换。YOLOv8n 在 Jetson Nano 上用 FP16 推理640x640 输入大约能跑到 25ms 一帧刚好够实时如果还想更快把 imgsz 降到 480速度能到 15ms但裂纹召回率下降明显。这里有个取舍技巧边缘设备上跑两个模型一个大的负责检测螺栓螺母一个小的专门负责裂纹。裂纹检测模型的输入用 800即使它只能跑 5fps配合触发式拍照去检也够用。而实时视频流用 640 尺寸跑整体检测。很多工业质检项目都是这样“实时检测 定格复检”的组合。4.3 导出 ONNX 并用 TensorRT 加速推理速度从 30ms 降到 8ms把 PyTorch 权重导出成 ONNX再用 TensorRT 转换成 engine是加速收益最大的一步。导出很简单model.export(formatonnx, imgsz800, halfTrue, dynamicFalse)halfTrue表示半精度 FP16在边缘设备上能带来接近翻倍的速度提升但对裂纹这种低对比度目标可能会有轻微的精度损失。如果导出后在设备上测试裂纹开始漏检就改成halfFalse速度和精度的取舍需要实测。得到best.onnx后在设备上用 TensorRT 的trtexec工具转换trtexec --onnxbest.onnx --saveEnginebest.engine --fp16如果用的是 RK3588对应工具是 rknn-toolkit2转换流程类似但要注意 ONNX 里的部分算子可能需要重写。转换完的 engine 只在本设备上有效换一台设备要重新跑一次转换这是第一次接触的人最容易踩的坑——把 A 机器转好的 engine 拷到 B 机器直接加载失败。推理脚本里加载 engine 时不再需要 YOLO 的 Python 封装直接用 TensorRT 或 onnxruntime 执行后处理阶段自己解码。这一步能显著降低 CPU 开销也让整个推理管线更可控。5. 避坑清单小裂纹、类别不平衡、光线干扰与误检高的排查记录这几条是我在不同产线上反复遇到的真实问题每一条都按“现象 - 原因 - 解决”写可以直接对照排查。5.1 裂纹总被漏检训练精度却不低现象val 集上 mAP 有 0.85但产线实测时细裂纹经常完全没框或者框的位置偏了一半。原因val 集里的裂纹图片和训练集来自同一批次采集背景光线一致现场真实裂纹更浅、纹路更细。另外训练时 imgsz 用 640裂纹在图上可能只有 8x30 像素模型根本没学到稳定的纹理特征。解决训练尺寸提到 800 甚至 960采集阶段把相机架到实际高度把最细的缺陷样件拍进去推理时把 conf 调低到 0.25看看是不是被门限滤掉了。如果还漏就要回数据侧用重叠切图重做。5.2 螺栓被误检成螺母齿条被误检成裂纹现象画面上螺栓头部被框成 nut齿条的边缘阴影频繁触发 crack 报警。原因标注不规范是首位。很多标注员把螺栓的六角头外接框标得特别大和螺母的框高度重合齿条的齿谷边缘在低角度光照下有深色阴影形状和裂纹很像。模型学的不是“裂纹”而是“深色细条”。解决统一标注规则螺栓只标六角头螺母标完整外轮廓两者在尺寸上本来就有差别靠数据让模型分开。裂纹标注必须要求“断裂纹理”——不能只标阴影。另外找一些没有裂纹但齿条带阴影的图放进训练集当负样本模型就知道阴影不是裂纹了。5.3 边缘部署后误检率飙升和本地测试完全不是一回事现象在台式机测试一切正常部署到 Jetson 后同一画面开始频繁误检有时一张图出十几个框。原因最常见是 FP16 精度导致低置信度框增多其次是摄像头自动曝光和本地测试图片的光照不一致最后是 TensorRT 的 engine 用了动态输入尺寸推理时输入分辨率变了后处理没跟上。解决先关掉 FP16 用 FP32 试如果误检减少确定是精度问题那就用更大输入尺寸或换 YOLOv8s 拉高置信度分布。摄像头手动固定曝光参数不要开自动增益。后处理里对conf 0.1的框统一做二次过滤不要直接相信模型输出。5.4 训练时 loss 降到一半就不动了cls_loss 反复横跳现象前 50 个 epoch 训练顺利之后 box_loss 不再下降cls_loss 时高时低整个训练像在振荡。原因最常见是类别不平衡——裂纹样本只有几十张螺母样本有几百张模型更新方向被大类别主导另外学习率太高后期收敛不下来。解决对裂纹类别做简单过采样把裂纹图片复制 2~3 份到 train 目录让它在每个 epoch 里被看到足够多次同时把 lr0 调低到 0.003。看 losses 曲线时别只看最后一行平均值要看 per-class 的 cls_loss。如果裂纹那一类的 loss 一直不下去再回头检查标注看是不是很多裂纹框宽度只有 5 像素导致回归信噪比太低。5.5 数据集小模型过拟合val mAP 高但现场一塌糊涂现象总样本数只有 400 张val 集 mAP 0.92上线后换了工位就失灵。原因模型记住了那 400 张的背景纹理换成另一条产线、另一台相机光线和背景一变泛化能力直接崩。工业相机换一个角度画面分布差异比想象大得多。解决先增加数据增强把hsv_h、hsv_s、rotation打开但旋转角度不要超过 15 度否则螺栓和螺母的方向性特征会被破坏。更有效的是换产线采集不同背景的坏样本加进训练集里。最后如果数据量实在上不去砍掉一些自定义类别把任务简化成“有缺陷 / 无缺陷”二分类把精力集中在裂纹上更现实。6. 上线前的验证方法用 mAP、混淆矩阵和“坏样本集”给模型体检训练完成后不要急着全量布到生产环境先用几个最少必要的手段给模型做一次体检。6.1 看 PR 曲线和混淆矩阵而不是只看总 mAPYOLOv8 训练目录下会自动生成PR_curve.png和confusion_matrix.png。我通常先看混淆矩阵里 crack 那一行如果有很多 crack 被预测成 bolt 或 nut说明缺陷和目标类别在视觉上混淆了。再看 PR 曲线在召回率 0.8 附近对应的精确率这个点才是现场实际工作点。6.2 攒一沓“坏样本”把置信度门限调到不会乱叫为止从现场录 200 张不重复的图片专门选带油污、阴影、运动模糊的。把模型跑一遍看排在前面的误检框是什么然后手动调 conf 门限。这个坏样本集比 val 集有价值得多因为它是真实产线环境。调到所有坏样本里不再出现置信度超过门限的误检才算合格。6.3 给现场留人工复核通道把检测结果叠加到原图并缓存最后在推理脚本里加一行把标注结果保存到审核目录方便质检员抽查audit_dir audit frame_file f{audit_dir}/{frame_id:06d}.jpg cv2.imwrite(frame_file, annotated)这个习惯让我少踩了很多雷现场说“误检”的时候可以直接翻原图和框的位置快速定位是模型问题还是相机角度问题。我习惯每上一个新产线都重新跑一遍坏样本集宁可多花一个月迭代数据也不愿上线后半夜接到电话。希望帮到你。本文还有配套的精品资源点击获取
