yolov8_train.yaml
计算机视觉实战项目分享:从零到一的挑战与突破
记得刚进公司的时候,我被分配到了一个计算机视觉方向的项目。当时对CV的理解还停留在“图像分类”和“目标检测”这样的初级阶段,而这次的任务远比想象中复杂得多——我们要开发一套面向零售行业的智能货架监控系统,实时识别商品种类并统计库存状态。听起来不难?可真正做起来才明白什么叫“细节决定成败”。
这篇文章我会结合自己的亲身经历,聊聊整个项目的来龙去脉,包括遇到的技术挑战、踩过的坑、以及最终落地的过程。希望对你在实战中有所启发。
项目背景与业务需求


我们的客户是一家大型连锁超市,他们希望通过摄像头自动监控每个门店的商品摆放情况,比如哪些商品缺货了、哪些摆错位置了,甚至是否有人恶意替换标签等行为。传统的做法是靠人工巡检,效率低且容易出错。因此,他们希望能够借助AI技术实现货架商品的智能感知。
我们接手这个项目后,初步梳理了一下需求:
- 实时视频流处理
- 多角度货架识别(前后左右)
- 支持200+SKU商品类别
- 高精度识别 + 小样本学习能力(部分商品销量低,图片少)
- 可视化展示 + API接口供其他模块调用
听起来是不是挺像YOLO或者 Faster R-CNN的经典应用?没错,但实际操作下来你会发现,理论模型和生产环境差距还是很大的。
实际遇到的挑战

1. 图像质量差,角度多变
最开始我们以为只要收集足够多的商品正面图就行,结果现场部署发现摄像头角度千奇百怪,货架反光严重,有时候人走动还会遮挡画面。有些商品本身体积小、颜色相似度高,导致误识别率非常高。
2. 数据样本不平衡 + 标注困难
虽然客户提供了上万张标注好的训练数据,但其实很多都是主流商品,冷门品类几乎没有。比如某个品牌的矿泉水可能有几百张,而一些进口零食可能只有十几张。这直接导致模型在这些冷门类别上的表现很差。
另外,标注工作量也很大。初期我们试过外包给第三方团队打标,结果发现标注错误率太高,反而影响模型训练效果。
3. 实时性要求高,硬件资源有限
客户现场部署的是NVIDIA Jetson Nano这类嵌入式设备,性能有限。如果使用大模型(如ResNet50+FPN)的话根本跑不动,帧率太低无法满足实时监控的需求。
技术方案与实现思路
面对这些问题,我们一步步摸索出了以下方案。
模型选型:轻量化 + 多尺度
一开始尝试了YOLOv5,但在Jetson Nano上推理速度勉强达到12FPS,而且准确率不够理想。后来我们改用 YOLOv8n(Nano版本),搭配TensorRT加速,在保持精度的同时将帧率提升到24FPS以上,基本达到了客户的要求。
同时,为了提升小物体的识别能力,我们对输入图像进行了多尺度裁剪,并加入了旋转增强、模糊滤波、对比度调整等预处理手段。
数据增强策略优化
针对样本不平衡的问题,除了常规的数据增强(旋转、裁剪、翻转),我们还做了几件事情:
- 使用 MixUp 和 Mosaic 增强策略
- 对冷门类别的样本进行复制,并加入噪声扰动(模拟不同光照条件)
- 利用 StyleGAN 进行生成伪造图像(这部分还在实验中)
此外,我们还引入了一个基于类别权重的损失函数(Focal Loss 的变种),缓解样本不均衡带来的影响。
离线标注 + 半监督训练提效
为了解决标注效率问题,我们在内部搭建了一套简易的标注平台,同时采用 Active Learning(主动学习)机制,让模型先挑出最有“不确定性”的图片交给人工审核,减少无效标注时间。
具体流程如下:
- 模型在已有数据上训练一轮;
- 使用该模型在未标注数据上预测;
- 找出置信度低于某个阈值的样本,交给人工标注;
- 更新训练集,重新训练模型;
- 循环执行直到准确率达到目标。
这个方法让我们在只标注了原始数据的30%的情况下,就能获得接近90%的mAP。
关键代码示例
下面是一段模型训练的核心配置(以YOLOv8为例):
train:
imgsz: 640 # 输入图像尺寸
batch: 16 # batch size
epochs: 100 # 总共训练轮次
data: data.yaml # 数据集路径
model: yolov8n.pt # 模型权重文件
pretrained: True # 是否加载预训练模型
save_period: 5 # 每五轮保存一次模型
device: 0 # GPU ID
workers: 8 # 数据加载器线程数
再来看下损失函数优化部分的关键代码片段(简化版):
import torch
import torch.nn as nn
class FocalLoss(nn.Module):
def __init__(self, alpha=0.25, gamma=2.0):
super(FocalLoss, self).__init__()
self.alpha = alpha
self.gamma = gamma
def forward(self, inputs, targets):
BCE_loss = nn.functional.cross_entropy(inputs, targets, reduction='none')
pt = torch.exp(-BCE_loss)
F_loss = self.alpha * (1-pt)**self.gamma * BCE_loss
return F_loss.mean()

