计算机视觉实战:从“识别猫狗”到运营提效,我的CV落地血泪史

慢慢写代码
2025-12-13 00:28
阅读 527

大家好,我是阿哲,一个在深圳某腾讯系公司搬砖的前端工程师(别笑,真有人以为前端不会搞CV?)。平时喜欢翻开源项目的源码,GitHub commit 记录比我的微信聊天记录还密集。上周五晚上还在加班调一个 Lottie 动画的贝塞尔曲线,结果周一早上就被老板拉进会议室:“我们想做一个商品陈列识别系统,帮线下门店做运营巡检,两周内出 Demo。”

我当场瞳孔地震——这不就是 CV 的活儿吗?!但转念一想,前端玩 Three.js 和 WebGL 都能搞 3D 渲染了,搞个 OpenCV + YOLO 算什么?于是,我这个“全栈边缘人”硬着头皮接下了这个看似不可能的任务。


为什么运营需要计算机视觉?

这事得从去年双11说起。我们给品牌客户做的小程序,线上流量爆了,但线下门店的货架陈列却乱成一锅粥——该放新品的位置堆着旧货,竞品混在自家产品中间……运营同事每天靠人工巡店拍照、Excel 打分,效率低到令人发指。产品经理甚至放出狠话:“要是能自动识别货架上有没有我们的产品、位置对不对,我就请你喝一个月喜茶。”

听起来很美好,但实际做起来,坑比深圳湾的共享单车还多。


从“Hello World”到真实场景:CV 不是玩具

我一开始天真地以为,找个现成的 YOLOv5 模型,拿 COCO 数据集微调一下就行。结果第一次在门店实拍图上跑,模型把一瓶可乐识别成了“消防栓”,把我们的新品包装盒认成“信封”。当时真的想砸电脑。

问题出在哪?训练数据和真实场景差距太大。COCO 里的瓶子都是干净、居中、光线充足的,而门店照片呢?反光、遮挡、角度刁钻、背景杂乱……更别说不同门店灯光色温还不一样。

于是,我拉着测试同学一起蹲点拍了三天照片,收集了 2000+ 张真实货架图,手动标注了 8 个 SKU 的位置和类别。用 Roboflow 做了数据增强:随机亮度调整、添加运动模糊、模拟手机拍摄畸变……这才让模型勉强“睁眼看世界”。

💡 开发心得:别迷信公开数据集!业务场景越垂直,自建数据集越重要。哪怕只有几百张,也比用百万级通用数据强。


模型选型:轻量 vs 精度,一场妥协的艺术

最初我试了 YOLOv8,精度高但推理速度慢(RTX 3060 上 15 FPS),根本扛不住门店巡检 App 的实时需求。后来换成 YOLOv5s,速度提到 45 FPS,但小目标漏检率飙升。

最后折中方案:YOLOv5n + TensorRT 量化 + ONNX 导出。关键配置如下:

# yolov5n.yaml (精简版 backbone)
nc: 8  # 我们的 SKU 类别数
depth_multiple: 0.33
width_multiple: 0.25
anchors:
  - [10,13, 16,30, 33,23]
  - [30,61, 62,45, 59,119]
  - [116,90, 156,198, 373,326]

导出 ONNX 后,用 onnxruntime-gpu 在服务端部署,单图推理时间压到 80ms。虽然精度掉了 3%,但运营同事反馈“能用就行”——毕竟他们不是做自动驾驶,错一两瓶不影响整体评分。

模型 mAP@0.5 推理速度 (ms) 模型大小 (MB)
YOLOv5l 0.89 180 170
YOLOv5s 0.82 95 27
YOLOv5n 0.78 80 6.5

代码人生:从“跑通”到“上线”的九九八十一难

最崩溃的不是训练,而是集成到现有系统。我们的巡检 App 是 React Native 写的,不能直接跑 PyTorch。于是搞了个 Flask 微服务,App 拍照上传,服务端返回识别结果。

但第一次上线就炸了:运维同学没开 GPU 实例,CPU 跑 ONNX 直接超时。日志里全是:

[ERROR] Request timeout after 30s

连夜改架构:加 Redis 缓存、异步任务队列、失败重试机制。还写了个简易 Dashboard,让运营能直观看到“今天识别了多少家门店、准确率趋势如何”。

# inference.py 核心逻辑(简化版)
import onnxruntime as ort
import cv2

class ShelfDetector:
    def __init__(self, model_path):
        self.session = ort.InferenceSession(model_path, 
                                          providers=['CUDAExecutionProvider'])
    
    def preprocess(self, img):
        # BGR -> RGB, resize, normalize
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img, (640, 640))
        img = img.astype(np.float32) / 255.0
        return np.transpose(img, (2, 0, 1))[None, ...]

    def detect(self, img_path):
        img = cv2.imread(img_path)
        input_tensor = self.preprocess(img)
        outputs = self.session.run(None, {'images': input_tensor})
        return self.postprocess(outputs)  # 返回 bbox + class

面试题挑战:你以为 CV 只是调库?

上周组内技术分享,leader 突然问我:“如果门店灯光突然变暗,模型性能下降怎么办?”

我差点脱口而出“加数据”,但忍住了。其实更优解是在线学习 + 主动学习:当模型置信度低于阈值时,自动将图片加入待标注队列,运营确认后增量训练。这招我在 Hugging Face 的一个开源项目里见过,立马安利给了算法组。

这也让我意识到:CV 工程师不能只懂模型,还得懂业务闭环。比如我们后来加了个“陈列合规度”打分逻辑:

  • 产品是否在指定区域?
  • 是否被竞品包围?
  • 是否正面朝外?

这些规则和 CV 结果融合,才真正帮运营提效。现在他们每周省下 20+ 人天,连产品经理都开始主动问:“下一个能识别价签吗?”


总结:CV 不是魔法,而是解决问题的锤子

回看这两周,从被逼上梁山到搞定上线,最大的感悟是:技术的价值不在 fancy,而在“能用”。面试官老爱问“你做过什么 CV 项目”,但真正打动业务方的,从来不是 mAP 提升了 2%,而是“我帮你少雇了两个巡店员”。

如果你也在深圳,或许哪天在南山科技园排队买咖啡时,会看到我一边 debug 一边刷 Kaggle。或者,你正被老板要求“用 AI 解决某个奇怪需求”——别慌,CV 没那么可怕,它只是另一套 if-else,只不过条件判断换成了神经网络。

最后送大家一句我在 GitHub README 里写的签名:

“代码改变不了世界,但能让运营少填一张 Excel。”

共勉。


附:避坑清单(血泪经验)

  • ❌ 别在 CPU 上跑 GPU 模型(说的就是你,运维兄弟)
  • ✅ 一定要做数据分布分析:门店照片的光照/角度/遮挡情况
  • ✅ 评估指标别只看 mAP,关注业务相关的 recall(比如“漏检新品”比“误检竞品”更致命)
  • ✅ 模型压缩优先考虑 ONNX + TensorRT,比 TF Lite 更适合服务端
  • ✅ 给运营一个可视化界面,他们会更愿意用你的系统

(完)

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