- 时序动作定位任务取 thumos 14 官方数据集的验证集当训练集,测试集当验证集
- 各有21个标注文件,Ambiguous_val.txt 文件记录了难以判断是否为动作的时间段,这些片段不参与评估。
根据标签文件把时序动作任务用到的视频移到同一个文件夹里(两个,一个val,一个test)
import shutil
from pathlib import Path
annotations_dir = Path('/hy-tmp/mmaction2-main/data/thumos14/annotations_val')
video_dir = Path('/hy-tmp/123/validation')
target_dir = Path('/hy-tmp/val_videos')
target_dir.mkdir(exist_ok=True)
video_names = set()
for txt in annotations_dir.glob('*.txt'):
with open(txt, 'r') as f:
for line in f:
if line.strip():
video_names.add(line.strip().split()[0])
moved_count = 0
not_found_count = 0
for v in sorted(video_names):
src = video_dir / f'{v}.mp4'
dst = target_dir / f'{v}.mp4'
if src.exists():
shutil.move(str(src), str(dst))
print(f'已移动: {src} -> {dst}')
moved_count += 1
else:
print(f'未找到视频文件: {src}')
not_found_count += 1
print(f'\n共移动视频数: {moved_count}')
print(f'共未找到视频数: {not_found_count}')
将thumos14的标注文件处理成时序动作定位可使用的标注格式
import json
import os
from pathlib import Path
import cv2
def get_video_duration_and_fps(video_path):
"""
使用 OpenCV 获取视频时长和FPS。
你需要根据实际视频文件路径来调用此函数。
这是一个示例,实际使用时可能需要更健壮的错误处理。
"""
try:
cap = cv2.VideoCapture(str(video_path))
if not cap.isOpened():
print(f"错误:无法打开视频 {video_path}")
return None, None
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
if fps > 0:
duration_second = frame_count / fps
else:
print(f"错误:视频 {video_path} 的FPS为 {fps}。无法计算时长。")
cap.release()
return None, None
cap.release()
return duration_second, fps
except Exception as e:
print(f"使用OpenCV处理视频 {video_path} 时出错: {e}")
if 'cap' in locals() and cap.isOpened():
cap.release()
return None, None
def convert_thumos_to_hacs(thumos_ann_dir, output_json_path, thumos_video_dir=None):
"""
将 THUMOS14 格式的标注文件转换为 HACS JSON 格式。
Args:
thumos_ann_dir (str): THUMOS14 标注文件所在目录 (e.g., '.../annotations_val/').
output_json_path (str): 输出的 HACS 格式 JSON 文件路径。
thumos_video_dir (str, optional): THUMOS14 视频文件所在目录。
如果提供,会尝试读取视频真实时长和FPS。
"""
hacs_data = {}
thumos_ann_path = Path(thumos_ann_dir)
if not thumos_ann_path.is_dir():
print(f"错误:找不到标注目录 '{thumos_ann_dir}'。")
return
for ann_file in thumos_ann_path.glob('*.txt'):
action_label = ann_file.stem.replace('_val', '').replace('_test', '')
print(f"正在处理类别: {action_label},来自文件: {ann_file.name}")
with open(ann_file, 'r') as f:
for line in f:
parts = line.strip().split()
if len(parts) != 3:
print(f"警告:跳过 {ann_file.name} 中的格式错误行: {line.strip()}")
continue
video_name = parts[0]
try:
start_time = float(parts[1])
end_time = float(parts[2])
except ValueError:
print(f"警告:跳过 {ann_file.name} 中时间无效的行: {line.strip()}")
continue
if video_name not in hacs_data:
actual_duration_s = None
current_video_fps = None
if thumos_video_dir:
potential_video_path = Path(thumos_video_dir) / f"{video_name}.mp4"
if potential_video_path.exists():
res_duration, res_fps = get_video_duration_and_fps(potential_video_path)
if res_duration is not None and res_fps is not None and res_fps > 0:
actual_duration_s = res_duration
current_video_fps = res_fps
else:
print(f"警告:无法从视频文件 {potential_video_path} 获取 {video_name} 的有效元数据(时长或FPS)。帧数相关字段将为0。")
else:
print(f"警告:在 {potential_video_path} 未找到 {video_name} 的视频文件。无法确定FPS,帧数相关字段将为0。")
else:
print(f"警告:未提供视频目录,无法获取 {video_name} 的FPS。帧数相关字段将为0。")
hacs_data[video_name] = {
"duration_second": actual_duration_s if actual_duration_s is not None else 0.0,
"duration_frame": 0,
"feature_frame": 0,
"_fps_temp": current_video_fps,
"annotations": []
}
annotation_entry = {
"label": action_label,
"segment": [start_time, end_time]
}
hacs_data[video_name]["annotations"].append(annotation_entry)
if hacs_data[video_name]["duration_second"] == 0.0:
hacs_data[video_name]["duration_second"] = max(
hacs_data[video_name].get("duration_second", 0.0),
end_time
)
for video_name in hacs_data:
video_info = hacs_data[video_name]
temp_fps = video_info.get("_fps_temp")
if video_info["duration_second"] > 0 and temp_fps is not None and temp_fps > 0:
video_info["duration_frame"] = int(video_info["duration_second"] * temp_fps)
else:
video_info["duration_frame"] = 0
if temp_fps is None or temp_fps <= 0:
print(f"错误:视频 {video_name} 的FPS未知或无效 (读取到的FPS: {temp_fps})。duration_frame 和 feature_frame 将设置为0。")
video_info["feature_frame"] = video_info["duration_frame"]
if "_fps_temp" in video_info:
del video_info["_fps_temp"]
with open(output_json_path, 'w') as f:
json.dump(hacs_data, f, indent=4)
print(f"转换完成。输出已保存到 {output_json_path}")
if __name__ == '__main__':
thumos_annotations_dir = r'/hy-tmp/mmaction2-main/data/thumos14/annotations_test'
thumos_videos_base_dir = r'/hy-tmp/test_videos'
output_hacs_json = r'/hy-tmp/annotations_test.json'
Path(output_hacs_json).parent.mkdir(parents=True, exist_ok=True)
convert_thumos_to_hacs(
thumos_annotations_dir,
output_hacs_json,
thumos_video_dir=thumos_videos_base_dir
)