踩坑经验 & 解决思路
1. 推理延迟 vs 准确率平衡
最开始我们过于追求模型准确率,选择了参数较多的网络结构(YOLOv8s),结果在Jetson上完全跑不动,帧率只有7~8帧。最后换成YOLOv8n牺牲了一点精度(从92%降到89%),但换来流畅的实时体验。
建议: 在边缘设备上部署时,优先考虑轻量化模型 + TensorRT 加速。
2. 商品重叠识别难题
当多个商品堆在一起时,模型经常出现漏检。这个问题最终通过 非极大值抑制(NMS)的后处理优化 和 引入注意力机制 来缓解。
我们加了一个简单的空间注意力模块:
class SpatialAttention(nn.Module):
def __init__(self):
super(SpatialAttention, self).__init__()
self.conv = nn.Conv2d(2, 1, kernel_size=7, padding=3)
def forward(self, x):
avg_out = torch.mean(x, dim=1, keepdim=True)
max_out, _ = torch.max(x, dim=1, keepdim=True)
x = torch.cat([avg_out, max_out], dim=1)
x = self.conv(x)
return x.sigmoid()
3. 大规模部署中的模型一致性问题
在多个门店部署过程中,由于网络环境、摄像头型号、光照差异等问题,同一套模型在不同地点的表现差异明显。
我们最终的做法是:在每个门店安装完后,保留一小段时间用于采集门店本地数据,并对该地点单独进行微调(Fine-tune),大幅提升了模型适应性。
实施效果与收益
经过大约三个月的努力,项目终于顺利上线。效果如下:
| 指标 | 初始版本 | 最终版本 |
|---|---|---|
| mAP | 78% | 91% |
| 平均帧率 | 8 FPS | 24 FPS |
| 冷门商品识别率 | 52% | 83% |
| 客户满意度 | 中等 | 非常满意 |
更重要的是,这套系统节省了大量人力巡检成本,平均每家门店每天节省约2小时的人力投入。后续我们还接入了商品推荐系统,实现了更深入的业务联动。
给读者的一些建议
如果你正在或打算做一个CV实战项目,以下是我在实战中总结的一些经验:
- 不要一味追求SOTA模型,合适的才是最好的。 尤其在边缘端部署时,轻量级模型配合后处理往往能带来意想不到的效果。
- 数据永远是第一位的。 与其花大量时间调参,不如先好好清理数据、补充样本、设计合理的增强方式。
- 多做一些可视化分析。 模型输出看不清摸不着的时候,不妨画个特征热图或attention权重图,也许会发现问题所在。
- 别忽视业务场景的特殊性。 同样的算法,在不同环境下可能表现迥异。一定要多实地调研,理解真实用户的使用方式。
- 团队协作很重要。 如果你不是一个人单枪匹马,那么确保大家有良好的代码规范、版本管理和文档记录,否则后期维护会很痛苦。
结语
计算机视觉的应用已经渗透到各行各业,但每当我们把论文里的模型搬到真实世界时,总要面对各种各样的现实问题。这个过程虽然充满挑战,但也让我收获颇丰。
从最开始对CV的认知仅限于“分类和检测”,到现在能够独立完成一个完整的项目闭环,这段经历让我深刻体会到——真正的“人工智能”,其实是在不断解决一个个“非智能”问题的过程中成长起来的。
希望这篇文章对你有所帮助。如果你也有类似的实战经历,欢迎留言交流!我们一起在这个AI时代里边学边干,共同进步 💪
文章来自一名在一线互联网公司奋战的AI开发者,如有不准确之处,欢迎批评指正。

评论 0