☰
基于YOLOV8的纸箱检测计数系统:从数据集构建到部署实战
2026/10/19 2:37:59 网站建设 项目流程

仓库管理干得久的都知道,纸箱盘点这件事有多让人头疼。尤其是电商大促、制造业成品入库这种场景,一托盘的箱子叠得密密麻麻,靠人拿扫码枪挨个扫,或者瞪着眼睛数,效率低不说,数错一笔账就是实打实的损失。我见过好几个人工盘点的仓库,月底对账差异率能到百分之三到五,这个数字放到几千平方的仓储面积里,就是一大笔钱。

最近我把基于YOLOV8的纸箱检测计数系统从头到尾搭了一遍,从数据集构建、模型训练到部署上线,整个过程踩了不少坑,也沉淀下来一套能直接复用的流程。这篇内容就把完整方案拆开讲清楚,包括数据集怎么做、YOLOV8怎么调、堆叠场景的计数怎么做到高精度,以及实际落地时的坑和优化手段。无论你是刚接触目标检测的学生,还是已经在做智能仓储项目的工程师,照着这套思路做,能少走很多弯路。

1. 系统设计思路与方案选型

1.1 需求拆解:检测和计数不是一回事

做这个项目之前,我先把需求掰开了看。标题里有两个核心词:纸箱检测、堆叠计数。很多人上来就把它当做一个目标检测任务,训个模型能框出箱子就完事了,但真正落地时你会发现,检测是计数的基础,计数才是用户真正关心的结果。

实际场景大致分三类:地堆、托盘堆叠、货架存储。地堆最常见也最乱,箱子互相遮挡,层数不一;托盘堆叠相对规整,但不同品规的箱子尺寸差异很大;货架存储则涉及多层隔板间的遮挡关系。所以系统要处理的不是"一张图有多少个箱子"这么简单,而是要稳定应对部分遮挡、紧密相邻、光照不均、箱体反光这些问题。

我当时给自己定下的目标是:检测精度mAP50达到95%以上,单帧计数准确率不低于92%,在普通GPU服务器上推理速度不低于30FPS。这几个指标框定了模型选型和优化的大方向。

1.2 为什么选YOLOV8而不是其他框架

现在做目标检测,能选的方案不少。两阶段的Faster R-CNN系列精度高但速度太慢,在实时计数场景不实用;YOLOv5已经是老将,生态成熟但一些细节设计偏旧;YOLOv7在COCO上有不错的表现,但工程化体验不如V8;还有RT-DETR这类端到端检测器,精度上好,训练和部署成本却更高。

我把几个候选方案放在同等条件下对比过,最终选了YOLOV8,理由很实在:

对比维度YOLOv5YOLOv7YOLOV8RT-DETR
训练速度较快中等较快慢
推理速度快快快中等
Anchor-Free否部分是是
部署生态成熟一般好一般
工程易用性中等中等高低

YOLOV8最大的优势是Anchor-Free设计,去掉了预设锚框这一大堆超参数,对于纸箱这种长宽比变化不小的目标来说,模型自适应能力更强。配套的Ultralytics框架训练、导出、部署一条龙,省下的时间足够把精力放在数据集和计数逻辑上。

1.3 系统总体流程设计

整个系统我拆成了五个环节:数据采集与标注、模型训练与评估、检测后处理、计数决策、结果输出与统计。每一步之间都有明确的输入输出接口,这样就算后面换模型或者改场景,也不用推倒重来。

实际落地时最容易被忽略的是"检测后处理"这一步。模型输出的是带置信度的边界框,但这些框里可能有重叠、误检、闪烁,如果不处理直接计数,误差会非常难看。我设计了一套规则:先用置信度阈值过滤低质量框,再用NMS去掉重叠框,最后结合目标尺寸和位置的合理性做一次校验。

2. 数据集构建:高精度模型的地基

2.1 数据采集策略与场景覆盖

数据集的质和量直接决定模型上限。我见过不少人随便拍几百张照片就开训,结果模型在测试集上看起来不错,一到现场就垮掉。原因很简单,训练数据的分布和真实场景不一致。

我采集数据时重点覆盖了几个维度:

  • 堆放形态:地堆、托盘堆叠、货架层板、输送线单排摆放
  • 拍摄视角:平视、俯视、斜视45度、高位监控视角
  • 光照条件:仓库日光灯、自然光、逆光、暗光
  • 遮挡程度:无遮挡、轻遮挡(遮挡面积小于30%)、重遮挡(大于30%)
  • 箱子外观:黄色牛皮纸箱、白色快递箱、印字彩箱、缠膜托盘

