
本文介绍如何将基于起止帧区间的行为标注数据框(如动物行为视频标注)扩展为逐帧行为标签序列,关键在于准确填充每个行为的有效帧范围,并将超出该范围的帧设为 nan,避免错误延续。
本文介绍如何将基于起止帧区间的行为标注数据框(如动物行为视频标注)扩展为逐帧行为标签序列,关键在于准确填充每个行为的有效帧范围,并将超出该范围的帧设为 nan,避免错误延续。
在动物行为视频分析中,标注软件常导出以“起始帧–结束帧”为区间的稀疏标注表(而非逐帧标注)。例如,某段“turning”行为从第 0 帧开始、第 2 帧结束(即覆盖帧 0 和 1),而下一段“immobility”从第 2 帧开始、第 5 帧结束(覆盖帧 2、3、4)。直接使用 reindex(..., method='ffill') 会错误地将前一行为延续至后续未定义区间(如帧 11–15 被误标为 “immobility”),违背原始标注逻辑。
正确做法是:先按完整帧索引(0 到最大帧号)重索引并前向填充,再依据每行的 Frame stop 值动态截断——当当前帧索引 ≥ Frame stop 时,强制置 Behavior 为 NaN。
以下是完整实现代码:
import pandas as pd
import numpy as np
# 原始稀疏标注数据
data = {
'Frame start': [0, 2, 5, 9, 16],
'Frame stop': [2, 5, 9, 11, 20],
'Behavior': ['turning', 'immobility', 'mild movement', 'immobility', 'jump']
}
df = pd.DataFrame(data).set_index('Frame start')
# 步骤1:构建完整帧索引(0 到 max_frame_stop - 1,此处取 0~19)
max_frame = df['Frame stop'].max() # 20 → 覆盖帧 0~19
new_index = list(range(max_frame))
# 步骤2:reindex + ffill 行为与 Frame stop 列
new_df = df.reindex(new_index, method='ffill')
# 步骤3:精准截断——仅保留 frame_start ≤ 当前帧 < frame_stop 的行为
# 即:当前帧索引 >= Frame stop 时,Behavior 设为 NaN
new_df.loc[new_df['Frame stop'] <= new_df.index, 'Behavior'] = np.nan
# 提取最终结果(仅 Behavior 列,以 Frame start 为索引)
result = new_df['Behavior']
print(result)输出结果严格符合预期:
Frame start 0 turning 1 turning 2 immobility 3 immobility 4 immobility 5 mild movement 6 mild movement 7 mild movement 8 mild movement 9 immobility 10 immobility 11 NaN 12 NaN 13 NaN 14 NaN 15 NaN 16 jump 17 jump 18 jump 19 jump Name: Behavior, dtype: object
⚠️ 注意事项:
-
Frame stop在原始数据中表示第一个不包含的帧(即区间为[start, stop)),这是视频帧索引的常规约定;若实际为闭区间[start, stop],则条件应改为new_df['Frame stop'] ; - 若存在重叠区间或非单调
Frame start,需预先排序并检查逻辑一致性; - 对于超大视频(如数万帧),建议使用
pd.arrays.SparseArray或分块处理以节省内存; - 最终结果可直接用于时序建模、行为持续时间统计或与视频帧对齐可视化。
该方法兼顾准确性与可读性,是行为分析工作流中处理稀疏标注的关键预处理步骤。


















