☰
深度学习抽烟识别落地指南:小目标检测、时序判定与误报控制
2026/10/27 11:23:41 网站建设 项目流程

去年年底一个做园区安防的朋友找我,说他们那套"抽烟识别"在演示环境里效果漂亮得很,一上真实点位就崩。我问他崩成什么样,他说一天下来告警两百多条,能看的不到十条,保安干脆把告警开关关了。这个场景我太熟了——基于深度学习的抽烟识别几乎是所有做视频分析团队绕不开的入门题,同时也是踩坑率最高的题之一。它看起来只是"检测一下香烟"这么简单的事,真落地的时候你会发现,小目标、遮挡、相似动作、光照、隐私边界、告警密度,每一个都能把你按在地上摩擦。

这篇东西我想把它写透一点:这套系统到底在识别什么、数据怎么标、模型怎么选、参数怎么算、部署怎么调、上线后怎么把误报压下去,以及哪些坑是我自己踩过、不想让后来人再踩的。适合正在做这个方向的算法同学、准备接这类需求的工程团队,也适合只是想搞明白"为什么这东西总是误报"的产品和运维。不堆公式,尽量讲人话,但该算的地方一定给你把数算清楚。

1. 先把任务边界划清楚:你到底在识别什么

1.1 需求侧的真实诉求往往和"检测香烟"不是一回事

很多需求方嘴上说的是"帮我识别抽烟",实际上他想要的是"在这个区域里发现有人正在吸烟,并且给我一个可复核的短片段"。这两件事差距很大。前者是一个目标检测任务,输出一个框和置信度;后者是一个事件级的行为判定任务,输出的是"某人在某时间段内处于吸烟状态"这样一个结论,还要带上起止时间和证据截图。

这个区别决定了很多东西。如果只做检测,你交付的是一个每帧都可能抖动的框,业务侧拿去没法用;如果做事件判定,你需要引入时序聚合、状态机、去重和冷却窗口。我在项目里通常会把它们拆成三层:检测层负责找到人/头部和可能的香烟,判定层负责结合空间关系和时序给出"是否吸烟"的状态,业务层负责去重、冷却、截图、推送。三层分开的好处是每一层都能单独评估、单独优化,出问题的时候也容易定位到底是哪一层在捣鬼。

还有一个很现实的约束是告警密度。一个点位一天报五十条,运维就会把它当噪声处理;一天报三条且基本都对,大家才愿意看。所以在设计阶段就要把"每小时最多允许几条告警"作为一个输入参数反推阈值,而不是先训模型再拍脑袋定 0.5。这一点后面讲评估指标的时候我会展开。

1.2 "抽烟"这个动作的物理特征:细、小、慢、易混淆

从图像角度看,抽烟这个行为有几个很讨厌的物理属性,必须提前想清楚。

第一是细。香烟是一根直径 8 毫米左右、长度 8 厘米左右的柱状物。在一个 8 到 10 米距离的监控画面里,人的头部宽度可能只有 60 到 80 像素,按比例折算下来,香烟的长度大约 30 像素,但宽度只有 2 到 4 个像素。这意味着检测框在宽度方向上极其敏感,标注时多一个像素少一个像素,IoU 就掉一大截,模型学起来非常痛苦。相比之下,人脸、安全帽、反光衣这些目标的长宽比接近 1:1 或 1:2,标注容错率高得多。

第二是小。按上面的估算,香烟在 1080P 画面里占的面积可能只有几十个像素。一个标准的检测网络主干下采样 32 倍,到了最深的特征图上,这东西连一个像素都占不满,直接消失了。即使是用 stride 8 的浅层特征图,30×3 像素的目标也只剩下 4×1 不到的分辨率。这是抽烟识别最根本的技术难点,后面讲输入分辨率和切片推理都是为了解决它。

第三是动作本身很隐蔽但有规律。吸烟的核心动作是"手抬起—送到嘴边—停顿—放下",一个完整的吸烟周期大概 3 到 8 秒,中间有明确的停顿。这个节奏特征其实比香烟这个物体本身更可靠,因为它是一个时序模式,喝水、打电话虽然也抬手到嘴边,但停留时间和重复节奏不一样。这就是为什么我在方案里一定会加时序判定,纯单帧检测天生吃亏。

