Allow explicitly audited Ego4D bbox tails
This commit is contained in:
@@ -190,11 +190,11 @@ worker 及其进程组,不杀无关训练。已完成的 `.pt` 保留,重跑
|
||||
`clip_end_sec=299.9333333333333`,但 bbox 仍到 `8999`,越界索引为 `[8998, 8999]`。
|
||||
因此只兼容一个末尾索引还不够;这第二例同样是标注结束位置与媒体长度一致、bbox 尾部多出记录。
|
||||
|
||||
提取器只在以下条件同时满足时忽略末尾记录:所有越界索引都属于 `N、N+1`,
|
||||
提取器默认只在以下条件同时满足时忽略末尾记录:所有越界索引都属于 `N、N+1`,
|
||||
`N=视频帧数=clip_end_frame`,标注帧起点为 0、时间起点在 1 微秒内为 0,
|
||||
且标注时长与 `N / source_fps` 相差不超过 0.1 毫秒。
|
||||
容差限制的是**末尾索引位置**,不是框数:即使仅一条记录,出现在 `N+2` 或更远处也不接受。
|
||||
负索引、缺少确认边界、较大越界或时长不匹配仍会报错,并打印具体范围;不自动跳过 clip。
|
||||
负索引、缺少确认边界、超过显式容差的越界或时长不匹配仍会报错,并打印具体范围;不自动跳过 clip。
|
||||
这是基于已核实样例的受限兼容规则,不代表所有 Ego4D 越界记录都可忽略。
|
||||
|
||||
日志显示忽略的末尾索引和框数;新 `.pt` 的 `box_frame_audit` 与预览目录的
|
||||
@@ -203,6 +203,58 @@ worker 及其进程组,不杀无关训练。已完成的 `.pt` 保留,重跑
|
||||
`0.2..299.8s`,2 FPS 的最后一个输入采样时刻仍为 `299.5s`。
|
||||
该处理不改编码器/池化配置,之前完成且通过校验的特征可以继续复用;同步修复后重跑原 8 卡命令即可。
|
||||
|
||||
#### 更长但边界一致的尾部:显式授权,不修改默认值
|
||||
|
||||
用户随后报告 `d2cb4045-8ef1-4288-8398-ab6d4d6a0709`:视频为 8987 帧、30 FPS,
|
||||
`clip_end_frame=8987`、`clip_end_sec=299.5666666666666`,但 bbox 延伸到 8999。
|
||||
两种长度信息一致,越界的 8987–8999 共 13 个索引都没有对应的视频帧。
|
||||
这解释了默认两帧规则为什么失败;不是 GPU OOM,也不意味着应平移全部框。
|
||||
本地没有该远程视频,本次用用户提供的边界建立 CPU 回归 fixture,未重新解码实际文件。
|
||||
|
||||
新增参数 `--ego4d-max-terminal-overrun-frames K`,只授权 `[N, N+K)` 内的尾部索引:
|
||||
|
||||
- 默认 `K=2` 不变;`K=0` 禁用所有尾部兼容;负值被拒绝。
|
||||
- 仍必须满足零起点、`N=source_frames=clip_end_frame` 和同样的时长一致性校验。
|
||||
- 上限按最远索引计算,不按框数或越界索引数量计算;本例 `K=13` 不接受索引 9000 或更远处。
|
||||
- 原始视频、标注 JSON 和 target 不改动;仅从本次内存 bbox 映射排除无对应视频帧的尾部。
|
||||
- 媒体仍需覆盖原始 target/全局特征要求的时长。参数不能修复截断的视频、补帧、缩短 target 或绕过全局/局部时间线校验。
|
||||
- 参数及实际尾部长度保存在每个新文件的 `box_frame_audit`,不改变编码器配置/旧特征复用条件。
|
||||
|
||||
同步代码后,使用上面已经配置好的 `MULTIGPU_ARGS` 续跑:
|
||||
|
||||
```bash
|
||||
python extract_ego4d_local_multigpu.py "${MULTIGPU_ARGS[@]}" \
|
||||
--ego4d-max-terminal-overrun-frames 13
|
||||
```
|
||||
|
||||
若在新终端中运行,先重新定义上一节的完整 `MULTIGPU_ARGS` 数组。无需软链接,不使用 `--overwrite`。
|
||||
当前失败会停止本次启动的其他 workers;已原子保存且复用检查通过的 `.pt` 不会重提,
|
||||
中途被停止、尚未保存的 clip 会重新计算。不要对更大的越界直接设无限容差,应先核对新日志。
|
||||
|
||||
新生成的该 clip 可以检查审计和网格长度:
|
||||
|
||||
```bash
|
||||
python - <<'PY'
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
root = Path('/data1/yfzx/wangx/Datasets/ego4d')
|
||||
clip_id = 'd2cb4045-8ef1-4288-8398-ab6d4d6a0709'
|
||||
p = torch.load(root / 'omni_features/local_qwen_1s' / f'{clip_id}.pt',
|
||||
map_location='cpu', weights_only=False)
|
||||
target = np.load(root / 'ego4d_target_frame' / f'{clip_id}.npy', mmap_mode='r')
|
||||
assert len(p['visual']) == len(p['audio']) == len(p['times']) == len(target)
|
||||
assert not p['partial']
|
||||
audit = p['box_frame_audit']
|
||||
assert audit['source_frames'] == audit['declared_bounds']['clip_end_frame'] == 8987
|
||||
assert audit['ignored_frame_indices'] == list(range(8987, 9000))
|
||||
print('visual:', tuple(p['visual'].shape), 'audio:', tuple(p['audio'].shape))
|
||||
print('target:', target.shape, 'last cutoff:', float(p['times'][-1]))
|
||||
print('bbox audit:', audit)
|
||||
PY
|
||||
```
|
||||
|
||||
提取完成后,原训练入口也直接用同一个原始全局特征根,无需 flat 索引:
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user