RuLan03/Sthv2_500_3scope
Something-Something V2 (SSV2) 视频预测数据集子集构建文档 🚀 1. 项目目标与任务定义 本项目旨在从庞大的 Something-Something V2 训练集中,构建一个针对指令驱动型视频预测任务的、高质量、小规模的训练和验证子集。 核心任务定义 我们采用经典的视频预测任务定义:给定一个短序列 (F_1 到 F_20) 和一个文本指令,预测序列的下一帧 (F_21)。 元素 描述 索引 图像尺寸 输入序列 (I_Input) 20 张连续帧作为观测输入。 F_01 到 F_20 128 × 128 目标帧 (I_Target) 序列的第 21 帧作为模型预测的真值。 F_21 128 × 128 文本指令 (T) 视频的原始文本标签 (label 字段)。 SSV2 train.json 字符串 🔬 2. 数据集子集精准提取策略(创新点) Something-Something V2 包含… See the full description on the dataset page: https://huggingface.co/datasets/RuLan03/Sthv2_500_3scope.
Something-Something V2 (SSV2) 视频预测数据集子集构建文档
🚀 1. 项目目标与任务定义
本项目旨在从庞大的 Something-Something V2 训练集中,构建一个针对指令驱动型视频预测任务的、高质量、小规模的训练和验证子集。
核心任务定义
我们采用经典的视频预测任务定义:给定一个短序列 (F1 到 F20) 和一个文本指令,预测序列的下一帧 (F_21)。
🔬 2. 数据集子集精准提取策略(创新点)
Something-Something V2 包含 174 种动作类型和 10 万多个视频,涵盖范围广且噪音较大。我们采用以下策略进行数据蒸馏 (Data Distillation),确保子集的高质量和任务相关性。
2.1 基于 Template 字段的精准筛选 (核心方法)
传统的筛选方法是基于自由文本的 label 字段进行关键词匹配,但由于 label 字段是可变的(例如 "Moving something up" vs. "Moving the box up"),鲁棒性差。我们的创新点是:优先利用 template 字段进行结构化匹配。
- Template 特点: template 字段(例如 "Pulling [something] from right to left")比 label 字段更具结构化和泛化性,能稳定地代表动作类别。
- 筛选步骤: 通过预定义模式(如 "Pulling [something]", "Covering [something]"),从原始 train.json 中精确提取与我们任务相关的三类动作 ID 列表。
2.2 最终选取任务
最终子集选择了三类动作,旨在覆盖物体位置变化、物理状态改变和重力作用:
- move_object: 物体移动(推、拉、滑)
- drop_object: 物体掉落
- cover_object: 物体覆盖
2.3 数据量定额与冗余 (工程优化)
为了确保最终数据集严格满足数量要求(每个任务 500 个合格视频),我们采取了冗余选取 + 定额控制的策略:
- 冗余选取: 第一步筛选时,我们将每个任务的合格视频数量目标设置为 550 个(10% 冗余)。
- 定额控制: 在帧提取阶段,严格限制训练集和验证集的合格计数(Train: 400,Val: 100)。一旦达到定额,立即停止对该任务视频的处理。
⚙️ 3. 工程挑战与鲁棒性优化
在实际的视频帧提取过程中,主要困难集中在处理 .webm 格式视频的鲁棒性问题上。
3.1 遇到的主要困难:帧数报告不准确
使用 cv2.VideoCapture 库时,cap.get(cv2.CAP_PROP_FRAME_COUNT) 报告的总帧数 ($N_{\text{reported}}$) 对于某些 .webm 视频是不准确的估算值(通常虚高)。
- 后果: 依赖 $N_{\text{reported}}$ 计算居中采样位置时,往往导致程序试图读取不存在的帧,触发
cv2.read()失败,使得代码崩溃。
3.2 优化方案:基于实际读取的采样策略 (鲁棒性提升)
我们采用了两阶段优化方案,保证了采样序列的有效性和完整性:
阶段 A: 可靠的帧数计数
- 放弃依赖
CAP_PROP_FRAME_COUNT。 - 我们在提取前,对每个视频执行一次逐帧读取(通过
get_actual_frame_count函数),获取实际可读取的总帧数 ($N_{\text{actual}}$)。
阶段 B: 安全居中采样
- 我们基于可靠的 $N{\text{actual}}$ 计算采样窗口的起始索引 $I{start}$: $$I{start} = \max\left(0, \lfloor \frac{N{\text{actual}}}{2} \rfloor - \lfloor \frac{21}{2} \rfloor \right)$$
- 这种方法确保了提取的 21 帧序列 始终位于视频的高潮区域,同时不会溢出视频边界,极大地提高了采样的有效性和鲁棒性。
💾 4. 最终数据集结构与元数据
最终的数据集被组织成一个标准的 ML 目录结构,并进行了 Train/Val 拆分,便于模型的直接加载。
4.1 最终目录结构
数据集的根目录为 dataset_root/,Train/Val 比例为 80% / 20% (即每任务 400 Train, 100 Val)。
dataset_root/
├── train/
│ ├── move_object/
│ │ ├── video_78687/ // 每个视频一个文件夹
│ │ │ ├── 00.jpg // F_01 帧
│ │ │ ├── ...
│ │ │ └── 20.jpg // F_21 目标帧 (共 21 张 128x128 图像)
│ ├── drop_object/
│ └── cover_object/
├── val/
│ └── ... (与 train 结构相同)
└── metadata.json // 包含所有 Train/Val 视频索引的单一 JSON 文件4.2 metadata.json 格式
metadata.json 是模型加载的主要索引文件,包含所有必要的训练信息。
[
{
"video_path": "train/move_object/video_78687", // 相对路径,用于加载图像
"instruction": "Pulling [something] from right to left", // 文本指令
"task_type": "move_object" // 任务类别
},
...
]🛠️ 5. 使用和复现
依赖环境
本项目主要依赖于 Python 3 环境和以下库:
- opencv-python (用于视频处理和帧提取)
- tqdm (用于进度显示)
- json, os, shutil, random (标准库)
复现步骤
- 确保原始 20bn-something-something-v2 视频文件夹和 train.json 位于正确位置。
- 执行第一步脚本(
prepare_subsets.py):筛选合格的 $550$ 个视频到ssv2_task_subsets/。 - 执行第二步脚本(
final_data_preparer.py):执行居中采样、定额控制、$128 \times 128$ 缩放和最终的目录结构构建。