这里有个经验:宁可每个场景少拍一些,也要保证场景类型丰富。模型见得多,泛化能力才会好。我最终收集了模拟仓库环境下的3800多张真实照片,剔除模糊和过度重复的样本后,留下约3200张用于标注。

2.2 标注规范与工具选型

标注是数据集构建中最耗时也最影响上限的环节。我先定了一套统一的标注规范:

  • 只标注完整可见且能明确判断为纸箱的目标
  • 遮挡面积超过50%且箱体轮廓不完整的目标不标注
  • 紧密相邻的箱子必须分开标注,不能合并
  • 边界框紧贴箱体边缘,宁可略紧不要宽松
  • 同一张图中同一类目标标注风格保持一致

标注工具我用过LabelImg和X-AnyLabeling。LabelImg是经典选择,安装简单、占内存小,适合单人标注;X-AnyLabeling自带SAM辅助分割,半自动标注效率高,适合大批量任务。我的建议是:数据量在2000张以下用LabelImg就行,超过这个量级直接上X-AnyLabeling,能省一半时间。

标注完成后统一导出为YOLO格式,也就是每个图片对应一个同名txt文件,每一行是class_id x_center y_center width height,坐标值基于图片宽高归一化到0到1之间。

2.3 数据增强策略

模型训练时的数据增强我用得比较克制,因为纸箱检测场景本身对颜色和纹理敏感度不高,关键在形态多样性。

Ultralytics框架默认开启的增强包括随机HSV扰动、随机平移、随机旋转、Mosaic拼接。对于纸箱堆叠场景,Mosaic增强非常有效,能把多张图和不同摆放形态拼在一起,极大增加单视角下目标的密度和分布多样性。

我额外做了两类处理:一是针对光照不均衡场景,用OpenCV做了亮度曲线调整,模拟暗光条件;二是针对遮挡场景,做随机遮挡模拟,用黑色方块随机覆盖部分目标区域,逼模型学会看局部特征。这两类增强分别保留了约25%的比例混入训练集。

2.4 数据集划分原则

训练集、验证集、测试集的划分不能随机抽。如果同一个堆放区域的照片同时进了训练和验证集,会出现"泄漏",评估结果虚高。我按拍摄场景整体划分,一个区域的多张照片要么全部进训练,要么全部进验证或测试,确保验证集能真实反映模型对不同场景的适应能力。最终划分比例是训练集70%、验证集20%、测试集10%,测试集单独留着做最终性能评估。

3. YOLOV8模型训练实操

3.1 环境搭建与依赖配置

训练环境的版本组合我用的是当前稳定的组合:Python 3.10、PyTorch 2.1、CUDA 12.1、Ultralytics 8.1以上版本。装好CUDA后先跑一个简单的张量运算验证GPU可用,避免训练到一半才发现用的是CPU在跑。

数据集文件结构按YOLO标准组织:

dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml

data.yaml内容很简单,指定路径、类别数和类别名:

path: /path/to/dataset train: images/train val: images/val nc: 1 names: ['carton']

这里有个小坑要提醒:路径最好写绝对路径,写成相对路径有时候训练能跑但验证时找不到图片,排查起来很浪费时间。

3.2 预训练模型选择与训练参数解析

YOLOV8有n、s、m、l、x五种规格,参数量从300万到6800万不等。我第一轮用yolov8n做快速验证,确认数据没问题后,用yolov8m做正式训练。倒不是因为n精度不够,而是纸箱堆叠场景中重叠目标多,m模型的C2f结构在特征融合上更稳,mAP50往往能比n高出两到三个点,推理速度在GPU上依然能跑到40FPS以上,完全够用。

训练命令:

yolo detect train data=data.yaml model=yolov8m.pt epochs=300 imgsz=640 batch=16 patience=30 optimizer=AdamW lr0=0.001

关键参数我的选择理由如下:

  • imgsz=640:纸箱不算小目标,但堆叠场景中远处的箱子会很小,640的输入能在精度和速度间取得平衡
  • batch=16:由显存决定,我用的是24G显存的卡,batch再大提升有限
  • patience=30:早停参数,如果连续30个epoch的在验证集上没有提升就停止,避免过拟合并节省时间
  • optimizer=AdamW:收敛速度比SGD快,在中等规模数据上表现更好
  • lr0=0.001:初始学习率我用AdamW的常用推荐值,太大容易震荡,太小收敛慢

