资讯动态

基于对象的视频伪造检测:从对象轨迹到细粒度审核实践

发布时间:2026/9/9 13:16:37 来源:尧图企业网站定制
简介面向视频伪造检测研究者与计算机视觉初学者的MATLAB实现资源聚焦视频中基于对象的伪造识别覆盖帧提取、特征提取、残差分析、集成分类器等完整检测流程。压缩包共65个文件以mat数据与模型文件、m源码脚本为主辅以sh批处理、c/mex扩展、PDF论文与项目报告并含演示视频与PPT整体约29.31MB。目录按代码、变量、文献、演示等模块组织便于对照学习。已有417人学习下载。通过资源包可掌握基于残差的视频伪造检测pipeline理解集成分类器如何结合多种模型提升泛化能力可运行demo.m复现实验也可基于现有特征与模型进行二次开发适合课程设计、科研入门及工程验证。 你手里有一段1080P的高清视频画面里的人、动作、光线都“看起来”很正常但这段视频其实是伪造的。这是这几年做内容安全审核时越来越常见的场景深度伪造工具门槛持续降低普通人也能生成以假乱真的换脸视频而对抗这类伪造的“视频伪造检测”技术也早已不是早期那种把整段视频丢进二分类模型就能解决的事情了。我最近在做的方向正是“基于对象的伪造检测”简单说就是不判断整段视频的真假而是先把视频里的关键对象——人脸、人体、车辆、证件等——逐帧定位出来、跨帧串联成轨迹再对每一条对象轨迹单独做真假判定输出“哪一帧、哪个区域、属于伪造”这种细粒度的结论。这篇文章就把这套检测思路、模型选型和完整落地流程梳理一遍适合正在做AI内容安全、风控审核、司法取证以及对deepfake检测感兴趣的读者参考。1. 先搞清楚基于对象的视频伪造检测到底在检测什么1.1 为什么“全局判断”不够用传统做法通常是把整段视频或者每隔几帧抽取的图像送进一个二分类网络直接输出“真/假”。这条路在伪造痕迹非常明显的简单场景下没问题但一旦遇到真实的伪造视频问题就暴露了大部分伪造操作只发生在局部区域比如只有人脸被替换背景、衣服、光影全是从原始视频里保留的。全局二分类模型会把大量正常画面和少量伪造区域混在一起做特征统计伪造信号被严重稀释最后的概率值往往偏向“真”导致漏检。项目标题里提到的“高级视频”这四个字恰恰是这个问题的高发场景。这里所谓的高级不是指分辨率有多高而是指视频经历了多次压缩、剪辑转码、局部修补、甚至多次上传下载等复杂处理。这些链路会把图像里的高频纹理和噪声分布搅得一团糟而早期检测模型非常依赖的频率域统计特征会大面积失效。换句话说视频越“高级”全局特征越不可靠。1.2 对象的时空轨迹才是更稳的分析单元基于对象的检测改变了分析粒度。先在同一帧画面里把目标对象用检测框框出来再通过跟踪算法把同一个对象在不同帧之间的位置串联起来形成一段对象时空轨迹。伪造检测就落在这条轨迹上而不是落在整段视频上。这个思路之所以有效有三个很直接的原因定位精确能明确指出哪一帧、哪一个对象是伪造的。实际业务里审核人员需要的是一个可以解释的结论而不是单纯一个“可疑”的概率值。特征聚焦伪造人脸在几十帧甚至几百帧内很难长期保持光照一致、生理信号合理、关键点运动平滑。把这些跨帧一致性特征放到一起对比造假痕迹会被放大。数据利用效率高一段包含几个人物的视频可以切出几十条对象轨迹样本比整段视频打一个标签的方式高效得多。当然对象级方案也不是万能。如果视频里的对象特别小、遮挡严重或者帧率极低跟踪本身就容易出错。这个问题后面会专门讲怎么处理。1.3 完整的检测管线长什么样我目前落地使用的管线大致分六个环节输入视频 → 对象检测 → 跨帧追踪 → 轨迹片段生成 → 特征提取 → 分类决策与后处理。如果用一句话概括就是“先锁定对象再审查对象”。前两步解决对象是谁、在哪里后两步解决对象是否被伪造。这条管线的最大优点是模块化任何一环落后了都可以单独替换不会牵一发动全身。对比维度全局二分类对象级检测检测粒度整帧/整段视频单个对象的时空轨迹可解释性弱只给一个分数强可定位到区域和帧局部伪造敏感度低容易被稀释高针对对象单独判断抗压缩能力较差依赖全局纹理较好可融合多种特征计算量相对低相对高但可工程优化部署复杂度简单较高需要检测追踪模块2. 核心细节模型怎么选、特征怎么提2.1 对象检测与追踪别在一开始就上大模型对象检测和追踪是整个管线的地基这里我踩过不少坑先说结论通用场景下检测器可以直接用YOLOv8或YOLOv9跟踪器用ByteTrack。YOLO系列虽然不算最新但工程化和部署生态非常成熟ultralytics的接口几行代码就能跑通。ByteTrack最大的优势在于对遮挡和短暂消失的处理比DeepSORT稳而且不依赖ReID网络不需要单独训练行人重识别模型省掉了大量调参时间。如果检测目标是人的脸建议把检测器换成SCRFD或RetinaFace这类专门做人脸检测的模型。原因很简单人脸检测和通用物体检测的anchor设计、感受野、样本分布差异都很大通用模型在侧面脸、遮挡脸、低分辨率小脸上会漏得比较厉害而这些人脸场景又是伪造检测最刚需的。检测场景推荐模型理由通用对象/行人/车辆YOLOv8 / YOLOv9训练生态成熟推理快部署方便人脸特写SCRFD / RetinaFace对姿态、遮挡、小脸召回率更高精细物体切片先用检测框抽取再做分类减少背景干扰特征更纯还有个细节很多人会忽略检测置信度阈值不要设太高。我通常设到0.3左右宁可多框出一些可疑候选项也不要漏掉真正的伪造区域。后面特征提取阶段会做二次筛选把候选框都喂进去并不会带来灾难性后果漏检才是更难补救的问题。2.2 伪造痕迹特征从三个维度去抓只靠单帧的CNN特征很容易被压缩和重编码干扰。所以我现在的工程方案里特征通常分三路提取第一路是空间痕迹。伪造区域和真实背景往往经过了不同的信号处理链比如人脸是被GAN网络生成后再贴回画面的那么贴回边界会留下“接缝”对象表面的传感器噪声分布也和原始背景不一致。PRNU传感器模式噪声一致性是一个经典思路实操中我会对对象区域和背景区域分别估计噪声残差计算它们的相关性分数伪造对象通常会出现明显的相关断裂。第二路是频域痕迹。自然图像经过JPEG等压缩后其DCT系数分布是有统计规律的而GAN生成的图像在部分中高频分量上会有不一样的特征。做法也不复杂把对象区域切成小块每个块做DCT变换统计高频系数能量、系数分布形状等这些手工特征配合后续分类器效果很好而且计算开销很小。第三路是时间痕迹。这是对象级检测独有的优势区间。真实人脸在自然说话时眨眼频率、眼球运动、头部的微小抖动都有一定的生理节奏伪造视频哪怕单帧画质再高连续几十帧看下来经常会出现关键点跳变、边界闪烁、眨眼频率异常、甚至嘴唇和音频不同步的现象。时间维度的特征对很多生成工具几乎就是死穴因为它们的生成过程往往逐帧或逐段进行很难保持全局运动一致性。2.3 分类决策特征工程还是端到端拿到对象轨迹和提取到的特征之后最后一步需要做真伪分类。我实际对比过两条路线特征工程 LightGBM训练速度快可解释性强小样本场景下也能稳定工作。把上一节提到的空间、频域、时间特征拼成一个向量喂给梯度提升树。这个方案特别适合业务冷启动因为不需要大规模GPU集群也不需要对每个新场景重新训练大模型。端到端视频Transformer或3D CNN潜力更大能自动从原始帧序列中学习篡改伪影但需要的数据量明显更大训练和推理成本也高。我的习惯是先用特征工程路线快速搭出基线拿到一个可以上线的版本同时积累badcase等数据量够了再考虑用端到端模型做第二版迭代。这样可以平衡时间成本和最终效果上限。实际项目里第一版特征工程模型往往就能满足大部分审核需求端到端模型更多是用来冲击更高指标。3. 实操过程从零搭一套对象级伪造检测系统3.1 环境与数据准备环境方面我用的是一套很常见的组合Python 3.10PyTorch 2.xultralytics提供YOLOv8检测能力ByteTrack做追踪OpenCV处理视频编解码LightGBM做特征分类。所有组件都可以用pip直接安装torch、torchvision深度学习基础ultralytics加载YOLO模型lap、scipyByteTrack依赖的线性分配与匈牙利匹配opencv-python视频读取、画框、裁剪lightgbm特征分类器数据集方面公开最常用的三个是FaceForensicsFF、DFDC和Celeb-DF。FF包含多种伪造方法DFDC规模大、场景杂Celeb-DF则在换脸上的质检比较严格。只拿其中一个数据集训练模型测试时性能会明显下降所以我的建议是至少混合两个数据集同时把不同压缩级别FF里的c0、c23、c40混着用。这其实就是在模拟“高级视频”经过多次压缩后高频痕迹被部分抹掉的真实情况。3.2 核心实现检测、追踪、提取特征先写一段对象检测与追踪的核心逻辑。思路是读取视频帧在首帧和后续帧中同时进行目标检测用ByteTrack把同一个对象串起来当一个对象的轨迹长度超过阈值时就把轨迹片段保存下来。import cv2 import numpy as np from ultralytics import YOLO from trackers.byte_tracker import BYTETracker # 初始化检测模型和跟踪器 detector YOLO(yolov8x.pt) # 按场景换成人脸检测模型 tracker BYTETracker(track_thresh0.3, match_thresh0.8) cap cv2.VideoCapture(sample.mp4) fps cap.get(cv2.CAP_PROP_FPS) tracks {} # track_id - {bboxes, frames, crops} frame_id 0 while True: ret, frame cap.read() if not ret: break # 检测 results detector(frame, classes[0], conf0.3, verboseFalse) # 人脸/行人按需改 detections [] for box in results[0].boxes: detections.append([ float(box.xyxy[0][0]), float(box.xyxy[0][1]), float(box.xyxy[0][2]), float(box.xyxy[0][3]), float(box.conf[0]) ]) # 追踪 online_targets tracker.update(np.array(detections), [frame.shape[0], frame.shape[1]], (frame.shape[0], frame.shape[1])) for t in online_targets: tid t.track_id bbox [t.tlwh[0], t.tlwh[1], t.tlwh[0] t.tlwh[2], t.tlwh[1] t.tlwh[3]] if tid not in tracks: tracks[tid] {bboxes: [], frames: [], crops: []} tracks[tid][bboxes].append(bbox) tracks[tid][frames].append(frame_id) tracks[tid][crops].append(frame[int(bbox[1]):int(bbox[3]), int(bbox[0]):int(bbox[2])]) frame_id 1 # 过滤长度足够的轨迹 min_len 30 valid_tracks {tid: v for tid, v in tracks.items() if len(v[frames]) min_len}这段代码里有两个关键参数检测置信度0.3和轨迹最少长度30帧。置信度设低是保证召回轨迹长度设阈值是防止一两帧的检测噪声干扰后续特征计算。具体阈值可以根据视频帧率调整10到30帧是比较合理的区间。下一步是特征提取。以一个对象轨迹的裁剪序列为输入计算三类特征并拼接成向量def extract_track_features(crops): feats [] for crop in crops: gray cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY) # 1. 分块DCT频域特征 h, w gray.shape dct_feat [] block 32 for y in range(0, h - block 1, block): for x in range(0, w - block 1, block): block_dct cv2.dct(np.float32(gray[y:yblock, x:xblock])) # 统计中高频系数能量 high_freq np.abs(block_dct[-8:, -8:]).mean() dct_feat.append(high_freq) feats.append(np.mean(dct_feat)) # 2. 简单噪声一致性用高通滤波估计噪声残差 noise cv2.Laplacian(gray, cv2.CV_64F).var() feats.append(noise) # 3. 时间一致性连续帧之间的L2距离均值与方差 diff [] for i in range(1, len(crops)): cur_gray cv2.cvtColor(crops[i], cv2.COLOR_BGR2GRAY) prev_gray cv2.cvtColor(crops[i-1], cv2.COLOR_BGR2GRAY) diff.append(np.linalg.norm(cur_gray - prev_gray) / (cur_gray.size)) feats.append(np.mean(diff)) feats.append(np.var(diff)) return np.array(feats, dtypenp.float32)这里展示的是最简特征集实际工程里我还会加入人脸关键点运动平滑度、光流一致性、甚至rPPG信号等特征。核心思路是一样的把“伪造会不会留下某种可计算的痕迹”翻译成对应的特征函数。3.3 训练分类器与推理后处理特征向量准备好之后标签怎么定义需要想清楚。我的做法是如果一条对象轨迹来自伪造视频或者该轨迹的对象区域确实被篡改过就标为1否则标为0。训练LightGBM模型import lightgbm as lgb from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test train_test_split(feature_matrix, labels, test_size0.2, random_state42) model lgb.LGBMClassifier( n_estimators500, learning_rate0.05, num_leaves63, subsample0.8, colsample_bytree0.8, ) model.fit( X_train, y_train, eval_set[(X_test, y_test)], eval_metricauc, callbacks[lgb.early_stopping(50)] )推理阶段不能只看单条轨迹的输出还要做后处理。我通常会在视频维度上做滑动平均把同一视频里所有对象轨迹的预测分数按时间窗口对齐然后做平滑得到每一帧的伪造概率。这样能有效减少单帧误检的毛刺视频级别的判定一般以平滑后的分数在窗口内超过阈值且持续若干帧为准。这里有一个非常值得强调的点训练和推理的输入粒度要保持一致。如果训练时用的是32帧以上的轨迹特征推理时就不应该用8帧的片段去做预测。我看到不少项目在这个细节上吃亏明明帧级模型效果不错上线后因为轨迹切短了特征统计不稳定整体指标掉了一大截。4. 常见问题与排查技巧实录4.1 高频问题速查表把我在项目里遇到最多的问题整理成一张表基本覆盖了从训练到上线的几个典型坑问题现象可能原因解决方案跨数据集测试性能骤降训练数据来源单一模型过拟合了特定压缩伪影混合多个公开数据集训练时叠加随机压缩/模糊增强高压缩视频频繁漏检高频纹理痕迹被转码抹掉增加低频和时序特征把判断重心从单帧转移到轨迹一致性跟踪把不同对象串在一起遮挡严重、交并比阈值设置过松调低ByteTrack的match_thresh缩短单条跟踪窗口推理速度太慢对每一帧都跑全图检测隔帧检测中间帧用运动补偿或者检测频率降到5-10 FPS伪造区域太小占比低分块粒度太大特征被大量正常像素稀释用分割或注意力先锁定疑似篡改区域再对该区域做细粒度检测部分伪造工具检测效果差训练集里没有覆盖这类生成方法定期补充新伪造方法的数据对真实badcase做增量训练4.2 几个独家避坑心得第一个坑是关于压缩率的。我最早在FF的c0质量上训练测试也跑c0AUC做到0.95以上自我感觉很好结果一放到c40超低压缩率的测试集上AUC直接掉到0.7以下。后来在训练阶段混合了c23和c40的数据同时加随机高斯模糊和重编码增强才恢复到0.9以上。这件事让我彻底明白对“高级视频”场景而言转码和压缩带来的domain gap比模型结构带来的收益更明显。第二个坑是不要迷信单帧判断。早期版本里我把检测结果做得非常“帧敏感”只要某一帧的伪造概率高就拉警报结果是误检率居高不下。后来强制加了一个约束单帧高概率只能标记为“待确认”必须连续几帧或者多条轨迹保持一致才会判为伪造。误检率立刻降下来真实漏检率并没有上升。第三个心得是关于轨迹长度的选择。轨迹太短特征估计的方差大不稳定轨迹太长一旦中途跟踪出错整段借来的数据都会有噪声。我实际试下来的经验值是25到35帧左右是一个比较稳的窗口既能覆盖足够多的变化又不会因为遮挡和跟丢而频繁失效。当然这个值需要结合具体视频的帧率来调25FPS的视频取1秒左右的轨迹逻辑上更合理。5. 检测能力的边界与后续扩展方向5.1 现有方案的明显短板基于对象的方案也不是银弹。跨界面对完全没有见过的生成模型时效果仍然会打折如果视频里出现多对象来回遮挡、快速运动模糊、画面大范围抖动对象追踪本身可能先失败后面的特征提取就无从谈起。另外低帧率或短视频场景下一条轨迹可能只有几帧特征严重不足这时候对象级方法还不如老老实实做单帧图像检测。还有一类对抗攻击需要提防在伪造视频上叠加微小的对抗噪声就能让深度学习模型把伪造画面误判为真实。这类噪声人眼几乎不可见但对特征统计的影响很明显。目前没有特别完美的解决方案只能靠增加训练数据的多样性、在推理阶段做输入预处理来缓解。5.2 可以继续扩展的方向一个很值得投入的方向是多模态一致性检测。伪造工具往往只处理视觉通道但音画一致性、口型同步、说话人身份特征这些跨模态信息很难同时伪造。把对象级视觉检测和音频特征结合起来能显著提升整体鲁棒性。另一个方向是为检测结果自动生成可解释报告。对象级检测天然有“哪个对象、哪一帧、哪个区域”的细粒度信息完全可以输出带有可视化热力图和文字描述的报告供审核人员和取证人员直接使用。这样既发挥了对象级方案的优势也解决了业务落地时“算法说假但说不清为什么假”的尴尬问题。目前我们已经在往这个方向走核心思路就是把轨迹级特征再送一层多模态模型自动生成疑似篡改区域的说明文字。我实际做这套系统最大的感受是伪造检测不是一个“一个模型打天下”的问题而应该是一套模块化的工程系统。对象检测与追踪是地基特征工程决定上限分类器选择决定落地成本后处理决定最终用户体验。尤其在做“高级视频”这种强压缩场景时数据层面的domain gap远比模型结构差异重要。最后再分享一个非常实用的小技巧在对象检测阶段把置信度阈值压到0.3左右绝大部分业务方听到这个建议的第一反应都是“你疯了会输出一堆垃圾框”但正是这些低置信度的候选框在后续特征筛选阶段经常能救回真正的伪造目标。我所有后续的调优都是在这个“宁多算不漏检”的基线之上展开的。如果你正准备搭自己的检测系统先把这条原则刻在脑子里能少踩很多坑。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价