第四是混淆源特别多。电话贴耳、喝水、咬笔、摸下巴、戴口罩调整、吃东西、甚至有人手托下巴发呆,单帧看都和吸烟高度相似。你如果只看一帧,模型基本没有可能区分开。

1.3 三条技术路线的取舍:我为什么最后选了混合方案

在动手之前,摆在面前的大致有三条路。

纯目标检测路线:直接把"吸烟的人"或者"香烟"作为一个类别标出来训练。优点是链路短、推理快、实现简单;缺点是小目标召回上不去,标注一致性极差(同样一张图,两个标注员对"香烟那个框该框哪"的理解可能完全不同),而且模型很容易退化成"看到手靠近脸就框"。

人体检测 + 头部 ROI 分类路线:先用一个成熟的人体检测器框出人,再根据人体框估算头部区域,裁出来送进一个二分类网络判断"是否在吸烟"。优点是分类网络可以吃更高分辨率的头部图像,绕开了小目标问题;缺点是 ROI 裁剪依赖人体框质量,人一多、一遮挡,头部位置就估不准,而且分类器丢掉了香烟的空间信息。

检测 + 关键点 + 时序的混合路线:人体/头部检测提供候选区域,头部 ROI 分类给出初步判断,手部关键点或香烟检测提供空间佐证,最后用时序窗口平滑和过滤。优点是准确率和误报控制都最好;缺点是链路长、算力开销大、工程复杂度高。

我最后选的是第三条的简化版:人体检测 + 头部 ROI 分类 + 轻量香烟检测辅助 + 时序投票。理由是实测算过账——纯检测路线在我手上的数据集里,帧级召回卡在 0.62 上不去,头部 ROI 分类能到 0.85 左右,加上时序之后事件级召回能到 0.9。这个提升对业务方来说是"能不能用"的分界线。算力上多出来的那点开销,在现在的边缘设备上完全扛得住,后面部署那一节我会给出具体的数字。

2. 数据工程:八成的时间花在这里,也八成的问题出在这里

2.1 采集环节的现实约束比想象中麻烦

真正开始做的时候,第一个拦路虎不是模型,是拿不到数据。做抽烟识别,公开数据集几乎没有能直接用的,勉强找到的几份要么场景单一(都是近距离正面半身照),要么标注口径和你需要的完全不一致。所以基本只能自己采。

采集阶段有几个坑我建议你提前规避。

第一,不要只用"摆拍"数据。找几个同事在摄像头前面举着烟演一遍,采出来的数据分布和真实场景差距巨大:真人吸烟的时候身体姿态是随意的,手的位置、头部角度、烟叼在嘴里的方式千变万化,摆拍数据里这些多样性几乎为零,模型训出来在真实现场会非常脆。

第二,负样本的重要性被严重低估。大多数人一开始只想着"我要收集吸烟的样本",结果正负样本比例做到 1:1 甚至正样本更多。真实场景里吸烟是极低频事件,一个点位一天可能就那么十几分钟,其余二十多个小时全是"不吸烟"。如果你训练时正负比接近 1:1,那模型学到的先验就是"画面里大概率有人在抽烟",上线后必然大面积误报。我的经验是把正负比控制在1:5 到 1:10之间,负样本里专门塞进大量"困难负样本"。

第三,困难负样本要定向采集。什么是困难负样本?喝水、打电话、托腮、吃饭、咬吸管、修东西、整理口罩、有人拿着细长物体(笔、螺丝刀、温度计)靠近嘴部。这些样本如果不主动去采,模型在真实场景里就会疯狂误报。我的做法是先把模型跑一轮上线,把误报的片段全部捞回来,人工筛一遍,专门做成一版"困难负样本集"再训第二版。第二版和第一版比,误报率通常能下降一个量级以上,这个性价比比调模型结构高得多。

2.2 标注口径:一场必须提前开完的会

标注这件事,我在项目里吃过的最大的亏就是"没提前把口径写死"。最早的一版,我让标注同学标"香烟",结果三个人标出了三种风格:有人只标露在嘴外面的那一截,有人把手指夹着的那一段也框进去,有人连烟雾都框——你自己想想这三类框混在一起,模型能学出什么。