3.3 训练过程监控与关键指标解读

训练不是把命令丢出去就完了。我习惯同时盯着几个指标:train/loss、val/loss、metrics/mAP50、metrics/mAP50-95。重点关注验证集上的mAP50-95,因为这个指标对边界框的定位精度更敏感,纸箱计数对框的位置精度要求很高,框偏了就容易造成重复计数或漏计。

我第一次用yolov8n训的时候,mAP50到了96%,看起来不错,但mAP50-95只有68%,定位精度不够,计数时问题很大。换成yolov8m后,mAP50-95提升到75%以上,计数准确率明显改善。

训练结束后我会跑一遍混淆矩阵,看看误检和漏检的主要类型。如果某个硬样本场景下的召回率过低,就去补数据而不是盲目调参。

3.4 一张表说清训练参数调优经验

遇到的现象优先调整项说明
mAP50高但mAP50-95低换更大的模型定位精度的瓶颈往往在特征提取能力
验证集loss下降但mAP不涨检查数据标注质量大概率是标注框不贴合目标
漏检远处小箱子提升imgsz到960但推理速度会明显下降
误检非纸箱目标增加负样本把没有箱子的背景图加入训练集
训练后期过拟合降低epoch或者增强数据扰动早停参数也可以缩小一点

4. 堆叠场景计数算法核心逻辑

4.1 基础计数逻辑:从检测框到数量

模型输出的是一组边界框:class_id、中心点坐标、宽高、置信度。最直接的计数方法就是统计置信度大于阈值的框数量:

import cv2 from ultralytics import YOLO model = YOLO('best.pt') results = model.predict(frame, conf=0.25, iou=0.5) boxes = results[0].boxes count = len(boxes)

就这几行代码,一个最朴素的计数功能就跑起来了。但实际落地时你会发现,问题多得很:同一个箱子在连续几帧里被重复计;一个箱子检测框被NMS误合并成两个框;堆叠太密导致底层箱子漏检。这些都得在计数逻辑层面处理。

4.2 单层堆叠的NMS与置信度联动优化

NMS阈值和置信度阈值是密切相关的两个参数,分开调会很痛苦。置信度调低,召回上去了,但误检也多了;置信度调高,误检少了,漏检又来了。我调参时用了一个双参数联动的思路:在小范围测试集上做网格搜索,把conf从0.15到0.4、iou从0.4到0.7组合跑一遍,以F1分数为准选出最佳组合。最终我常用的组合是conf=0.25、iou=0.45,在大多数场景下效果比较稳。

还需要注意Ultralytics在predict时有两个阈值:conf和iou。conf过滤置信度低的框,iou控制NMS合并时的重叠程度。前者影响召回,后者影响精确率。堆叠场景里箱子挨得近,iou设太大会把小框合并掉,设太小又会出现同一个目标的重复框。实际项目里我会用简单脚本针对测试集做参数枚举,找到一次性稳的搭配。

4.3 堆叠遮挡场景的高级计数策略

重遮挡场景才是计数误差的大头。箱子叠在一起,底层箱子可能只有一小条边露在外面,模型检测不出来,直接按检测框计数,漏检率会很可观。这时我做了两个层面的优化:

第一层是滑动窗口检测。把原始大图切成多个512x512的重叠窗口,每个窗口独立检测,再统一合并结果。这个手段对小目标的召回提升明显,代价是推理时间增加。我一般只在关键点位使用,比如传送带出入口这类需要精确定数的位置。

第二层是基于跟踪的跨帧去重。单个静态画面信息有限,但如果摄像头能看到一个短暂过程,就能利用序列信息。简单有效的做法是用ByteTrack这类轻量跟踪器,将不同帧中同一个箱子关联到同一个ID,计数时只统计新出现的ID。这么做有几个明显好处:一是消除重复计数,二是箱子被短暂遮挡后恢复,只要轨迹未断,不会二次计数。

我实际测试过一个场景:托盘装满箱子后用叉车运过摄像头前,单帧检测约数到76个,跟踪去重后稳定在81个,人工核对就是81箱,误差直接降下来了。

4.4 计数结果校验机制

