共计 2776 个字符,预计需要花费 7 分钟才能阅读完成。
AVA 数据集结构解析
AVA 数据集的核心在于时空定位(spatio-temporal localization)和行为识别。它的标注包含两个关键部分:

- 边界框(bounding box):以
[x1, y1, x2, y2]格式存储,表示人物在视频帧中的位置 - 行为标签(action label):来自 80 类预定义动作(如 ”walk”、”hand shake”),每个边界框可对应多个动作
标注文件通常为 CSV 格式,关键字段包括:
video_id:视频唯一标识frame_id:时间戳(每秒 30 帧)person_id:同一人物的跨帧追踪 IDbbox:归一化坐标(0- 1 范围)action_ids:分号分隔的动作 ID 列表
主流标注工具对比
CVAT(Computer Vision Annotation Tool)
- 优势:
- 内置视频插值功能,标注关键帧后自动生成中间帧
- 支持多人协作和任务分配
-
可直接导出 AVA 标准格式
-
劣势:
- 部署需要 Docker 环境
- 对长视频支持较差
Label Studio
- 优势:
- 网页版即开即用
- 灵活的标签配置界面
-
支持主动学习工作流
-
劣势:
- 视频标注需要安装插件
- 多人标注管理功能较弱
VGG Image Annotator (VIA)
- 优势:
- 纯前端工具,无需安装
-
极简的 JSON 标注格式
-
劣势:
- 缺乏视频专用功能
- 无法处理大体积文件
推荐选择:CVAT(适合团队生产环境)或Label Studio(适合快速原型开发)
标注规范制定要点
动作边界判定原则
- 起始帧:动作特征首次明确出现的帧
- 结束帧:动作特征完全消失的下一帧
- 模糊区间:当存在疑问时,遵循 ” 宁可漏标,不要错标 ” 原则
多人交互场景处理
- 独立标注:每人单独标记 bounding box
- 关联标注 :使用相同的
person_id追踪交互对象 - 组合动作:为双方同时添加交互类标签(如 ”hand shake”)
Python 标注校验示例
import cv2
import pandas as pd
from typing import List, Tuple
class AVAValidator:
def __init__(self, csv_path: str):
self.df = pd.read_csv(csv_path)
self.error_log = []
def check_bbox(self, bbox: List[float]) -> bool:
"""验证边界框是否合法"""
x1, y1, x2, y2 = bbox
if not (0 <= x1 < x2 <= 1 and 0 <= y1 < y2 <= 1):
self.error_log.append(f"Invalid bbox coordinates: {bbox}")
return False
return True
def visualize(self, video_path: str, output_path: str):
"""标注可视化工具"""
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 绘制当前帧所有标注
frame_id = int(cap.get(cv2.CAP_PROP_POS_FRAMES))
annotations = self.df[self.df['frame_id'] == frame_id]
for _, row in annotations.iterrows():
x1, y1, x2, y2 = eval(row['bbox'])
h, w = frame.shape[:2]
pt1 = (int(x1*w), int(y1*h))
pt2 = (int(x2*w), int(y2*h))
cv2.rectangle(frame, pt1, pt2, (0,255,0), 2)
cv2.imshow('Validation', frame)
if cv2.waitKey(int(1000/fps)) == 27:
break
cap.release()
cv2.destroyAllWindows()
质量保障方案
多人标注一致性检验
-
Krippendorff’s Alpha 系数:衡量不同标注者间的一致性
from sklearn.metrics import cohen_kappa_score def calculate_agreement(annotator1, annotator2): return cohen_kappa_score(annotator1, annotator2) -
冲突解决流程:
- 第一阶段:标注员自行讨论达成共识
- 第二阶段:由资深标注员仲裁
- 第三阶段:剔除无法达成一致的样本
标签分布分析
import matplotlib.pyplot as plt
def plot_label_distribution(df):
action_counts = df['action_ids'].str.split(';').explode().value_counts()
plt.bar(action_counts.index, action_counts.values)
plt.xticks(rotation=90)
plt.show()
避坑指南
帧偏移错误解决方案
- 问题现象:动作标签与视觉内容出现时间差
- 解决方法:
- 预处理阶段统一视频帧率
- 使用
ffmpeg精确提取关键帧 -
在标注工具中启用帧同步预览
-
检测代码:
def detect_frame_shift(video_df, threshold=5): """检测连续帧间的人物位移异常""" shifts = [] for person_id in video_df['person_id'].unique(): person_df = video_df[video_df['person_id'] == person_id].sort_values('frame_id') for i in range(1, len(person_df)): prev_bbox = eval(person_df.iloc[i-1]['bbox']) curr_bbox = eval(person_df.iloc[i]['bbox']) dx = abs((prev_bbox[0]+prev_bbox[2])/2 - (curr_bbox[0]+curr_bbox[2])/2) dy = abs((prev_bbox[1]+prev_bbox[3])/2 - (curr_bbox[1]+curr_bbox[3])/2) if dx > threshold or dy > threshold: shifts.append((person_df.iloc[i]['frame_id'], dx, dy)) return shifts
延伸思考
- 如何处理视频中部分遮挡的人物标注?
- 当同一人物同时执行多个动作时,标签权重应如何分配?
- 如何设计增量学习策略来优化长期视频的标注效率?
正文完