后来我定了一套硬规则,写进标注文档里,每次标注前对照执行:

标注对象定义操作要求
person完整人体可见部分遮挡超过 60% 不标,边缘截断的人标可见部分
head从头顶到下巴的头部区域侧脸、低头、戴口罩都要标,允许包含部分颈部
smoking正在吸烟的人框住整个人,判定依据是"烟在嘴部或手中且处于吸烟姿态"
hard_negative疑似但非吸烟的行为单独给标签,不参与正样本训练,用于负样本池

这里有个关键决策:"吸烟"这个状态到底标在人身上还是标在烟上。我强烈建议标在人身上(用一个属性或者独立类别),因为香烟这个框太不可靠。标注规则里明确写"当香烟不可辨识但姿态明确(手在嘴边停留超过 1 秒)时,仍然标注 smoking",这样标注一致性会好很多,模型也更关注整体姿态而不是那根几像素的细线。

另外提醒一句,标注一致性一定要做抽检。我一般会让一个质检同学随机抽 10%,重新标一遍,和原标注做 IoU 对比,低于某个阈值的框打回去重标。这个动作看着费事,但它能省掉后面几周的模型调参时间——很多"模型学不动"的根因其实就是标注噪声。

2.3 数据增强:小目标场景下要针对性设计

通用增强(随机翻转、HSV 扰动、随机缩放、Mosaic)该开还是要开,但抽烟识别有几个需要专门处理的地方。

小目标复制粘贴。这是我个人觉得最有效的一招。做法是把标注好的香烟区域(连同周围一小块背景)裁出来,随机缩放、旋转,粘贴到其他图像的嘴部或手部区域,生成带标注的新样本。这样做的好处是人为提高了小目标的出现频次和尺度多样性,模型对细小目标的敏感度会明显提升。代价是粘贴痕迹可能引入伪影,所以缩放比例和位置要控制,别贴到天上或者大腿上。

尺度抖动要更狠。因为这个任务的核心难点是目标特别小,训练时输入的尺度分布必须覆盖到真实场景里最远的那一档。我会在增强里加入较大的缩小比例(比如 0.5 倍),让模型在训练阶段就见过"很小的人头 + 更小的香烟"这种情况。

低照度和逆光。真实点位里夜间的画面和白天完全是两个分布。如果点位有红外补光,那画面是灰度图,色彩信息全丢,原本靠颜色区分香烟(白色烟身、橙色烟头)的策略直接失效。这时候要靠形状和姿态。所以我建议在训练集里主动混入灰度化的样本,让模型不要过度依赖颜色通道。

运动模糊。25 帧的视频里,快速抬手的那几帧模糊很严重。适度的运动模糊增强能让模型在动态片段上更稳。

2.4 数据集划分:按帧随机切分会让你自我感觉良好

这一条我要单独拎出来说,因为它是新手最容易犯、后果最隐蔽的错误。

如果你把采集到的所有帧打散了随机划分训练集和验证集,那么同一个视频片段里相邻的两帧很可能一帧在训练集、一帧在验证集。这两帧的画面几乎一模一样,模型在训练时见过前一张,验证时自然"认得"后一张,mAP 蹭蹭往上涨,你以为模型很强,上线后一塌糊涂。

正确的做法是按视频源/按人/按时间段划分。同一段连续视频、同一个人、同一个点位,只能出现在一个集合里。如果条件允许,最好再留一个"完全没见过的点位"作为测试集,用来评估跨场景泛化能力。我在项目里通常这么分:训练集 70%(覆盖多个点位、多个时间段)、验证集 15%(不同点位)、测试集 15%(全新点位 + 全新人员),这样出来的数字才可信。

3. 模型与训练:结构选型背后的账要算明白

3.1 骨干网络和检测框架怎么挑

检测框架这块,YOLO 系列在这个任务上性价比最高,没必要上两阶段的方法。原因很直接:抽烟识别是个高频推理任务,一个点位 25 帧,几十上百个点位,推理成本是第一约束;而两阶段方法多出来的那点精度,在面对香烟这种 2 到 4 像素宽的目标时基本体现不出来,因为限制精度的是分辨率,不是网络结构。