为了防止计数结果出错,我加了一道校验逻辑:对大目标(面积异常大或宽高比异常)做拆分提示。这类目标很可能是多个箱子靠太近导致检测框并框了。具体做法是结合目标面积和单箱平均面积做比值,如果比值超过1.5倍,就标注为"待确认",交由后续细化模块处理。这道校验把边缘error率进一步压缩了不少。

5. 模型部署与精度优化

5.1 导出与推理加速

模型训练完不是直接拿来用的。我把PyTorch模型导出为ONNX再转为TensorRT引擎,推理速度能提升两倍左右。TensorRT的构建过程要指定精度模式,FP16精度在纸箱检测这个任务上没有明显精度损失,但速度优势显著,优先使用。

导出命令:

yolo export model=best.pt format=onnx dynamic=True trtexec --onnx=best.onnx --saveEngine=best.engine --fp16

部署时用TensorRT引擎推理,单张640x640输入在消费级GPU上能跑到3到5毫秒,满足实时性要求。CPU部署是另一个常见需求,但YOLOV8在CPU上跑640输入大概需要60到120毫秒,对实时场景偏慢。如果必须CPU,建议用静态尺寸导出ONNX并开多线程,或者干脆降低推理分辨率。

5.2 实际场景中的硬性问题处理

纸箱检测的实际环境比训练集复杂得多,有几类问题几乎每次都会碰到:

  • 箱体反光。仓库灯光从顶部打下来,牛皮纸箱表面会产生高光区域,局部纹理被"洗白",容易漏检。我的对策是训练数据里加强光照扰动,并尝试在推理前对图像做去高光预处理
  • 叉车遮挡。工作状态下叉车的手臂、货物会挡住部分箱子,造成目标被切割。这种必须靠跟踪,帧间信息补全
  • 视角透视。同一个区域的箱子在画面不同位置尺寸差异大,单纯用固定阈值过滤小目标会误删远处的真实箱子。我改为按画面区域动态调整置信度阈值,远处区域用低阈值。

5.3 一张常见问题排查速查表

现象大概率原因处理办法
漏检底层重叠箱子遮挡过重、特征信息不足滑动窗口+底层专项训练数据
同一个箱子计数两次跟踪ID切换或NMS阈值过低调高IOU阈值、检查跟踪器参数
把非纸箱物体识别为纸箱负样本不足、特征混淆增加背景负样本、降低置信度阈值
夜间或暗光场景检测率骤降训练集缺少暗光样本补充暗光数据或做亮度归一化
推理延迟波动大动态尺寸ONNX影响缓存效率固定输入尺寸、TensorRT静态化
检测框抖动导致计数闪烁单帧输出不稳定跟踪算法+置信度平滑

5.4 系统扩展思路

这个项目的框架完全可以扩展到更多仓储场景。比如把单分类改成多分类,区分不同品规箱型;或者叠加OCR模块读箱体上的标签,把"数了多少个"升级成"哪些箱子到场了"。我目前在做的一个方向是把计数结果直接对接到仓储管理系统,每次计数自动生成盘点记录,省掉人工录入环节。

6. 实操心得体会

这套系统我从数据集采集到部署上线大概用了一个月,真正花费时间最多的不是写代码,而是数据集打磨和参数调优。有几个体会分享给正在做的朋友。

数据集的采集一定要到现场去,哪怕先拿手机拍一百张回来看看也是好的。我用训练集里加入手机拍摄的低分辨率图片后,模型在现场旧摄像头的效果提升非常明显,这一点很多人会忽略。

训练参数的调节不要贪心。YOLOV8在默认参数下已经能跑到很好的baseline,先把baseline跑出来,再针对具体问题做小步调优,远比我一开始那样同时调四五个参数高效得多。

计数规则的优先级思考很关键。我后来把"宁可漏检也不误检"定成默认策略,原因在于漏检可以通过跟踪算法补偿,而误检直接污染统计数据,用户感知极差。这个思路不一定普适,但值得做业务的人深入权衡。

最后提醒一个部署细节:摄像头安装高度和角度一定要在实际使用的位置拍摄测试数据。我遇到过现场把摄像头装在货架顶部的俯视角场景,训练集里几乎没有类似的俯视大倾角样本,模型效果断崖式下跌。重新补了一批高位俯拍数据后才恢复正常。前期如果能提前确定安装位,这半个月的时间是可以省下来的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询