File size: 4,088 Bytes
c8ef6d5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# -*- coding: utf-8 -*-

"""
preprocess_videos_v2.py

本脚本是 preprocess_videos.py 的 v2 版本。
它会创建 AudioVisual.py 期望的嵌套目录结构。

它会为每个 .mp4 文件 (例如 video1.mp4) 创建如下结构:
.../data/video1_frames/
    ├── frame_1/
    │   └── video1.jpg
    ├── frame_2/
    │   └── video1.jpg
    ...
    └── frame_10/
        └── video1.jpg
"""

import os
import cv2
import glob
import numpy as np

# --- 配置 ---

# 1. 你的 .mp4 文件所在的目录
SOURCE_DIR = '/home5/bwd/equiav/videos'

# 2. 存储提取的帧的目录
TARGET_DIR = '/home5/bwd/equiav/frames'

# 3. 每个视频提取的帧数 (根据 EquiAV 论文)
NUM_FRAMES = 11

# 4. 帧文件夹的后缀
FRAME_DIR_SUFFIX = '_frames'

# 5. 帧子目录的格式 (!! 关键更改 !!)
FRAME_SUBDIR_FORMAT = 'frame_{:d}' # e.g., frame_1, frame_10 (之前是 :02d)

# ---------------

def preprocess_videos_v2():
    """
    主处理函数 (V2)
    """
    print(f"开始预处理视频 (V2)...")
    print(f"源目录: {SOURCE_DIR}")
    print(f"目标目录: {TARGET_DIR}")
    print(f"每个视频提取帧数: {NUM_FRAMES}\n")

    mp4_files = glob.glob(os.path.join(SOURCE_DIR, '**', '*.mp4'), recursive=True)
    
    if not mp4_files:
        print(f"错误: 在 {SOURCE_DIR} 中未找到 .mp4 文件。")
        return

    print(f"找到了 {len(mp4_files)} 个 .mp4 文件。\n")

    for mp4_file_path in mp4_files:
        try:
            # 1. 获取 video_id 和 video_path
            video_id = os.path.splitext(os.path.basename(mp4_file_path))[0]
            # 基础帧目录, e.g., ".../CR450_frames"
            base_frame_output_dir = os.path.join(TARGET_DIR, video_id + FRAME_DIR_SUFFIX)
            
            # 2. 打开视频文件
            cap = cv2.VideoCapture(mp4_file_path)
            if not cap.isOpened():
                print(f"错误: 无法打开视频文件 {mp4_file_path}")
                continue

            # 3. 获取视频总帧数
            total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

            if total_frames < NUM_FRAMES:
                print(f"警告: {video_id}.mp4 只有 {total_frames} 帧 (少于 {NUM_FRAMES} 帧)。跳过此视频。")
                cap.release()
                continue

            # 4. 计算要提取的帧的索引
            indices = np.linspace(0, total_frames - 1, NUM_FRAMES, dtype=int)
            
            print(f"正在处理 {video_id}.mp4 ... (共 {total_frames} 帧, 提取 {len(indices)} 帧)")
            
            # 5. 提取并保存帧 (!! 新的目录结构 !!)
            frames_saved = 0
            for i, frame_index in enumerate(indices):
                cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
                ret, frame = cap.read()
                
                if ret:
                    # 构造帧的子目录, e.g., ".../CR450_frames/frame_1"
                    # (i+1) 会是 1, 2, ..., 10
                    frame_subdir = os.path.join(base_frame_output_dir, FRAME_SUBDIR_FORMAT.format(i + 1))
                    os.makedirs(frame_subdir, exist_ok=True)
                    
                    # 构造最终的 .jpg 文件路径, e.g., ".../frame_1/CR450.jpg"
                    # 文件名使用 video_id
                    output_path = os.path.join(frame_subdir, video_id + '.jpg')
                    
                    cv2.imwrite(output_path, frame)
                    frames_saved += 1
                else:
                    print(f"  - 错误: 无法读取帧索引 {frame_index}")
            
            print(f"  -> 完成。 {frames_saved} 帧已保存至 {base_frame_output_dir} (嵌套结构)\n")

            cap.release()

        except Exception as e:
            print(f"处理 {mp4_file_path} 时发生未知错误: {e}")
            if 'cap' in locals() and cap.isOpened():
                cap.release()

    print("="*30)
    print("所有视频预处理 (V2) 完成。")
    print("="*30)

if __name__ == "__main__":
    preprocess_videos_v2()