具体到版本,我一般会在 YOLOv8n/s 和 YOLOv5s 之间选。n 版本胜在快,适合边缘盒子多路并发;s 版本精度更稳一点,适合服务器集中推理。如果是国产边缘芯片(比如带 NPU 的那类),我会优先选算子支持最完整的版本,避免某些自定义算子在量化时出问题——这个坑后面部署那节细说。

分类网络那一路,头部 ROI 的输入一般是 96×96 或 128×128,用 MobileNetV3-Small 或者更轻的自研小网络就够了。这里不需要太强的骨干,因为输入本身就很小,太深的网络反而过拟合。我实测过 ResNet18 和 MobileNetV3-Small 在这个任务上的差距,事件级指标几乎打平,但后者推理耗时只有前者的三分之一,选它没跑。

3.2 输入分辨率这个参数,必须算着定

这是整个项目里最需要"算"的参数,我把它单独拿出来讲。

假设你的点位是常见的高清枪机,输出 1920×1080。一个人站在离摄像头 10 米的位置,视场角横向覆盖大约 8 米,那么画面横向 1920 像素对应 8 米,也就是 240 像素/米。人的头部宽度约 15 厘米,在画面里就是 36 像素。香烟长度 8 厘米,约 19 像素,宽度 1 厘米,约 2.4 像素。

现在如果你把输入缩放到 640×640,横向缩放比例是 640/1920 ≈ 0.333,那么香烟的宽度就变成了0.8 像素。这个尺寸在任何特征图上都是一个点甚至不存在,检测网络不可能定位它。

如果你把输入提高到 1280×1280(实际用 letterbox 会变成 1280×736),缩放比例约 0.667,香烟宽度变成 1.6 像素。还是很勉强,但至少在最浅层的特征图上有信息了。

所以我的结论是:如果业务场景里人距离摄像头的距离超过 8 米,640 的输入分辨率基本没戏,必须上 960 或者 1280,或者用切片推理。这个账一定要在方案阶段就算清楚,别等训完发现召回上不去再回头改输入尺寸,那样数据增强策略、锚框、训练时长全得重来。

切片推理是另一个思路:把 1920×1080 的画面切成 3×2 共 6 块,每块 640×540,各自缩放到 640×640 推理。这样等效分辨率提高了大约 3 倍,香烟宽度从 0.8 像素变成 2.4 像素。代价是推理耗时接近线性增长 6 倍,还要处理跨块的框合并问题。我的经验是:如果 GPU 资源够,切片推理比单纯提高输入分辨率的性价比更高,因为大分辨率输入下,画面里绝大部分区域是空的,算力浪费严重。

3.3 训练超参和损失的那些实操设置

具体数值给你一套可以抄的起步配置(基于 YOLOv8s,1280 输入,单卡 24G):

  • batch size:8(1280 输入下显存吃得凶,再大就 OOM 了,用梯度累积凑到等效 32)
  • 初始学习率:0.01,warmup 3 个 epoch,余弦退火到 0.0001
  • 训练轮数:150 到 200,通常 120 轮左右验证集指标就平了,多跑没用
  • 权重衰减:0.0005
  • 优化器:SGD 动量 0.937(AdamW 在这个任务上我没跑出更好的结果,反而收敛不稳)
  • 正负样本分配:用 TaskAligned 那套,对小目标友好一些

关于类别不平衡,我的做法不是简单调 loss 权重,而是保证一个 batch 里至少有一半是包含吸烟样本的图像。这样梯度的方向不会长期偏向负样本,模型不会退化成"全预测背景"。这个技巧比调 cls_pw 参数直观得多。

训练过程中我会重点盯三个指标,不是只看 mAP:

  1. 小目标的召回分档:把验证集按目标像素面积分成几档(小于 100 像素、100 到 400、大于 400),分别看召回。如果小目标那一档明显塌了,说明输入分辨率或者数据增强有问题,先别动模型结构。
  2. 困难负样本上的误报率:单独建一个困难负样本测试集,看模型在这上面的误报。这个指标比整体 precision 更能反映上线后的表现。
  3. loss 分项:box loss 和 cls loss 的比值。如果 box loss 一直很高降不下去,八成是标注框不一致;如果 cls loss 卡住,多半是正负样本太像,需要加强负样本。

