172张图也能训练YOLO?工业车间人员检测小样本实操指南
简介目标检测作为计算机视觉的核心任务其原理是通过卷积神经网络提取图像特征定位并分类目标对象。在工业智能化和安全生产需求推动下人员检测成为车间管理的第一道基础能力但真实场景中常面临样本量不足的困境。小样本数据集并不等于项目不可行借助迁移学习、数据增强与合理的训练策略即使只有百余张标注图片也能训练出可用的YOLO模型。本文从目标检测基础原理出发解析小样本场景下的技术价值与工程落地路径重点介绍YOLO版本选型、预训练权重利用、在线增强参数调整以及过拟合规避方法并延伸至推理部署与业务扩展为产线监控、安全巡检等工业应用提供一套可复现的完整方案。 做工业视觉这几年YOLO几乎是我处理车间视频流的默认起点。前两天整理素材时翻到一个“172张图片、标注类别为person”的车间人员目标检测数据集正好有朋友问我这种小样本数据集到底能不能拿来训练YOLO能不能落地。这算是目标检测项目里最典型的场景之一数据少、场景杂、还要快速验证算法效果。这篇博文就基于这个项目标题把工业车间人员检测这个任务从数据理解、算法选型到训练部署完整过一遍特别是针对小数据集该怎么避坑、怎么把效果撑起来都会给出可复现的实操方案。如果你手里正攥着类似规模的数据集或者打算在产线监控、安全巡检场景里做人员检测这篇文章应该能帮你少走不少弯路。1. 工业车间人员检测的任务拆解与数据集定位1.1 车间场景下的检测难点与业务价值在工业车间里做人员目标检测和平时在街景、公开数据集里做人检测完全是两码事。车间环境有几个很棘手的特征光照条件复杂有的工位强光直射有的区域光线昏暗背景里全是设备、货架、传送带纹理极其丰富非常容易造成误检工人着装通常统一且颜色和安全帽、设备涂装容易相近还有大量遮挡场景人站在机器后面、弯腰操作时身体只有一部分暴露在画面里。但业务需求却非常明确。人员检测是车间安全管理的基础能力往下走可以接安全帽佩戴识别、区域闯入告警、人员计数、在岗状态判断。不管是做合规巡检还是产线效率分析第一步都是先把“人”的位置从视频帧里找出来。这也是为什么很多项目起步阶段都会先拿一个只有person类别的检测数据集来做算法验证——先把基础检测能力跑通再逐步扩展业务类别。这个数据集的定位其实很清晰它不追求覆盖所有复杂场景而是聚焦车间的真实拍摄画面用172张标注好的图片提供一份可以直接喂给YOLO训练的干净数据。对于要做原型验证、算法选型测试、或者跑通整套训练流程的开发者来说这个规模完全够用。1.2 172张在深度学习项目中算什么量级直说172张图片在目标检测领域属于典型的极小样本。拿COCO数据集做参考train2017有11.8万张图片、80个类别相比之下172张连零头都不到。但这不代表这个数据集没有价值关键在于你怎么用它。小数据集真正的威胁是过拟合模型很容易把训练集里的背景、光照、姿态“背”下来而不是学到“人”的通用特征。如果直接从头训练一个YOLO模型大概率会得到一份loss曲线很漂亮、验证集上却一塌糊涂的结果。但实际工程里我们很少会从零训练。工业项目通常都有预训练权重可以迁移而YOLO在COCO上的预训练模型本身就见过大量person类别的样本这相当于帮你把“什么是人”这件事已经学好了你需要做的只是让它适配车间场景。在这个前提下172张图片承载的任务不是让模型学会认人而是让模型在车间场景里准确找到人。这个区别非常关键决定了后续所有训练策略的走向。数据划分上我建议按8:1:1或9:1来切分训练集和验证集。172张的话我不建议再单独切测试集因为样本太少测试集的评估结果方差会很大。把验证集留15张左右用于观察训练过程中的mAP变化就够了。如果后面需要更严谨的评估再用独立的车间视频抽帧来补。2. YOLO算法选型版本怎么挑、预训练权重怎么用2.1 YOLO家族各版本核心差异与选择建议YOLO发展到现在v5、v6、v8、v9、v10、v11这么多版本新手容易看花眼。但其实从工程落地角度选型逻辑非常直接看生态成熟度、预训练权重丰富度、部署难易度而不是追新。版本核心特点小样本场景适配性部署友好度YOLOv5生态最成熟文档齐全Ultralytics维护高v5s参数量小容易收敛极高TensorRT/ONNX支持完善YOLOv6美团开源工业部署优化较多中需要自行适配训练流程高YOLOv8当前主流anchor-freeAPI统一高ultralytics包一键训练极高YOLOv10无NMS设计推理更快中新特性文档相对少中高YOLOv11最新版分类/检测/分割统一框架高但部分功能仍在迭代高针对172张这种规模的数据集我推荐用YOLOv5s或YOLOv8s。原因有三第一s版本参数量在7M到11M之间在小数据上不容易过拟合训练速度也快第二两个版本都有稳定的COCO预训练权重person类在COCO里是第0类迁移基础非常好第三在线增强策略成熟mosaic、mixup这些增强手段在训练后期会自动关闭减少过拟合风险。我个人实测下来YOLOv8s在工业场景的小样本任务上表现比较稳ultralytics提供的训练接口也省心适合把主要精力放在数据处理和调参上。2.2 小数据集为什么必须用迁移学习这个点值得展开讲。很多人拿小数据集训练第一反应是“数据不够那就改模型结构、加数据增强”但最有效的手段其实是迁移学习。我们看一下在COCO上预训练的YOLO模型到底学到了什么。COCO数据集里有大量person类别标注模型的主干网络已经学会了提取人的边缘、轮廓、部件特征检测头也学会了输出人的边界框。你把它拿到车间场景要做的事情不是重新教它认人而是做一次“领域适配”让模型理解车间里的光照、背景、摄像头视角下的人是什么样子。实际训练时有几个具体做法。第一个做法是直接加载预训练权重比如yolov8s.pt然后正常训练全部层。172张数据下学习率要调低一些建议初始学习率在0.001以下避免在迁移基础上大幅破坏已学到的特征。第二个做法是冻结骨干网络只训练检测头等loss下降平稳后再解冻骨干网络微调。冻结骨干的好处是可以防止小数据训练时骨干特征被破坏缺点是如果车间场景和COCO差异较大最终精度可能不够。我的建议是先用方案一加载完整预训练权重设一个较低的学习率跑50到100轮观察验证集mAP。如果出现过拟合或特征漂移再切换到冻结骨干的方案对比。3. 数据集格式、标注细节与训练全流程实操3.1 YOLO格式数据集的目录结构与标签含义拿到数据集后第一步是核对目录结构。标准YOLO检测数据集的格式如下dataset/ ├── images/ │ ├── train/ │ ├── val/ ├── labels/ │ ├── train/ │ ├── val/ ├── data.yamlimages里放原始图片labels里放对应的txt标注文件文件名字必须和图片名字完全一致仅扩展名不同。如果数据集本身把train和val分好了直接用如果没有分那就自己按比例切分注意切分时用random seed固定随机种子保证可复现。每一张图片对应的labels txt文件内容大致是0 0.5432 0.4156 0.3214 0.6542 0 0.1024 0.7834 0.1987 0.3521每行一个目标共5个数含义是类别ID、目标中心点x坐标、目标中心点y坐标、目标宽度w、目标高度h。这里的x、y、w、h都是相对于图片宽度和高度的归一化值范围在0到1之间。这行内容对应的就是YOLO标注格式的核心定义。data.yaml配置文件长这样train: dataset/images/train val: dataset/images/val nc: 1 names: [person]这个文件告诉训练脚本去哪里找训练数据和验证数据、类别数量是多少、每个类别叫什么名字。3.2 训练实操从环境准备到模型输出的完整步骤这里我以YOLOv8为例把完整训练流程走一遍这些命令直接复制就能用。先准备环境建议用Python 3.9或3.10GPU显存至少6G如果只有CPU也能训练但速度会慢很多pip install ultralytics # 如果要ONNX导出需要额外安装 pip install onnxruntime验证一下环境是否正常yolo predict modelyolov8s.pt sourcehttps://ultralytics.com/images/bus.jpg能输出检测结果说明环境没问题。接下来把数据集放到项目目录下确认好目录结构和data.yaml路径一致。启动训练yolo detect train datadataset/data.yaml modelyolov8s.pt epochs100 batch8 imgsz640 lr00.0005 patience15几个关键参数的取舍我得重点说一下。epochs设100是一个比较保守的起步值。172张图batch8的话一个epoch大约21个step100个epoch也就是2100个step这个训练量配合预训练权重是合理的。如果想更快验证效果可以先跑30个epoch看趋势。batch-size在显存允许范围内尽量调大。batch8对应大约8-10G显存如果显存不够就调小到4。学习率lr00.0005是基于迁移学习场景的设置比起默认的0.01要低很多目的是在已有权重上做细调而不是大改。patience15是early stopping的容忍轮数验证集mAP连续15个epoch没有提升就自动停止能有效防止过拟合。训练结束后会在runs/detect/train目录下生成一堆文件best.pt是验证集mAP最高的权重last.pt是最后一轮的权重results.png是训练曲线图confusion_matrix.png是混淆矩阵val_batch*.jpg是验证集上的预测可视化结果。评估指标主要看三个mAP50IoU阈值0.5下的平均精度、mAP50:95从0.5到0.95取不同IoU阈值的平均更严格、precision和recall。在小数据集场景下mAP50是更有参考价值的指标因为它不要求框特别精确更关注能不能检出而mAP50:95对框的位置精度要求高在样本少时波动会很大。3.3 数据增强实测172张怎么撑起一个能用的训练集YOLO自带的在线数据增强在小样本任务中作用巨大但很多人只是开着默认参数并不知道每个增强选项对结果的影响有多大。我在实验里专门对比过几组增强策略。默认开启的mosaic增强是把4张图片拼成一张再训练这相当于强制模型在更丰富的上下文里学习目标特征对场景多样性的提升很有帮助。但在训练的后期如果一直开mosaic反而可能影响模型对真实场景的适应能力所以ultralytics默认在最后10个epoch自动关闭mosaic这个设计已经帮你考虑到了。另一个关键增强是HSV色彩空间扰动包括色调、饱和度、亮度三个维度。车间不同区域的光照差异很大这个增强能模拟不同曝光条件下的画面让模型对光线变化更鲁棒。我通常会把hsv_s和hsv_v适当调高一点yolo detect train datadataset/data.yaml modelyolov8s.pt epochs100 batch8 imgsz640 lr00.0005 hsv_s0.7 hsv_v0.6除了在线增强还可以从数据侧做离线增强。比如把图片做水平翻转、90度旋转、小幅缩放和裁剪生成辅助训练样本。这样操作的前提是标注坐标会跟着变换手动做容易出错建议直接用ultralytics或Roboflow这类工具的增强功能别自己写脚本改坐标。数据增强的本质是给模型提供更多“看起来不同、但语义一致”的样本。在172张这个基数上增强后相当于把有效训练数据扩大到5到10倍配合预训练权重效果提升会非常明显。4. 车间场景下的常见问题与排查实录4.1 小数据集过拟合的典型表现与对策我拿小数据集训练YOLO时最常遇到的问题就是过拟合。怎么判断过拟合看训练曲线如果train loss持续下降、val loss降到某个点后开始反弹同时val mAP不再上升甚至下降那基本就是过拟合了。在172张数据上过拟合几乎一定会出现区别只是来得早还是晚。有几种手段可以缓解。第一种是降低训练轮数并配合early stopping。我之前跑过一个实验50轮时验证集mAP50到0.91继续跑到100轮反而跌到0.87这就是典型的过拟合。所以训练时一定要盯着best.pt而不是last.ptbest.pt就是早停机制帮你选出来的最优权重。第二种是增加数据增强强度。除了前面说的HSV扰动还可以开启flipud上下翻转、scale缩放、translate平移。但注意车间场景里人一般是直立站着的上下翻转虽然能增加数据量但会让模型学到“倒立的人”这种错误模式所以flipud建议关闭fliplr水平翻转可以开。第三种是降低模型复杂度。如果yolov8s还是过拟合严重可以换yolov8n参数更少虽然基准精度略低但在小数据上可能反而效果更好。这个思路很多人想不到但实测有效。4.2 漏检与误检工业车间的特有难点用172张训练出来的模型放到车间真实视频流里跑最容易出现两类问题漏检和误检。漏检主要集中在几个场景工人背对摄像头且穿深色工作服时人物和背景对比度太低人在设备后面只露出半个身体时检测框置信度偏低光线强烈反光的地面上出现倒影时模型有时会把倒影当成真实目标导致误检。针对这些情况我的处理顺序是先在测试视频上跑一遍推理把置信度阈值从默认的0.25调到0.1看那些漏检的目标是否只是置信度低、但检测框位置其实是对的。如果确实是这样说明模型是学到了特征的只是不够自信那可以通过补充类似难例的数据来提升。如果调到0.1仍然检不出来说明模型完全没有学到这个模式的“人”需要对这类场景单独抽帧补充标注。误检则多半是模型把某些设备纹理、人形立牌、墙上的安全标识当成了人。查这个问题时把推理结果可视化出来逐张看误检目标的置信度分布。如果置信度普遍偏低调高置信度阈值到0.35就能解决如果置信度高说明模型真的被某些视觉模式骗了需要找一些这类负样本图片加入训练集但注意负样本不需要标注让模型看到这些图里没有人即可。4.3 数据标注常见错误与清理方法数据质量决定了模型上限这是我在项目里反复验证的一句话。拿到数据集后第一步不要急着训练先做一个数据质量体检。最常踩的坑有三个。第一个坑是标注坐标越界。yolo格式要求坐标归一化到0到1之间但有些标注工具导出时可能产生大于1或小于0的值训练时会导致loss异常甚至报错。可以用下面这段代码快速检查import os label_dir dataset/labels/train for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue path os.path.join(label_dir, fname) with open(path) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(f{fname}: 字段数错误 - {line}) continue cls, x, y, w, h parts x, y, w, h float(x), float(y), float(w), float(h) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): print(f{fname}: 坐标越界 - {line}) print(检查完成)第二个坑是标注框不贴合目标。尤其是目标较小的工人标注框经常偏大或者偏小。标签框偏大会给模型传递错误的目标范围信息导致预测框总是或大或小。检查方法是把标注框画到图片上肉眼扫一遍。用ultralytics提供的可视化脚本yolo detect val datadataset/data.yaml modeldataset/runs/detect/train/best.pt会输出带预测框的可视化图片但要看标注框本身可以用opencv自己画一遍我用下面这版脚本比较多import cv2 import os img_dir dataset/images/train label_dir dataset/labels/train for fname in os.listdir(img_dir): img_path os.path.join(img_dir, fname) label_path os.path.join(label_dir, fname.rsplit(., 1)[0] .txt) img cv2.imread(img_path) h, w img.shape[:2] if not os.path.exists(label_path): continue with open(label_path) as f: for line in f: cls, x, y, bw, bh line.strip().split() x, y, bw, bh map(float, (x, y, bw, bh)) x1 int((x - bw / 2) * w) y1 int((y - bh / 2) * h) x2 int((x bw / 2) * w) y2 int((y bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imwrite(check_ fname, img)第三个坑是类别命名不统一。有些数据集里同一类目标可能在不同图片里被标成person、people、worker、man虽然语义一致但YOLO会把它们当成不同类别。所以拿到数据后一定要检查labels目录下所有txt文件里的类别ID是否只有0data.yaml中的nc是否为1。这个检查很简单但往往决定训练是否顺利。5. 模型部署与业务落地扩展5.1 推理脚本用训练好的权重做车间在线检测训练的目标是落地。把这个训练好的best.pt接到实时视频流或者图片上用ultralytics API非常直接from ultralytics import YOLO model YOLO(runs/detect/train/best.pt) results model.predict( source车间视频.mp4, conf0.25, iou0.45, imgsz640, saveTrue, classes[0] # 只保留person类别 )如果接的是工业相机流用cv2.VideoCapture读帧然后逐帧推理import cv2 from ultralytics import YOLO model YOLO(runs/detect/train/best.pt) cap cv2.VideoCapture(0) # 换成实际相机ID或RTSP地址 while True: ret, frame cap.read() if not ret: break results model(frame, conf0.25, iou0.45, classes[0])[0] annotated results.plot() cv2.imshow(车间人员检测, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这里要重点说一个参数配置思路conf阈值要按实际场景调固定摄像头场景下光照稳定可以适当提高conf到0.3到0.4来减少误检如果是移动巡检设备画面变化快conf可以降低到0.2左右优先保证不漏检。iou在0.4到0.5之间防止同一个人的多个框没有合并干净。5.2 从人员检测到更多业务应用训练好这个模型之后它就是一个可持续扩展的基础能力。我在实际项目里常用的扩展方向有三个。第一个是人员计数。在固定摄像头画面里划一条虚拟线或者一个虚拟区域当检测到的人的中心点越过线或进入区域时计数加一。这可以统计产线某个工位的人员在岗时长或者防止人员在危险区域逗留。第二个是安全帽识别。工业安全场景里人员检测通常和安全帽检测是配套的。常见做法是先用这个模型检测出人再对人的头部区域做一次裁剪用独立的分类模型判断是否戴了安全帽。这种级联方案比一次性训练多类别检测要稳定得多因为安全帽是小目标单独做分类更容易提高精度。第三个是扩展为多类别检测。如果业务需要识别“人安全帽反光衣”可以在现有标注基础上补充这些类别的数据把nc改成对应类别数然后加载best.pt继续训练。这样可以保留已经在车间场景上学到的人员特征不需要从头再来。实际项目中我发现用这种方式扩展类别即使新类别数据只有几十张结合迁移学习也能得到一个能用的模型。核心思路就是不要每次都从零开始让模型在已有积累上持续迭代。最后再分享一个落地层面的小建议。如果模型要部署到边缘设备上比如Jetson Nano或者RK3588这类板子上建议把权重导出为TensorRT或ONNX格式推理速度能提升不少。导出命令如下yolo export modelruns/detect/train/best.pt formattensorrt imgsz640导出后需要跑一遍验证集确认导出前后mAP没有明显下降一般fp16精度下差距在1%以内都属于正常。这一步很多人会忘记但部署到实际设备前精度对比验证是必须做的。本文还有配套的精品资源点击获取