计算机视觉进入下半场,这句话我在行业里听了快两年。一开始我把它当媒体造词,直到自己从纯算法岗转到带落地项目,才明白这句话翻译过来就一个意思:想靠模型结构刷分刷出竞争力,越来越难了。真正把一个计算机视觉项目从demo推到生产环境,卡住你的极少是某个模型的参数量或者新不新,而是一些听起来很不性感的东西——数据怎么闭环、推理怎么提速、指标怎么对齐业务、系统挂了你怎么办。这篇文章想把这些问题摊开聊一遍,也把我这两年实际踩过的坑和验证过的做法记下来,希望能帮正在做计算机视觉项目、或者准备入行的朋友,把注意力放回真正决定成败的地方。
1. 为什么说视觉落地进入了“下半场”
1.1 模型刷分的路越走越窄
公开数据集刷分时代,大家比的是谁能在ImageNet、COCO这些榜单上往前挪一位。从ResNet到Transformer,再到扩散模型、多模态大模型,每隔半年就有一批新结构出来刷新纪录,那段时间确实热闹。但最近两年风向明显变了:头部模型的精度差距缩到一两个点,想再往上提,靠的不是灵感,而是超大的训练集群和烧掉的电费。普通团队、普通项目根本玩不起这种军备竞赛。
更要命的是,榜单上刷出来的那一两个点,放到真实业务里常常直接归零。我见过太多论文里指标漂亮的模型,拿到工厂产线或者园区监控现场,因为光线、视角、遮挡、样本分布完全不一样,表现直接崩盘。这不是模型本身差,而是刷分场景和业务场景之间隔着一条巨大的鸿沟:公开数据集是干净、均衡、标注准确的,真实场景是脏乱、长尾、充满各种意外的。模型结构创新的价值我当然认,但在落地视角下,它早就不在关键路径上了。
1.2 demo能跑和产品能用是两码事
我印象最深的一个项目,前期在测试集上mAP做到0.93,客户看完demo非常满意,结果模型一到现场新产线,实测只有0.7左右。问题出在哪?现场的光线是黄灯混合日光,缺陷样本的种类比我们标注集多出好几倍,还有大量半成品、反光、油污造成的疑似目标。demo阶段我们用的是精心挑选的几百张图片,而现场是连续不断的视频流。这种落差不是个别现象,几乎是每个视觉落地项目的必修课。
更深一层看,模型只是整个系统中的一环。一套能用的视觉系统,至少包含采集、解码、推理、后处理、业务逻辑、告警、运维监控。哪怕模型本身精度合格,只要并发一高进程崩溃、视频流断流没人管、告警风暴把客户惹毛,项目照样失败。所以我一直跟团队说一句话:demo的终点是模型的诞生,产品的起点是系统的成立。想明白这一点,再看“模型之外什么决定落地”,答案就清晰多了。
2. 真正决定落地的四个“模型之外”的因素
2.1 数据配比:比模型结构更影响上限
做视觉的人大多听过一句话,数据和特征决定上限,模型只是逼近这个上限。落地项目里,最磨人的不是调网络结构,而是搞数据。真实场景的问题几乎都是长尾:常见的缺陷、常见的目标只占一小部分,真正要命的是那些低频但高风险的样本。比如工业质检里,某种裂纹一个月就出现几次,但漏掉一次就可能整批退货。这种样本靠人工采集根本攒不够。
我实操下来比较有效的做法有三个。第一是用扩散模型做数据合成,把稀缺缺陷贴到真实背景图里,或者用ControlNet生成可控角度、可控光照的目标样本,我试过在某纹理缺陷项目上,合成数据把检测准确率提高了五到八个点。第二是用CLIP做困难样本挖掘,把海量无标注视频帧用CLIP做语义聚类,自动挑出模型容易混淆的片段送去人工标注,比随机抽帧效率高太多。第三是搭主动学习闭环,把推理阶段置信度落在模糊区间的样本自动回流到标注池,让模型越用越准。
这里有个坑要提醒:合成数据比例别贪多,我见过有人合成样本加到一半,结果模型在真实图像上反而变差了,因为它学的是合成图像的风格纹理。一般控制在训练集两成以内,而且要混着真实样本一起训。
2.2 推理性能:算力墙面前的现实选择
很多算法工程师习惯在A100上训模型、跑推理,完全没想过现场设备可能是Jetson nano、老旧工控机,甚至要同时处理几十路视频流。这也是为什么YOLOv5s轻量化这类话题一直有热度——大家不是因为它结构多新,而是它在精度损失可接受的前提下,把计算量压到了能落地的水平。
我的经验是,优化推理性能有个固定套路:先把模型转成TensorRT或者ONNX Runtime格式,用FP16精度跑,一般能把延迟压到原来的三分之一左右。如果还不够,再考虑INT8量化,但工业场景经常掉点两三个点,尤其小目标检测特别敏感。遇到这种情况,我的做法是先跑一遍量化,把掉点严重的层找出来,只让敏感层保留FP16,其他层继续INT8,这样能兼顾速度和精度。注意校准集一定要用真实场景抽帧,别用训练集,否则量化出的零点分布是偏的。说到底,目标不是指标最高,而是在给定算力下产出最大的业务价值,这个观念不转过来,后面容易白忙活。
2.3 业务指标:客户要的不是mAP
你去跟客户说mAP提升了两个点,他只会礼貌点头,然后追问一句:漏检率降了多少?误报每天能压到几次?单条视频处理延迟多少?事件处置率有没有提升?这才是业务关心的。技术指标和业务指标之间需要翻译。
我比较常用的一套方案是模型加规则再加机器学习。视觉模型负责感知,输出检测框、置信度、目标特征,后面接一个lightgbm回归模型做结果校准和风险评分。举个例子,安防场景下检测模型给了个人形框,但这个人可能是海报、是影子、是远处走来的真人员。我把框的大小、运动速度、置信度、帧间位置差、画面亮度这些特征喂给lightgbm,输出一个“该目标值得告警”的概率,误报率直接降了一半。这种模型融合思路在工业视觉里非常实用,视觉模型不负责最终决策,它把感知结果交给一个更懂业务逻辑的模型去判断。这种组合方式也提醒我们,别把鸡蛋全放在一个深度模型里,感知和决策分开,反而更好调、更好解释。
2.4 部署运维:从“交模型”到“交系统”
模型文件交付,是我最反对的一种交付方式。权重文件给过去,对方没有环境、没有依赖、没有文档,跑不起来算谁的?现在比较成熟的思路是把模型包进容器,用Docker把推理服务、运行库、依赖环境一起打包,推到服务器就能跑。这个思路不只适用于视觉模型,大模型部署也一样,像docker部署ollama、GGUF模型部署,都是把模型和运行时打包成标准服务,大家越来越习惯这套容器化方案。
更关键的是服务治理。线上会有并发高峰,如果没有队列和限流,同时来几百路请求,推理服务直接显存溢出或者进程崩溃,然后你就看到客户端抛“模型繁忙,请稍后重试”。这种提示本质上是后端没有流量控制,和模型本身一点关系都没有。我现在做项目都会强制要求加三样东西:请求队列带超时和丢弃策略、GPU资源隔离、推理延迟和错误率的监控曲线。模型升级也要走灰度发布,先切一小部分流量观察,没问题再全量,否则一次升级回退就够你加一周班。
3. 一个智慧园区项目的全流程实操复盘
3.1 需求拆解与模型选型
去年我带了一个智慧园区人员监管项目,需求是跨摄像机追踪一个目标的行踪,并对重点区域做异常行为报警。几十路摄像头分布在园区不同角落,算力是几台带GPU的边缘服务器,单路画面要求实时处理。这个需求直接决定了选型方向:检测用YOLOv5s轻量化版本,跨镜追踪用轻量ReID模型,目标是把单路延迟压在30毫秒以内。
为什么不选更大的模型,比如YOLOv8x之类的?因为瓶颈不在单帧精度,而在于并发路数。几十路视频同时推流,任何一个环节稍微重一点,服务器就可能扛不住。模型融合在这个项目里也不是简单的多模型投票,而是检测、分类、ReID三层级联,前一级的输出作为后一级的输入,最后再用业务规则把结果融合起来。这样设计还有个好处:每个模型都是独立模块,以后检测模型升级了,ReID和决策层不用跟着动,维护成本低很多。
3.2 数据工程与训练细节
这个项目最耗时间的不是训练,而是数据处理。园区摄像头角度高低不一,有逆光、有夜间红外、有镜头上有污渍,必须保证训练数据把这些情况都覆盖到。标注阶段最怕的是标准不一致:有的人把远处模糊的人形框进去,有的人漏标,模型学出来的特征就是乱的。所以我会先把标注规范写成文档,附上典型样例,再让两个人背对背标同一批图,用一致率抽检。
训练到中期有个技巧特别值钱:用当前模型在真实视频上跑一遍,把误检和漏检的片段全部导出,人工挑出最典型的那些,补标之后加进训练集。这比随机加数据有效得多,因为模型自己告诉了你它哪里不会。另一个细节是数据增强要克制,Mosaic增强在检测小目标时确实有用,但在人员检测这种尺度相对稳定的任务上,有时反而破坏尺度分布,我做过A/B试验,最后关闭了Mosaic,精度还提升了一点点。另外我还用CLIP微调了一个场景分类器,自动判断当前摄像头是白天、夜间还是逆光,用来切换推理时的预处理参数,这个小模块后来省了大量调参的时间。
轨迹后处理也有讲究。检测框在帧间会抖,直接输出坐标给业务方,轨迹图会像心电图一样乱跳。我这边用的是滑动窗口滤波模型,对连续几帧的坐标取加权平均,画面平稳时非常稳,比卡尔曼滤波简单,实时性也好。
3.3 模型优化与推理部署
模型训练完只是开始,上线的关键环节是转引擎。我的流程一般是:先把PyTorch的pt权重导出成ONNX,再用TensorRT把ONNX转成engine,推理时直接加载engine。转的这一步有几个容易踩的坑:一是固定batch size反而性能更好,动态batch看着灵活,但TensorRT优化得不充分;二是工作空间设置太小会导致转引擎失败或者性能很差,我一般给到2GB以上;三是精度模式,先直接用FP16,跑不通再排查。
核心命令大概是这样:
# 导出ONNX python export.py --weights yolov5s.pt --include onnx --opset 12 --simplify # ONNX转TensorRT FP16 trtexec --onnx=yolov5s.onnx --saveEngine=yolov5s.engine --fp16 --workspace=2048 # ONNX转TensorRT INT8 trtexec --onnx=yolov5s.onnx --saveEngine=yolov5s_int8.engine --int8 --calib=calib.txt --workspace=2048部署端我用Docker把推理服务打包,基础镜像选nvidia/cuda对应版本,里面装好TensorRT、Python运行时和推理代码,用docker compose管理多个服务实例。并发控制上,我没有让请求直接打到推理进程,而是先经过一个消息队列,worker按显存余量拉取任务处理,这样就算高峰期来了几百个请求,最多就是排队,不会把GPU打爆。实测下来,优化前单卡并发五路视频流就顶不住了,做完FP16加队列优化后能稳定跑到三十路以上。
3.4 后处理与业务融合
业务方不关心你用的什么模型,他关心的是地图上能不能看到人、点一下能不能查看历史轨迹。所以视觉系统必须提供干净的业务接口:识别结果的坐标、目标ID、时间戳、置信度,按规范字段推送出去。这个项目里,我们把识别结果写进消息队列,再通过Cesium加载OBJ格式的建筑模型,在3D场景中实时渲染人员位置,支持拖拽模型旋转视角,按时间轴回放轨迹。这种3D可视化的效果对客户非常直观,也方便运维人员快速定位问题区域。
这一步也让我体会到,视觉落地的最后一公里往往是接口和交互,不是算法本身。识别结果如果只是堆在数据库里,业务价值就打了折扣。设计接口时就要想清楚下游要消费什么数据,目标ID怎么分配、时间同步怎么对齐、跨镜切换时轨迹怎么拼接,这些细节不在模型里,但都在决定项目成败。
4. 上线之后才会遇到的真问题:排查实录
4.1 白天黑夜两个“模型”
项目上线第一个月,最头疼的问题是白天和晚上的表现完全是两个样子。白天阳光充足,检测得很准;到了晚上灯光混杂,误检率飙升,经常把车灯反射、树枝晃动当成人员。根本原因很简单:训练数据里白天场景占了绝大多数,晚上样本不够。查数据分布之后,我有两个处理手段。一是按时间段切换模型或预处理参数,白天用一套,晚上用另一套;二是把亮度、对比度、色温这些环境特征作为后处理输入,让lightgbm回归模型根据当前环境动态调整告警置信度阈值。后者效果更平滑,不会出现黄昏时刻陡然切换的跳变。
我建议所有做室外视觉项目的朋友,从第一天起就按“场景分桶”来管理数据,把白天、夜晚、逆光、雨天分开统计。不要等到上线被客户投诉才开始补,那就太被动了。
4.2 量化掉点与模型回归
有一次我们想进一步压缩延迟,把推理服务从FP16切到INT8,结果小目标检测掉得非常明显,漏检率直接翻了倍。这个问题最后定位到两个方面:一是校准集画面太单一,用的是白天园区主干道的抽帧,没有覆盖夜间场景;二是模型有几个层对量化特别敏感,量化后特征分布完全变了。解决办法是重建校准集,从线上连续采样24小时视频,按时段均匀抽帧,再结合逐层敏感度分析,把敏感的层留在FP16,最终精度回到了可接受范围,延迟比FP16又压低了将近三成。
模型升级回归也是常见事故。有一次我们更新了检测模型,本地测试精度比旧版高,但上线后客户反馈误报变多了。排查最后发现是因为新版模型对某类目标的召回提高了,但连带把以前能过滤的几个相似场景也判成了目标。所以现在我要求每次发布前跑一遍固定的回归测试集,这个集合包含最难的正样本和最容易混淆的负样本,数据一旦定下来就不轻易改。所有版本上线前自动跑,指标低于旧版的直接拦截,不允许发布。这个机制帮我挡掉过好几次事故,强烈推荐。
4.3 “模型繁忙”背后的系统设计
高峰期并发上来了,线上偶尔会出现“模型繁忙,请稍后重试”的提示。第一次看到这个我第一反应是模型推理太慢,加机器就行。后来一查才发现,问题出在推理服务缺少流量控制:请求全部直接打到GPU推理进程,显存被占满后新请求只能被强制拒绝。这个请求卡在排队阶段,前端等不到响应,就会给用户抛“模型繁忙”。根因不在模型,而在系统设计。
解决思路很简单:在推理服务前面加一层请求队列,设置最大排队长度和超时时间;队列满了先降级返回预设结果,而不是让请求一直占着连接;同时做多副本水平扩展,每副本限制并发数,整体吞吐靠副本数量解决。现在我做系统设计时,排队长度、超时率、丢弃率跟推理延迟一样,都是核心监控指标。一个人人都能调通demo的系统,和一个人人用了不骂的系统,差别就在这里。
4.4 鲁棒性与安全:不能等出事再补
平时聊视觉落地,很少有人提模型安全,但真实项目里这个风险是存在的。比如对抗样本,往画面上贴几张精心设计的图案,模型就会把目标识别错,这在安防场景里是真有可能被人利用的攻击方式。还有模型中毒攻击,训练数据被人污染,测试时看着正常,一旦遇到特定触发条件就输出错误结果。听起来像论文里的概念,但我们的训练数据来源杂、标注外包多,确实要警惕。
我的做法有三层:输入侧做异常检测,对画面的亮度突变、噪声异常发出告警;推理侧做多模型融合投票,单模型输出不可信时看其他模型是否一致;业务侧给所有结果加置信度下限,低于阈值的强制进入人工复核流程。另外,训练数据在入库前做一轮抽样审计,剔除明显异常标签。这些措施不复杂,但能在很大程度上避免“平时没事、出事就是大事”的局面。
5. 给想认真做视觉落地的朋友几点建议
5.1 先把评估体系定下来,再谈优化
我见过太多项目一上来就急着开训,连评估集都没有。结果就是模型改了一版又一版,谁都说自己的好,但没人能说清好在哪。正确的做法是动手之前先定义清楚:这个项目承诺给客户的指标是什么?线上怎么度量?哪种失败是不可接受的?评估集必须包含最典型、最困难、最容易出错的场景,而不是随机抽几张图。
有了固定评估集,后面所有优化才有依据。无论是调阈值、换模型、加后处理,都在同一把尺子上量,是骡子是马一目了然。这也是我每次项目启动会必讲的第一件事。
5.2 把模型放回系统工程里
模型只是感知模块,和数据系统、业务系统、运维系统的耦合才是落地难点。我粗略统计过,一个落地项目里,花在模型结构和训练上的时间通常不到三分之一,剩下的时间都在处理数据、部署、调试接口、和客户对需求。所以别只顾着把模型训得漂亮,要主动去学数据管道怎么搭、服务怎么部署、监控怎么配、和业务系统怎么对接。
带项目这两年,我最大的转变是:不再迷信单个模型的精度,而是追求整个系统的稳定产出。模型偶尔犯迷糊不可怕,可怕的是系统没有兜底机制,一个模型崩了全线跟着崩。
5.3 学习路线的重心转移
如果你是准备入行或者还在校的学生,计算机视觉学习路线也要相应调整。模型结构、损失函数、注意力机制这些当然要学,但别只停留在刷论文、复现代码的阶段。企业真正愿意高薪招的人,往往是能把模型跑起来、部署出去、还能解决现场问题的人。
建议找一个真实的项目从头到尾走一遍:从数据采集标注开始,到训练、量化、转引擎、容器化部署,再做监控和升级维护。这个端到端的经历比刷十篇论文都值钱。现在的工具链也比以前友好太多,TensorRT、ONNX Runtime、Docker、Ollama、GGUF这些部署方案都可以去玩一玩。技能树往工程方向伸一伸,你的竞争力会完全不一样。
我个人实际做下来的体会是,模型是你手里一张好牌,但牌桌上的规则是由数据、算力、业务和运维共同决定的。与其天天焦虑模型不够新,不如先把手里的系统跑稳。做视觉落地这几年,最值钱的经验没几个是从论文里学的,基本都是现场一遍遍试错试出来的。最后分享一个小技巧:每次项目收尾,花半天时间把所有阈值、版本号、数据集清单、接口文档整理归档,别觉得麻烦,后期维护的时候能帮你省出大把时间。