3.4 头部 ROI 分类器怎么训才不容易过拟合

分类这一路的输入是裁剪出来的头部区域,尺寸小、信息少,特别容易过拟合。我踩过的坑是:训练集 3 万张,验证集准确率 0.98,上线后惨不忍睹。后来发现原因还是划分泄漏——同一段视频的相邻帧被分到了两边。

解决办法除了前面说的按视频划分,还有几个细节:

裁剪时留足够上下文。如果只裁脸部,模型看不到手,而手的位置恰恰是最强的判别特征。我一般会按头部框向外扩 1.5 到 1.8 倍,保证手抬到嘴边的时候能进画面。这个扩边比例要试,扩太小手进不来,扩太大背景噪声多。

不要用太强的正则。Dropout 开到 0.5、标签平滑 0.2 这种配置在这个任务上会让模型学得很保守,召回上不去。我的经验是 dropout 0.2 到 0.3,标签平滑 0.05 就够。

加入手部区域的辅助监督。如果标注里有手部关键点,可以让分类网络额外预测一个"手是否在嘴部附近"的辅助任务,多任务学习能明显提升泛化。没有关键点标注的话,用现成的手部检测器生成伪标签也行,虽然噪声大一点,但作为辅助任务够用。

4. 从模型到服务:部署阶段的坑一点不比训练少

4.1 推理引擎和硬件匹配的实际考量

如果是服务器集中推理,TensorRT 基本是必选项。YOLOv8s 在 1280 输入下,TensorRT FP16 在一张主流推理卡上跑单 batch 能到 60 帧上下,配合切片推理(6 块)大概 10 帧。这意味着一个点位如果按 5 帧/秒抽帧,一张卡能带两路。这个数字一定要提前算,不然方案报出去成本会很难看。

如果是边缘盒子,情况复杂一些。这里我要提醒一个特别容易踩的坑:量化校准集必须来自真实场景。用 COCO 的图片去做 INT8 校准,出来的模型在监控画面上会掉得很厉害,因为监控画面的动态范围、噪声特性、色彩分布和自然图像完全不同。我一般会从实际点位里抽 500 到 1000 帧做校准,量化后精度损失能控制在 1 个点以内。

还有一个是前后处理的一致性。这个坑太经典了:训练时用的是 OpenCV 读图(BGR)、双线性插值 letterbox、像素归一化到 0 到 1;部署时用的是某推理框架自带的预处理(RGB)、最近邻插值、还忘了做归一化。结果就是模型输出完全乱掉,但你在本地测试又一切正常。我现在的做法是把预处理封装成一个独立模块,训练和推理共用同一份代码,中间只换 tensor 的来源。这个改动看着小,能省掉无数排查时间。

4.2 后处理和业务逻辑层:真正决定体验的地方

模型输出只是一堆框,业务方要的是一个能看的事件。这中间的转换逻辑,我觉得比模型本身更值得打磨。

空间关系判定:检测到 head 框和 smoking 状态的框之后,要做关联。我的规则是中心点在 head 框扩展 1.5 倍范围内、且面积比在合理区间,才算同一个人。这样可以避免画面里人多的时候张冠李戴。

置信度阈值不要拍脑袋:正确做法是在验证集上画出不同阈值下的 FP 和 TP 曲线,然后根据"每小时允许几条误报"反推。比如目标是单点位每小时不超过 0.5 条误报,那就找到那个阈值点,接受对应的召回损失。

冷却窗口:同一个人连续吸烟,不应该报十次。我的做法是同一个人(用简单的 IoU 跟踪或者位置匹配)在 5 分钟内只报一次,除非中间有明显的长时间中断。这个小逻辑能把告警量压掉 70% 以上,而且完全不损失有效信息。

截图策略:不要只截触发那一帧,要截触发前 3 秒到触发后 2 秒的连续几帧,最好拼成一张图。运维人员看单帧经常判断不了,看连续帧一眼就明白。这个细节对系统的可接受度影响特别大。

4.3 时序过滤:把误报再砍一半的那一刀

单帧判定做完之后,还有一道工序是时序投票。我的配置是这样的:

