ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

视频异常检测三大经典数据集深度对比与实战指南

视频异常检测三大经典数据集深度对比与实战指南 做视频异常检测这行绕不开一个现实算法千千万但能在公开论文里横向比较的数来数去还是那几个数据集。UCSD Ped2、CUHK Avenue、Street Scene这三个名字你大概率已经在无数实验表格里见过它们也是这个方向绝大多数论文的“标配”跑分对象。我一开始也以为数据集不过是把视频和标注打包好真正动手跑实验才知道不同数据集的场景设定、异常形态、标注粒度、评估协议差别非常大直接影响你的模型能学到什么、指标能刷多高。这篇内容就从实际使用角度把几个经典基准拆开讲重点对比 Ped2、Avenue 和 Street Scene顺便放在“五大经典数据集”这个框架里看清楚各自的位置。内容包括数据集的构成、异常标注方式、评估指标的坑以及一段可以基于 PyTorch 直接改用的数据加载和评估代码。无论你是刚开始做异常检测还是准备写论文实验章节这篇都能帮你在数据集选型和结果汇报上少走弯路。1. 先搞清楚视频异常检测到底在检测什么视频异常检测通俗说就是让模型只看正常视频训练完后再去判别测试视频里有没有偏离常态的动作或物体。这里“偏离常态”不是一个固定类别而是相对于场景上下文而言的。校园步行道上行人正常行走是常态突然出现自行车、滑板、推婴儿车的人就算异常但换到一条繁华商业街这些可能又变成正常。这正是视频异常检测区别于常规目标检测、动作识别的地方它没有一个预先定义好的封闭类别集合所有“没见过”或“不符合规律”的情况都要被捕捉到。这种设定让数据集的选择变得异常重要。因为异常是开放式的训练数据里正常模式的覆盖程度基本决定了模型的上限测试数据里异常的类型和难度则决定了指标能不能真实反映泛化能力。我见过不少人拿自己采集的视频跑得很欢换到公开数据集上立刻露馅多数时候不是模型问题而是数据形态差异太大。这也是为什么社区里最后沉淀下来的始终是那几套公认的基准数据。这篇文章不打算罗列论文公式而是从“动手跑实验”的角度来看问题。我会先给视频异常检测领域最常用的五个数据集做一个全景盘点然后集中拆解 UCSD Ped2、CUHK Avenue、Street Scene 这三个被引用最多、也最适合做对比的基准最后分享一段可以直接落地的数据加载和评估代码。想做异常检测实验或者准备写论文实验章节的朋友这篇应该能帮你省下不少踩坑时间。2. 视频异常检测五大经典数据集全景纵览在细聊之前先列一张总表把“五大”放在一起看。这里我按照领域内最常见的划分列出 UCSD Ped1、UCSD Ped2、CUHK Avenue、ShanghaiTech Campus 和 Street Scene 五个。前四个是过去十来年的主力基准第五个是更贴近真实监控场景的新一代数据集。数据集发布方与年份分辨率训练/测试视频数标注粒度主要异常类型特点与难点UCSD Ped1UCSD / 2010238×158 灰度34 / 36帧级 部分框级自行车、滑板、推车、横穿马路人群密度大、视角固定但分辨率低、帧数少UCSD Ped2UCSD / 2010360×24016 / 12帧级 框级自行车、滑板、小型车辆等场景单一、背景稳定最适合快速验证CUHK Avenue香港中文大学 / 2013640×36016 / 21帧级 像素级奔跑、扔包、骑自行车、扔纸等目标尺度变化大像素级标注完整ShanghaiTech Campus上海科技大学 / 2018约 856×480330 / 107帧级 部分框级追逐、打架、盗窃、摔倒、闯入场景数量多、光照复杂目前使用最广Street Scene亚利桑那州立大学 / 20201280×72046 / 35帧级 像素级违规横穿、骑车、滑板、动物出没、非法停车真实街景背景杂乱遮挡和小目标严重这张表有两层意思。第一层是看数据集的演进从早期干净、低分辨率的校园单场景慢慢走向多场景、多异常类型和真实街景从简单背景逐步过渡到复杂遮挡和光照变化。第二层是看算法选型如果算法刚写好想几分钟内看出收敛情况Ped2 是最快的如果要做消融实验需要更丰富的信息来区分模型能力Avenue 和 Street Scene 更合适如果论文需要“更全面”的说服力那就把 ShanghaiTech 也补上。至于很多人常问的第一个问题为什么我推荐重点对比 Ped2而不是 Ped1原因是 Ped1 虽然同样经典但分辨率和帧率都比较低人群密度分布差异大部分片段还是灰度图像很多依赖纹理细节的模型在它上面表现不稳定。Ped2 是同一系列的修正和补充分辨率更高、场景更稳定实验可复现性更好因此在近几年的论文里出场率明显更高。这也是我把 Ped2、Avenue、Street Scene 三者拿出来专门比对的原因。3. UCSD Ped2最适合快速跑通的入门基准3.1 数据构成与标注规范UCSD 系列数据集来自加州大学圣迭戈分校校园内的步行道俯瞰视角画面主要内容是来回走动的行人。Ped2 给出了 16 个训练视频和 12 个测试视频分辨率 360×240帧率约 10fps。正常模式下只有行人在人行道上行走异常主要是一些非行人目标或异常运动方式闯入画面比如骑自行车、踩滑板、推婴儿车、滑旱冰以及行人横穿马路等。标注方面Ped2 提供了帧级标注和部分边界框标注。帧级标注解决的是“这一帧到底有没有异常”边界框则标出异常目标的位置。绝大多数算法在 Ped2 上只使用帧级分数做评估也就是把每一帧算出一个异常分数然后画 ROC 曲线计算 AUC 和 EER。这里有一点容易忽略Ped2 的测试总体量很小总共只有几千帧正常与异常帧分布不太均衡所以单次实验的随机性比较大连续跑几次出现一两个点的波动完全是正常现象。我个人的习惯是把 Ped2 当作“冒烟测试”。每次写完一个新模型先用 Ped2 快速跑一版看整体 AUC 是否正常、训练 loss 有没有下降、异常分数分布是否符合预期。因为它场景固定、背景基本不动许多问题会暴露得很快比如重建类模型很容易出现“所有帧都重建得很好、分数没有区分度”的情况在 Ped2 上一眼就能看出来。3.2 常用评估指标AUC 与 EER 怎么算视频异常检测里的 AUC全称是 Receiver Operating Characteristic Curve 下的面积。计算方法是给测试集中每一帧打一个异常分数然后遍历所有可能的阈值计算每个阈值下的真正例率和假正例率最后对整条 ROC 曲线求面积。AUC 越接近 1说明模型把异常帧排在正常帧前面的能力越强。AUC 的一个好处是它不依赖固定阈值对正常帧和异常帧比例不是特别敏感适合训练集多为正常样本、测试集带有部分异常样本的场景。EEREqual Error Rate则是让假正例率和假负例率相等时的错误率数值越低越好。在 Ped2 上我通常会同时保留 AUC 和 EERAUC 看整体排序能力EER 看实际部署时选阈值的一个参考点。两者结合起来比单独报告一个指标要靠谱得多。现在的公开成绩方面Ped2 的帧级 AUC 已经卷得很高主流记忆增强类、流模型和基于重建的方法普遍在 95% 以上不少论文报到了 97% 到 98%。如果你在 Ped2 上只跑到 90% 左右先别急着怀疑模型很有可能是数据处理或评估脚本出了问题。需要注意的是指标高不代表问题解决Ped2 场景内容单一、异常类别也有限很多模型靠背景不变的特征就能刷出不错的分数这并不代表它在真实场景里能用。3.3 我的实操体会Ped2 容易犯的三个错误第一个错误是训练时把测试集也塞进去。Ped2 提供的是整个数据集的文件很多新手会为了“多跑点数据”把测试集中的正常片段也放进训练集导致训练阶段已经见过测试帧的上下文测试分数虚高。这是严重的数据泄漏论文审稿人一旦发现会非常敏感。正确做法是严格只用官方划分的 16 个训练视频。第二个错误是忽略了帧级标注与像素级标注的区别。如果你下载的是完整版 UCSD 数据包会发现测试集目录里既有原始帧目录也有以_gt结尾的标注目录。前者包含异常目标像素级 mask后者则是帧级的 0/1 标注。帧级评估直接读取标注文件里的值就行不要把像素级 mask 简单求和当作帧级分数去算否则结果会偏。第三个错误是缩放过猛。Ped2 分辨率只有 360×240为了加速训练不少人直接缩到 128×128 甚至更小很多小尺度的滑板、自行车很容易丢失模型性能会明显下降。4. CUHK Avenue更复杂的场景与异常行为4.1 场景设置与数据规模Avenue 数据集由香港中文大学发布拍摄场景是校园大道。和 Ped2 最大的不同是视角更宽画面中行人不再沿单一方向稳定行走而是在短距离内来回移动同时伴随大量相互遮挡和尺度变化。Avenue 一共提供 16 个训练视频和 21 个测试视频分辨率 640×360总帧数约 3 万。它的异常类别不再局限于自行车、滑板等“非人目标”而是加入了多种人体行为异常比如奔跑、扔书包、扔纸、逆向行走、来回徘徊等。这个变化对模型提出了新要求。像 Ped2 里那种“只要检出目标不是人就报警”的路子在 Avenue 上行不太通因为异常目标很可能就是一个普通行人但行为模式与周边环境不匹配。比如有人在画面中突然狂奔或者把书包扔向另一个行人单帧静态信息有限必须结合时序上下文才能判断异常。这也是为什么很多在 Ped2 上表现不错的方法换到 Avenue 上 AUC 会掉一大截。4.2 像素级标注与评估协议Avenue 同时提供帧级和像素级标注这也是它比 Ped2 信息量更大的地方。像素级评估的做法是模型不仅要判断某一帧是否异常还要输出异常区域位置再与标注的二值 mask 计算重叠率。这个要求在真实监控场景非常重要因为光报警不给位置值班人员根本不知道去看哪里。实际评估时像素级 AUC 的计算比帧级复杂一点。常见做法是对预测的异常图通常由重建误差或特征距离得到做阈值化然后在像素层面算 ROC。不过由于异常目标往往只占画面很小区域像素级 AUC 容易偏低甚至出现“帧异常检测很好但异常定位几乎崩掉”的极端情况。我建议你在 Avenue 上一定要同时报告帧级 AUC 和像素级 AUC否则无法反映模型的真实定位能力。在 Avenue 上目前主流方法的帧级 AUC 大致在 88% 到 92% 的区间。虽然也有方法报到 93% 以上但不同实现、不同预处理方式差异很大。像素级 AUC 则普遍比帧级低一截很多论文只在表格里放帧级指标对像素级指标一笔带过投出去后在复试环节经常被问住。如果你准备拿 Avenue 做论文主线实验像素级评估跑通是基本门槛。4.3 Avenue 上的典型难点与预处理建议Avenue 场景里包含栏杆、路灯、绿植、车辆等复杂背景行人相互遮挡严重。很多测试异常目标非常小比如扔出去的纸团在 640×360 的分辨率下只占几十个像素模型很容易忽略。因此我不太建议像对待 Ped2 那样把 Avenue 帧缩得太小至少保持 256 以上的短边否则小目标直接消失。另一个问题是异常标注是按“异常对象”给 mask一帧里如果同时出现多个异常你必须全部检出才算完美。这种设定让评估变得非常严格也更容易暴露出模型“只学到大面积异常、漏掉小目标”的问题。从我实验的经验看Avenue 比 Ped2 更需要关注特征分辨率典型做法是把编码器最后一层特征 upsample 回输入尺寸再逐像素计算重建误差而不是只用一个全局向量去代表整帧。全局向量在 Avenue 上很容易把扔纸和正常行走混为一谈。5. Street Scene从学术场景走向真实街景5.1 为什么说 Street Scene 更“难啃”Street Scene 数据集来自亚利桑那州立大学于 2020 年前后发布是目前公开数据里更接近真实监控环境的基准之一。它拍摄的是美国某城市街道摄像机俯瞰街道与人行道背景里有商店入口、树荫、车辆、路牌天气和光照变化也远大于前两个校园场景。分辨率达到 1280×720总帧数超过 16 万帧训练视频 46 个、测试视频 35 个。这个数据集难的原因可以概括为四点一是背景杂乱画面中存在大量自然运动和相机抖动容易让模型把树叶晃动、车灯光斑当作异常二是目标尺度差异大同一个人可能从近处走过也可能在街道尽头变成几个像素的小点三是遮挡频繁行人被车辆、树木完全挡住的情况很常见四是异常类型更开放不仅有人的异常行为还有动物闯入、非法停车等场景级异常。想在 Street Scene 上刷出高分比在 Ped2 上难了一个量级。5.2 异常类型与标注特点Street Scene 的异常类型包括骑行、滑板、违规横穿马路、人行道上快速接近的车辆、野生动物闯入、非法停车等。标注同时覆盖帧级和像素级而且同一帧可以存在多个异常对象每个对象都有独立的 mask。这种做法鼓励模型做到“多目标定位”而不是只输出一个笼统的帧级异常分数。我特别建议关注的细节是Street Scene 的训练集和测试集按时间划分同一地点不会跨集重复出现。这意味着模型不能靠死记背景来得分必须学到相对通用的运动规律和场景语义才能对测试阶段的新场景保持稳定。很多在 Ped2 和 Avenue 上表现很惊艳的记忆库类方法到了 Street Scene 上性能滑落明显核心原因就是记忆内容与测试背景匹配不上。再从指标现状看如果以帧级 AUC 为标准Street Scene 上目前较新方法一般在 80% 出头能到 90% 的方法已经算很强了像素级 AUC 则普遍更低许多方法甚至不到 70%。这个数字和 Ped2 的普遍 97% 放在一起差距非常直观。我在多个公开对比实验里观察到越是讲究“场景理解”的模型在 Street Scene 上的相对优势越大越是只靠像素重建误差硬撑的模型越容易在这个数据集上露馅。5.3 实战中的调整策略如果你打算在 Street Scene 上做实验建议一开始就把输入分辨率定在 256×256 以上因为 720p 下的微小异常目标在低分辨率下几乎不可见。另一个建议是数据增强里加入随机颜色扰动、亮度和对比度调整因为 Street Scene 跨视频的光照差异比 Ped2 大得多不做色彩增强会导致模型把光照变化当成异常。还要注意光流输入的使用很多异常检测方法会让模型同时输入 RGB 和光流Street Scene 中既有镜头内部的少量运动也有目标本身的真实运动光流能帮助区分“背景噪声”和“目标异常”。一个更容易被忽略的点是时间滑动窗口的设置。Street Scene 视频较长很多方案使用固定长度的滑动窗口切视频片段窗口过短会导致模型无法判断“正常”与“异常”的时序关系窗口过长则训练成本飙升。我自己的实践是先试 8 到 16 帧的窗口配合 2 帧的步长生成训练样本这样既能覆盖动作连续性又不会让单段视频的数据量过于冗余。6. 实战流程数据集加载、训练准备与评估脚本6.1 三种数据集的目录结构先讲数据读取。以常见下载包为例三个数据集的目录结构大概是这样的UCSD Ped2主目录下分Train和Test每个视频单独一个子文件夹文件夹名是按序号编号的里面是一帧一帧的.tif图片测试集还带有_gt后缀的标注文件夹里面存放像素级 mask。CUHK Avenue主目录下有training_videos和testing_videos两个视频集合另有ground_truth_demo一类目录里面是按测试视频编号对应的.mat标注文件每个 mat 里保存了像素级 mask 序列。Street Scene提供了裁剪好的帧目录和对应的标注文件测试标注通常是 csv 或 mat 格式每一行标注了测试视频名、帧号、异常类别以及异常区域的边界框或多边形坐标。实际操作时我一般会把所有帧先按统一命名规则整理成下面的结构datasets/ ├── UCSDped2/ │ ├── Train/ │ └── Test/ ├── Avenue/ │ ├── training_frames/ │ └── testing_frames/ └── StreetScene/ ├── train_frames/ └── test_frames/整理成统一结构后后面不管换哪个数据集数据加载器都能复用。很多人会觉得这一步多余但我在同时跑多个数据集时发现统一目录结构能省下大量调试时间。6.2 PyTorch 数据集加载示例下面是一个简化版的数据集类以帧目录为输入返回连续帧序列和帧标签。实际使用时你可以根据需要把标签替换成像素级 mask。import os import cv2 import torch import numpy as np from torch.utils.data import Dataset class VideoFrameDataset(Dataset): def __init__(self, root_dir, frame_dir_list, seq_len8, transformNone, clip_step2): self.samples [] self.seq_len seq_len self.transform transform self.clip_step clip_step for video_dir in frame_dir_list: full_dir os.path.join(root_dir, video_dir) frame_names sorted( [f for f in os.listdir(full_dir) if f.endswith((.tif, .png, .jpg))] ) for i in range(0, len(frame_names) - seq_len 1, clip_step): self.samples.append( [os.path.join(full_dir, frame_names[i t]) for t in range(seq_len)] ) def __len__(self): return len(self.samples) def __getitem__(self, idx): frame_paths self.samples[idx] frames [] for path in frame_paths: img cv2.imread(path, cv2.IMREAD_COLOR) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) frames.append(img) frames np.stack(frames, axis0) # (T, H, W, 3) if self.transform: frames self.transform(frames) return torch.from_numpy(frames).permute(0, 3, 1, 2).float() / 255.0使用的时候训练阶段只传入官方训练视频对应的帧目录并且只使用正常视频。测试阶段则把测试视频全部传入不限制是否包含异常因为你需要对每一帧输出异常分数。上述代码里的clip_step控制视频切片段时的步长步长太小会让相邻样本高度重合增大训练冗余步长太大会让样本数量锐减训练不稳定。我的建议是先设为 2看训练收敛情况再调整。6.3 帧级 AUC 与 EER 计算代码评估端最关键的是把模型输出转成每一帧的异常分数。对于重建类模型常用方法是计算输入帧与重建帧之间的像素级 MSE 或 PSNRPSNR 越低表示异常分数越高。对于基于光流或分类的模型分数可能来自网络输出的异常类别概率。不管哪种方式最终你都需要一个一维序列与真实标注对齐。下面是一段只依赖 scikit-learn 的评估代码可以直接在测试集结果上运行。import numpy as np from sklearn.metrics import roc_auc_score def compute_frame_metrics(frame_labels, frame_scores): frame_labels: list/np.ndarray, 0 表示正常帧, 1 表示异常帧 frame_scores: list/np.ndarray, 分数越高越可能异常 frame_labels np.asarray(frame_labels) frame_scores np.asarray(frame_scores) # 帧级 AUC auc roc_auc_score(frame_labels, frame_scores) # EER寻找假正率与假负率最接近的阈值 thresholds np.linspace(frame_scores.min(), frame_scores.max(), 1000) eer 1.0 for th in thresholds: pred (frame_scores th).astype(int) fp np.sum((pred 1) (frame_labels 0)) fn np.sum((pred 0) (frame_labels 1)) fpr fp / max(np.sum(frame_labels 0), 1) fnr fn / max(np.sum(frame_labels 1), 1) eer min(eer, (fpr fnr) / 2.0) return auc, eer # 示例输入 frame_labels [0, 0, 1, 1, 0, 1, 0, 0] frame_scores [0.1, 0.2, 0.8, 0.7, 0.3, 0.9, 0.4, 0.2] auc, eer compute_frame_metrics(frame_labels, frame_scores) print(fAUC: {auc:.4f}, EER: {eer:.4f})这里要特别提醒一点不要对帧级分数做归一化时把训练集和测试集混在一起计算均值和方差。正确的做法是用训练集的统计量去归一化测试集或者干脆使用 Rank 类指标因为帧级 AUC 本质上是排序指标分数做线性变化不会改变 AUC 结果但你一旦引入了未来帧的信息就有了泄漏风险。6.4 像素级评估怎么处理 street scene 的多目标标注如果你在 Avenue 或 Street Scene 上做像素级评估不能只算一个全局 mask 的 AUC。建议先把每一帧模型输出的异常图二值化然后对每个真实标注框计算是否命中。命中的标准通常是预测 mask 与真实框的交并比大于某个阈值比如 0.1 或 0.3这个阈值在越严格的数据集上差异越大。Street Scene 的标注框里常有重叠情况遍历时要去重避免一个预测框同时匹配多个真实框导致分数偏高。这部分逻辑没有现成工具能完全通用我一般会自己复刻一遍官方评测脚本跑通后再决定是否使用别人封装好的库。7. 常见问题与避坑指南7.1 训练集与测试集别混用这看起来像废话但我在多个开源代码里真的见过。有些时候是因为数据集目录组织不清晰有些时候是数据加载器读取了全部文件夹。尤其是 Ped2 的测试集里也有正常帧如果被塞进训练集模型会提前见到大量测试片段的背景最终 AUC 虚高且完全没有可复现性。建议每次启动训练前用脚本打印一下训练样本对应的目录名列表人工核对一遍是否与官方划分一致。7.2 帧级指标高了不代表定位能力强帧级 AUC 只判断“这一帧有没有异常”不要求知道异常在哪里。因此两个模型可能帧级 AUC 相同但像素级 AUC 相差接近二十个百分点。如果你要解决的是实际监控问题定位能力往往比帧级硬指标更重要。我强烈建议至少在 Avenue 或 Street Scene 上额外跑一次像素级评估哪怕只是作为附录也会让论文结论结实很多。7.3 视频切分和帧率对齐不能想当然三个数据集的原始视频帧率并不完全一致Ped2 约 10fpsAvenue 与 Street Scene 也各有不同。如果你从视频重新抽帧必须按官方标注时间戳对齐否则评估时帧标签会错位。更稳妥的方法是直接使用官方提供的已抽取帧而不是自己用 OpenCV 从视频里重采。再就是滑动窗口切片段时统一使用固定帧数而不是固定秒数方便 batch 训练。7.4 别只报告单次结果这些数据集规模都有限尤其是 Ped2测试集只有几千帧单次实验受随机初始化和训练扰动影响大。我见过同一套代码在不同随机种子下Ped2 AUC 相差 3 个百分点。建议热门核心实验至少跑 3 个随机种子报告均值加标准差。这样审稿人那边也更踏实。回想我自己刚接触视频异常检测时差点因为迷信单一数据集指标而对模型能力产生严重误判。后来三个数据集都完整跑了一遍才真正理解了“数据集是算法的裁判”这句话。UCSD Ped2 适合排查基础问题CUHK Avenue 能帮你区分真正理解场景的模型和只会重建背景的模型Street Scene 则是检验走向真实部署的试金石。你的模型能跨过这三道门槛才敢说在视频异常检测方向上站稳了脚跟。最后再送一个小技巧所有实验前先把输入分辨率、片段长度、随机种子这些超参写死在配置文件里看起来多花十分钟实际上能帮你避免后面成千上万次的无效返工。
返回列表