先按 5 帧/秒抽帧,维护一个长度为 2 秒(10 帧)的滑动窗口。窗口内如果超过 7 帧被判为吸烟状态,才认为是真事件。这个阈值是可以调的,7/10 相对严格,适合误报敏感的场景;如果更看重召回,可以放宽到 5/10。

这里有个技巧:不要用简单的多数投票,要用加权。靠近窗口中心的帧权重高,边缘的低。因为事件的开始和结束两端,模型状态本来就在跳变,参考价值低。加权之后,同一个阈值下的召回和精度都能好一点。

另外补充一个我觉得很管用的细节——动作节奏校验。真正的吸烟有时间结构:手抬起、停顿、放下,这个周期会重复。如果检测到一段连续 10 秒里手一直在嘴边没动过(比如有人托腮思考),那大概率不是吸烟。加一个简单的"停顿时间不超过 X 秒"的约束,能过滤掉相当一部分静态误报。

5. 上线之后:问题排查实录和速查表

5.1 误报漏报的典型场景速查

这套东西跑了几个点位之后,我整理了一张对照表,基本覆盖了九成的问题:

现象最可能的原因处理方式
喝水、打电话大量误报困难负样本不足定向采集负样本,正负比调到 1:8 以上
远处的人全部漏检输入分辨率不够提高输入尺寸或启用切片推理
白天正常,夜间全漏红外画面色彩丢失,训练集无灰度样本训练集混入灰度化增强,或用近红外数据补训
侧脸、低头时漏检head 标注口径不一致补标侧脸低头样本,检查标注规范
训练 loss 降但验证指标不涨数据划分泄漏改为按视频源/按人划分
本地测试正常,部署后全乱预处理不一致训练和推理共用同一份预处理代码
量化后精度掉很多校准集与真实分布不符用真实点位画面做校准
告警量爆炸没有冷却窗口加同类事件 5 分钟去重
同一人反复告警缺少目标跟踪加简单的 IoU 跟踪做身份关联

5.2 几个我自己踩过的具体坑

坑一:标注框宽了一个像素,IoU 掉一半。前面说过香烟宽度只有 2 到 4 像素,标注时手一抖,宽度从 3 变成 4,IoU 直接掉到 0.75 以下,而很多框架的匹配阈值是 0.5,勉强还能过,但训练信号会变得很不稳定。我的应对是:在标注工具里对这个类别设置最小框宽提示,同时把 GIoU 换成对宽高不敏感的损失变体,减少模型对那一个像素的执念。

坑二:把"吸烟的人"和"香烟"标成两个类别,结果两个都学不好。早期版本我贪心,同时标了 person_smoking 和 cigarette 两类。结果模型在香烟那一类上几乎学不到东西,还拉低了主类的表现。后来我把香烟类别砍掉,改成只标人 + 一个属性位,效果立刻好转。类别的数量不是越多越好,标注一致性才是第一位的。

坑三:验证集指标漂亮,上线后崩,原因是负样本太"干净"。我早期的负样本全是从"确认无人吸烟"的时段里随机抽的,画面干干净净没人。而真实误报往往发生在"有人但没抽烟"的场景。补了这类样本之后,模型才真正学会区分。

坑四:地址冲突——推理服务的帧率被 NMS 卡住了。我一开始没在意,后来发现 GPU 利用率只有 40%,瓶颈在 CPU 上做的后处理 NMS。把 NMS 移到 GPU 上、并且限制每帧最大检测数(比如 100)之后,吞吐直接翻倍。这个优化不涉及任何模型改动,纯属工程侧白捡的性能。

5.3 评估指标怎么定,才不至于骗自己

这一条我想多啰嗦几句,因为我见过太多团队在指标上自欺欺人。

帧级 mAP 只是中间指标,不能作为验收标准。mAP 高不代表系统好用,因为业务关心的是"事件"而不是"帧"。一段 5 秒的吸烟,报出 3 秒和报出 5 秒,对运维来说差别不大,但对帧级指标影响很大。

我建议的验收指标是三个:

  1. 事件级召回:测试集里真实吸烟事件,被系统报出来的比例。目标定在 0.85 以上。
  2. 每小时误报数(FP/hour):单路视频每小时的误报条数。这个指标最贴近运维体验,目标定在 0.5 以下。
  3. 平均响应延迟:从吸烟动作开始到系统出告警的时间。控制在 3 秒以内,太慢了没意义。

另外强烈建议做跨点位测试。在 A 点位训练的模型,拿到 B 点位(不同品牌相机、不同安装角度、不同光照)上去测,指标通常会掉 10 到 20 个点。这个数字才是你方案能不能规模复制的真实答案。如果掉得太多,考虑加一点目标域的数据做微调,或者干脆上域自适应。

6. 绕不开的边界问题:隐私和结果定位

6.1 数据治理这条线要提前画好

做人体相关的视觉分析,数据治理是必须提前设计进去的,不能等出事再补。我在项目里的做法是几条硬规则:

不采集可识别的生物特征信息。头部 ROI 裁剪时,把分辨率控制在一个刚好够判定的水平(比如 128×128 以内),不做人脸识别、不做身份关联、不存原始高清视频。系统只输出"某区域某时刻存在吸烟行为"这样一个事件,附带低分辨率的证据截图。

优先边缘侧处理。能在摄像头端或者边缘盒子上算完的,就不要把视频流传回中心。原始视频不出本地,只有事件片段和结构化数据上行,这样即便链路出问题,泄露面也很小。这一条在方案评审时也更容易被接受。

留存期限明确。事件截图存多久,要有明确约定,比如 30 天自动清理。不要无限期堆积。

访问权限收敛。谁能在系统里看到这些截图,要有日志。这不是技术问题,是管理问题,但技术上要提供这个能力。

6.2 识别结果的定位:辅助提示,不是判据

这一点我在所有交付文档里都会写清楚:系统输出的是"疑似"提示,作用是引导人去复核,而不是自动做出任何处置。

原因很实际——当前技术水平下,这个任务的误报率不可能做到零。哪怕你把 FP/hour 压到 0.1,一天下来一个点位还是会有一两条误报。如果把系统的输出直接当成事实依据去做处置,一旦报错,造成的麻烦远大于系统带来的价值。

所以我在设计上会做几件事:所有事件都带"置信度"和"证据片段",让人能快速判断;系统里明确标注"AI 辅助提示"字样;不提供任何自动化处置接口。这套定位既降低了系统的风险,也让运维更愿意用——因为他们知道这东西是帮他们省事的,不是来给他们添麻烦的。

7. 我个人觉得最值钱的几个经验

写完上面这些,再补几句零散的、但我觉得对实际做项目帮助最大的体会。

第一,先跑通链路再优化模型。我见过太多团队在模型上死磕两个月,结果整条链路根本没跑通过。正确的顺序是:用最粗糙的模型把"视频接入—抽帧—推理—时序—告警—界面"全链路跑通,看看端到端体验是什么样,然后再回头优化最短板的那一环。很多时候你会发现,瓶颈根本不在模型上,而在抽帧策略、告警去重或者截图时机上。

第二,别迷信大模型。这个任务的输入信息量本身就有限,香烟就那么几像素,你把骨干从 s 换到 x,指标可能只涨 1 个点,算力翻三倍。真正带来提升的是数据质量、输入分辨率和时序逻辑这三件事。我做过对比实验,同样的数据下,"YOLOv8s + 切片 + 时序"的配置,事件级指标明显好过"YOLOv8x + 单次前向"。

第三,把每一个阈值都做成可配置的。置信度阈值、时序投票比例、冷却时间、ROI 区域,全部走配置文件。因为不同点位的场景差异太大了,一套固定参数不可能通吃。工程上多花半天做配置化,运维阶段能省掉无数次重新打包发版。

第四,留一个"误报回捞"的通道。让运维能在界面上点一下"这是误报",把对应片段自动归档到一个专门的目录。这些数据积累起来,就是你下一版模型最好的训练素材。我负责的项目里,这个通道上线三个月捞回来的困难负样本,比我前面半年手动采集的还多,而且分布更贴近真实。

最后说个具体的参数经验:如果你现在正卡在召回上不去,先别急着改模型,把输入分辨率从 640 提到 960 试试,同时把正负样本比从 1:2 调整到 1:8,这两步做完,大概率能给你带来 10 个点以上的提升。这两个改动成本极低,但收益往往比换模型结构高得多。

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

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

立即咨询