视频理解与生成解析(Video Understanding & Generation)

目录

  1. 视频理解基础理论
  2. 时序建模方法
  3. 动作识别
  4. 视频分类与检测
  5. 视频分割
  6. 视频生成基础
  7. 扩散模型视频生成
  8. 视频预测与插值
  9. 评估指标与数据集
  10. 应用与前沿

1. 视频理解基础理论

1.1 什么是视频理解

复制代码
视频理解的目标:
  从视频序列中提取语义信息

  ┌─────────────────────────────────────────────────────────────────┐
  │                    视频理解任务                                   │
  ├─────────────────────────────────────────────────────────────────┤
  │                                                                 │
  │  分类任务:                                                       │
  │  ├── 动作识别: 识别视频中的动作 (跑步、游泳、吃饭)               │
  │  ├── 视频分类: 将视频分类到预定义类别                            │
  │  └── 事件检测: 检测视频中的事件                                  │
  │                                                                 │
  │  定位任务:                                                       │
  │  ├── 时间动作定位: 定位动作的起止时间                            │
  │  ├── 时空动作检测: 定位动作的时间和空间                          │
  │  └── 视频摘要: 提取视频的关键片段                                │
  │                                                                 │
  │  跟踪任务:                                                       │
  │  ├── 多目标跟踪: 跟踪视频中的多个物体                            │
  │  ├── 单目标跟踪: 跟踪特定物体                                    │
  │  └── 行人重识别: 跨摄像头跟踪行人                                │
  │                                                                 │
  │  生成任务:                                                       │
  │  ├── 视频生成: 从文本/图像生成视频                               │
  │  ├── 视频预测: 预测未来帧                                        │
  │  ├── 视频插值: 生成中间帧                                        │
  │  └── 视频编辑: 编辑视频内容                                      │
  │                                                                 │
  └─────────────────────────────────────────────────────────────────┘

1.2 视频数据特性

复制代码
视频数据的特殊性:

  图像: [H, W, C] --- 静态
  视频: [T, H, W, C] --- 动态 (T 帧)

  特性:
    1. 时序性: 帧之间有时间顺序
    2. 冗余性: 相邻帧高度相似
    3. 运动信息: 帧间差异包含运动信息
    4. 长时依赖: 理解需要长时上下文
    
  挑战:
    1. 计算量: T 帧 × 每帧计算量
    2. 内存: 存储 T 帧特征
    3. 时序建模: 如何有效建模时间关系
    4. 长视频: 处理数分钟甚至数小时的视频

1.3 视频表示

复制代码
视频表示方法:

  1. 帧级表示:
     每帧独立处理
     
     优点: 简单,可用图像模型
     缺点: 忽略时序关系
     
  2. 片段级表示:
     采样固定长度的片段 (如 16 帧)
     
     优点: 平衡计算和时序信息
     缺点: 固定窗口,可能错过关键帧
     
  3. 视频级表示:
     处理整个视频
     
     优点: 完整时序信息
     缺点: 计算量大

2. 时序建模方法

2.1 早期方法

复制代码
时序建模的演进:

  1. 双流网络 (Two-Stream, 2014):
     空间流: 单帧图像 → CNN → 空间特征
     时间流: 光流图 → CNN → 运动特征
     
     融合: 空间 + 时间 → 分类
     
     理论:
       光流编码了帧间运动
       空间流捕获外观信息
       两者互补
       
  2. 3D 卷积 (C3D, 2015):
     使用 3D 卷积核处理视频
     
     输入: [T, H, W, C]
     卷积核: [k_t, k_h, k_w]
     
     理论:
       3D 卷积同时建模空间和时间
       但计算量大
       
  3. SlowFast (2019):
     Slow 路径: 低帧率,捕获空间语义
     Fast 路径: 高帧率,捕获运动信息
     
     理论:
       视频中的运动速度快
       需要高帧率捕获
       但空间信息不需要那么高帧率
python 复制代码
import torch
import torch.nn as nn

class TwoStreamNetwork(nn.Module):
    """
    双流网络
    
    空间流: 处理单帧图像
    时间流: 处理光流图
    
    理论:
      空间流: 捕获外观信息 (物体、场景)
      时间流: 捕获运动信息 (光流)
      融合: 结合两者进行分类
    """
    def __init__(self, num_classes):
        super().__init__()
        
        # 空间流 (图像)
        self.spatial_stream = nn.Sequential(
            nn.Conv2d(3, 64, 3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(64, 128, 3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.AdaptiveAvgPool2d(1),
            nn.Flatten(),
            nn.Linear(128, num_classes)
        )
        
        # 时间流 (光流)
        self.temporal_stream = nn.Sequential(
            nn.Conv2d(2 * 10, 64, 3, padding=1),  # 10 帧的光流 (x, y)
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(64, 128, 3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.AdaptiveAvgPool2d(1),
            nn.Flatten(),
            nn.Linear(128, num_classes)
        )
        
        # 融合权重
        self融合_weight = nn.Parameter(torch.ones(2) / 2)
    
    def forward(self, frame, optical_flow):
        """
        frame: [B, 3, H, W] 单帧图像
        optical_flow: [B, 20, H, W] 10 帧光流
        """
        # 空间流
        spatial_out = self.spatial_stream(frame)
        
        # 时间流
        temporal_out = self.temporal_stream(optical_flow)
        
        # 加权融合
        weights = torch.softmax(self融合_weight, dim=0)
        output = weights[0] * spatial_out + weights[1] * temporal_out
        
        return output

"""
光流 (Optical Flow):

  定义: 像素在相邻帧之间的位移向量
  
  光流场: F = (u, v)
    u: 水平位移
    v: 垂直位移
    
  计算方法:
    1. 稀疏光流: Lucas-Kanade (只计算特征点)
    2. 稠密光流: Farneback, RAFT (计算所有像素)
    
  应用:
    - 双流网络的时间流输入
    - 运动估计
    - 视频稳定
"""

2.2 3D 卷积

python 复制代码
class C3D(nn.Module):
    """
    C3D (3D Convolutional Network)
    
    使用 3D 卷积核处理视频
    
    理论:
      3D 卷积同时建模空间和时间维度
      卷积核: [k_t, k_h, k_w]
      
    缺点:
      - 参数量大
      - 计算量大
      - 难以训练
    """
    def __init__(self, num_classes):
        super().__init__()
        
        # 3D 卷积层
        self.features = nn.Sequential(
            nn.Conv3d(3, 64, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(1, 2, 2), stride=(1, 2, 2)),
            
            nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            
            nn.Conv3d(128, 256, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            
            nn.Conv3d(256, 512, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2))
        )
        
        # 分类器
        self.classifier = nn.Sequential(
            nn.AdaptiveAvgPool3d(1),
            nn.Flatten(),
            nn.Linear(512, 4096),
            nn.ReLU(),
            nn.Dropout(0.5),
            nn.Linear(4096, num_classes)
        )
    
    def forward(self, x):
        """
        x: [B, C, T, H, W]
        """
        x = self.features(x)
        x = self.classifier(x)
        return x

"""
3D 卷积的参数量:

  2D 卷积: C_in × C_out × k_h × k_w
  3D 卷积: C_in × C_out × k_t × k_h × k_w
  
  当 k=3 时:
    2D: 9 × C_in × C_out
    3D: 27 × C_in × C_out (3 倍)
"""

2.3 SlowFast 网络

复制代码
论文: "SlowFast Networks for Video Recognition" (Feichtenhofer et al., 2019)

核心思想:
  Slow 路径: 低帧率 (如每 16 帧取 1 帧)
    捕获空间语义 (物体、场景)
    
  Fast 路径: 高帧率 (如每 2 帧取 1 帧)
    捕获运动信息 (快速变化)
    
  融合: 侧向连接 + 最终拼接

理论:
  视频中的信息有多时间尺度:
    - 空间语义: 变化慢 (背景、物体)
    - 运动信息: 变化快 (手势、动作)
    
  Slow 路径处理慢变化的信息
  Fast 路径处理快变化的信息
python 复制代码
class SlowFast(nn.Module):
    """
    SlowFast 网络
    
    Slow 路径: 低帧率,捕获空间语义
    Fast 路径: 高帧率,捕获运动信息
    
    理论:
      不同时间尺度的信息需要不同的帧率
      Slow: 每 16 帧取 1 帧
      Fast: 每 2 帧取 1 帧
    """
    def __init__(self, num_classes, slow_frames=4, fast_frames=32):
        super().__init__()
        
        self.slow_frames = slow_frames
        self.fast_frames = fast_frames
        
        # Slow 路径 (低帧率,大通道数)
        self.slow_path = nn.Sequential(
            nn.Conv3d(3, 64, kernel_size=(1, 7, 7), stride=(1, 2, 2), padding=(0, 3, 3)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1)),
            
            nn.Conv3d(64, 128, kernel_size=(1, 3, 3), padding=(0, 1, 1)),
            nn.ReLU(),
            
            nn.Conv3d(128, 256, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            
            nn.AdaptiveAvgPool3d(1)
        )
        
        # Fast 路径 (高帧率,小通道数)
        self.fast_path = nn.Sequential(
            nn.Conv3d(3, 8, kernel_size=(5, 7, 7), stride=(1, 2, 2), padding=(2, 3, 3)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(1, 2, 2), padding=(0, 1, 1)),
            
            nn.Conv3d(8, 16, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            
            nn.Conv3d(16, 32, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            
            nn.AdaptiveAvgPool3d(1)
        )
        
        # 侧向连接 (Fast → Slow)
        self.lateral_connections = nn.ModuleList([
            nn.Conv3d(8, 64, kernel_size=(1, 1, 1)),
            nn.Conv3d(16, 128, kernel_size=(1, 1, 1)),
            nn.Conv3d(32, 256, kernel_size=(1, 1, 1))
        ])
        
        # 分类器
        self.classifier = nn.Linear(256 + 32, num_classes)
    
    def forward(self, slow_input, fast_input):
        """
        slow_input: [B, 3, T_slow, H, W]
        fast_input: [B, 3, T_fast, H, W]
        """
        # Slow 路径
        slow_features = self.slow_path(slow_input)
        
        # Fast 路径
        fast_features = self.fast_path(fast_input)
        
        # 融合
        combined = torch.cat([slow_features.flatten(1), fast_features.flatten(1)], dim=1)
        
        # 分类
        output = self.classifier(combined)
        
        return output

"""
SlowFast 的通道比例:

  Slow: β = 1 (正常通道数)
  Fast: β = 1/8 或 1/16 (小通道数)
  
  理论:
    Fast 路径主要捕获运动
    运动信息可以用较少的通道表示
    减少计算量
"""

2.4 时间注意力

python 复制代码
class TemporalAttention(nn.Module):
    """
    时间注意力机制
    
    理论:
      不同时间步的重要性不同
      注意力机制学习关注重要的时间步
      
    应用:
      - 视频分类中关注关键帧
      - 动作识别中关注动作发生的时间
    """
    def __init__(self, d_model):
        super().__init__()
        
        self.query = nn.Linear(d_model, d_model)
        self.key = nn.Linear(d_model, d_model)
        self.value = nn.Linear(d_model, d_model)
        
        self.scale = d_model ** 0.5
    
    def forward(self, x):
        """
        x: [B, T, D] 时间序列特征
        """
        Q = self.query(x)
        K = self.key(x)
        V = self.value(x)
        
        # 时间注意力
        attn = torch.bmm(Q, K.transpose(1, 2)) / self.scale
        attn = torch.softmax(attn, dim=-1)
        
        # 加权聚合
        output = torch.bmm(attn, V)
        
        return output

"""
时间注意力的理论:

  自注意力: 每个时间步关注所有其他时间步
  因果注意力: 只关注过去的时间步
  
  对于视频:
    非因果: 可以看到整个视频 (分类任务)
    因果: 只能看到过去 (在线任务)
"""

3. 动作识别

3.1 动作识别概述

复制代码
动作识别任务:

  输入: 视频片段
  输出: 动作类别

  数据集:
    - Kinetics-400: 400 类动作,300K 视频
    - Kinetics-700: 700 类动作
    - UCF-101: 101 类动作
    - HMDB-51: 51 类动作
    
  挑战:
    - 类内差异大 (同一动作有多种方式)
    - 类间差异小 (不同动作可能相似)
    - 背景干扰
    - 相机运动

3.2 时空建模方法

复制代码
时空建模的演进:

  1. 双流网络 (2014):
     空间流 + 时间流
     
  2. C3D (2015):
     3D 卷积
     
  3. I3D (2017):
     膨胀 3D 卷积
     从 2D 模型膨胀为 3D
     
  4. SlowFast (2019):
     双路径,不同帧率
     
  5. X3D (2020):
     高效 3D 网络
     
  6. TimeSformer (2021):
     视频 Transformer
     
  7. VideoMAE (2022):
     掩码自编码器预训练
python 复制代码
class I3D(nn.Module):
    """
    I3D (Inflated 3D ConvNet)
    
    核心思想:
      将 2D 预训练模型膨胀为 3D
      复用 ImageNet 预训练权重
      
    膨胀方法:
      2D 卷积核 [k, k] → 3D 卷积核 [k, k, k]
      
      权重复制: 沿时间维度复制 k 次,再除以 k
      
    理论:
      空间特征可以从 ImageNet 迁移
      时间维度需要从头学习
    """
    def __init__(self, num_classes):
        super().__init__()
        
        # 膨胀的 Inception 模块
        self.features = nn.Sequential(
            Inception3D(3, 64),
            nn.MaxPool3d(kernel_size=(1, 3, 3), stride=(1, 2, 2)),
            
            Inception3D(64, 192),
            nn.MaxPool3d(kernel_size=(3, 3, 3), stride=(2, 2, 2)),
            
            Inception3D(192, 256),
            Inception3D(256, 320),
            nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            
            Inception3D(320, 576),
            Inception3D(576, 576),
            nn.AdaptiveAvgPool3d(1)
        )
        
        self.classifier = nn.Linear(576, num_classes)
    
    def forward(self, x):
        """
        x: [B, 3, T, H, W]
        """
        x = self.features(x)
        x = x.flatten(1)
        x = self.classifier(x)
        return x

class Inception3D(nn.Module):
    """
    3D Inception 模块
    
    多尺度 3D 卷积
    """
    def __init__(self, in_channels, out_channels):
        super().__init__()
        
        # 分支 1: 1×1×1
        self.branch1 = nn.Conv3d(in_channels, out_channels // 4, 1)
        
        # 分支 2: 1×1×1 → 3×3×3
        self.branch2 = nn.Sequential(
            nn.Conv3d(in_channels, out_channels // 4, 1),
            nn.Conv3d(out_channels // 4, out_channels // 4, 3, padding=1)
        )
        
        # 分支 3: 1×1×1 → 3×3×3 × 2
        self.branch3 = nn.Sequential(
            nn.Conv3d(in_channels, out_channels // 4, 1),
            nn.Conv3d(out_channels // 4, out_channels // 4, 3, padding=1),
            nn.Conv3d(out_channels // 4, out_channels // 4, 3, padding=1)
        )
        
        # 分支 4: MaxPool → 1×1×1
        self.branch4 = nn.Sequential(
            nn.MaxPool3d(3, stride=1, padding=1),
            nn.Conv3d(in_channels, out_channels // 4, 1)
        )
    
    def forward(self, x):
        b1 = self.branch1(x)
        b2 = self.branch2(x)
        b3 = self.branch3(x)
        b4 = self.branch4(x)
        
        return torch.cat([b1, b2, b3, b4], dim=1)

3.3 视频 Transformer

复制代码
论文: "Is Space-Time Attention All You Need for Video Understanding?" 
      (Bertasius et al., 2021)

TimeSformer 核心思想:
  将 Transformer 应用于视频
  使用时空注意力

注意力模式:
  1. 时间注意力: 每个 patch 关注所有时间步的同一位置
  2. 空间注意力: 每个 patch 关注同一时间步的所有位置
  3. 联合时空注意力: 关注所有位置 (计算量大)
  4. 分离时空注意力: 先时间后空间 (推荐)
python 复制代码
class TimeSformer(nn.Module):
    """
    TimeSformer
    
    视频 Transformer,使用分离的时空注意力
    
    理论:
      先进行时间注意力 (不同时间的同一位置)
      再进行空间注意力 (同一时间的不同位置)
      分离降低计算复杂度
    """
    def __init__(self, img_size=224, patch_size=16, num_frames=8, 
                 num_classes=400, d_model=768, n_heads=12, n_layers=12):
        super().__init__()
        
        self.patch_size = patch_size
        self.num_patches = (img_size // patch_size) ** 2
        
        # Patch Embedding
        self.patch_embedding = nn.Conv3d(
            3, d_model, 
            kernel_size=(1, patch_size, patch_size),
            stride=(1, patch_size, patch_size)
        )
        
        # 位置编码
        self.position_embedding = nn.Parameter(
            torch.randn(1, num_frames * self.num_patches + 1, d_model)
        )
        
        # CLS Token
        self.cls_token = nn.Parameter(torch.randn(1, 1, d_model))
        
        # Transformer 层 (分离时空注意力)
        self.layers = nn.ModuleList([
            SpatioTemporalAttention(d_model, n_heads)
            for _ in range(n_layers)
        ])
        
        # 分类头
        self.norm = nn.LayerNorm(d_model)
        self.head = nn.Linear(d_model, num_classes)
    
    def forward(self, x):
        """
        x: [B, C, T, H, W]
        """
        B, C, T, H, W = x.shape
        
        # Patch Embedding
        x = self.patch_embedding(x)  # [B, d_model, T, H/P, W/P]
        x = x.flatten(2).transpose(1, 2)  # [B, T*H/P*W/P, d_model]
        
        # 添加 CLS Token
        cls_tokens = self.cls_token.expand(B, -1, -1)
        x = torch.cat([cls_tokens, x], dim=1)
        
        # 位置编码
        x = x + self.position_embedding
        
        # Transformer 层
        for layer in self.layers:
            x = layer(x, T, self.num_patches)
        
        # 分类
        x = self.norm(x[:, 0])
        x = self.head(x)
        
        return x

class SpatioTemporalAttention(nn.Module):
    """
    分离时空注意力
    
    先时间注意力,后空间注意力
    
    理论:
      时间注意力: 每个 patch 关注不同时间的同一位置
      空间注意力: 每个 patch 关注同一时间的不同位置
      分离降低计算量从 O((THW)²) 到 O(T(HW)² + (T²)HW)
    """
    def __init__(self, d_model, n_heads):
        super().__init__()
        
        self.time_attn = nn.MultiheadAttention(d_model, n_heads, batch_first=True)
        self.space_attn = nn.MultiheadAttention(d_model, n_heads, batch_first=True)
        
        self.norm1 = nn.LayerNorm(d_model)
        self.norm2 = nn.LayerNorm(d_model)
        self.norm3 = nn.LayerNorm(d_model)
        
        self.mlp = nn.Sequential(
            nn.Linear(d_model, d_model * 4),
            nn.GELU(),
            nn.Linear(d_model * 4, d_model)
        )
    
    def forward(self, x, T, num_patches):
        """
        x: [B, N, D] 其中 N = T * num_patches + 1 (CLS)
        """
        B, N, D = x.shape
        cls_token = x[:, :1]
        patches = x[:, 1:]
        
        # 重塑为 [B, T, P, D]
        patches = patches.view(B, T, num_patches, D)
        
        # 时间注意力 (每个 patch 位置独立)
        # [B*P, T, D]
        patches_flat = patches.permute(0, 2, 1, 3).reshape(B * num_patches, T, D)
        time_out, _ = self.time_attn(patches_flat, patches_flat, patches_flat)
        patches = patches + time_out.reshape(B, num_patches, T, D).permute(0, 2, 1, 3)
        
        # 空间注意力 (每个时间步独立)
        # [B*T, P, D]
        patches_flat = patches.reshape(B * T, num_patches, D)
        space_out, _ = self.space_attn(patches_flat, patches_flat, patches_flat)
        patches = patches + space_out.reshape(B, T, num_patches, D)
        
        # 重塑回 [B, T*P, D]
        patches = patches.reshape(B, T * num_patches, D)
        
        # 加回 CLS Token
        x = torch.cat([cls_token, patches], dim=1)
        
        # MLP
        x = x + self.mlp(self.norm3(x))
        
        return x

"""
TimeSformer 的复杂度分析:

  联合时空注意力: O((T·P)²) = O(T²·P²)
  分离时空注意力: O(T·P² + T²·P)
  
  当 T=8, P=196 时:
    联合: (8×196)² = 2.5M
    分离: 8×196² + 8²×196 = 320K
    
  加速比: ~8x
"""

4. 视频分类与检测

4.1 视频分类

python 复制代码
class VideoClassifier(nn.Module):
    """
    视频分类器
    
    使用预训练的视频模型进行分类
    
    策略:
      1. 单片段: 采样一个片段进行分类
      2. 多片段: 采样多个片段,取平均
      3. 密集采样: 采样所有帧
    """
    def __init__(self, backbone, num_classes, num_clips=10):
        super().__init__()
        
        self.backbone = backbone
        self.num_clips = num_clips
        
        # 分类头
        self.head = nn.Linear(backbone.output_dim, num_classes)
    
    def forward(self, video):
        """
        video: [B, C, T, H, W]
        """
        if self.training:
            # 训练时: 单片段
            features = self.backbone(video)
            logits = self.head(features)
        else:
            # 测试时: 多片段平均
            clips = self.sample_clips(video, self.num_clips)
            
            logits = []
            for clip in clips:
                features = self.backbone(clip)
                logit = self.head(features)
                logits.append(logit)
            
            logits = torch.stack(logits).mean(dim=0)
        
        return logits
    
    def sample_clips(self, video, num_clips):
        """
        采样多个片段
        """
        T = video.shape[2]
        clip_length = min(16, T)
        
        clips = []
        for _ in range(num_clips):
            start = torch.randint(0, T - clip_length + 1, (1,)).item()
            clip = video[:, :, start:start+clip_length]
            clips.append(clip)
        
        return clips

"""
视频分类的测试策略:

  1. 单片段: 采样中心片段
  2. 多片段: 均匀采样 N 个片段
  3. 密集采样: 滑动窗口
  
  多片段 + 平均: 提高稳定性
"""

4.2 时间动作定位

复制代码
时间动作定位 (Temporal Action Localization):

  任务: 定位动作的起止时间并分类
  
  输入: 长视频
  输出: [(start_1, end_1, class_1), (start_2, end_2, class_2), ...]

  方法:
    1. 自顶向下: 生成候选片段 → 分类
    2. 自底向上: 逐帧分类 → 合并
python 复制代码
class TemporalActionLocalization(nn.Module):
    """
    时间动作定位
    
    理论:
      1. 生成候选片段 (proposal)
      2. 对每个片段分类
      3. 后处理 (NMS)
    """
    def __init__(self, feature_dim, num_classes):
        super().__init__()
        
        # 特征提取 (使用预训练模型)
        self.feature_extractor = None  # 预训练的视频模型
        
        # 候选生成网络
        self.proposal_net = nn.Sequential(
            nn.Conv1d(feature_dim, 512, 3, padding=1),
            nn.ReLU(),
            nn.Conv1d(512, 2, 1)  # 前景/背景
        )
        
        # 分类网络
        self.classifier = nn.Sequential(
            nn.AdaptiveAvgPool1d(1),
            nn.Flatten(),
            nn.Linear(feature_dim, num_classes)
        )
    
    def forward(self, video_features):
        """
        video_features: [B, D, T]
        """
        # 候选生成
        proposal_scores = self.proposal_net(video_features)  # [B, 2, T]
        
        # 分类
        class_scores = self.classifier(video_features)  # [B, num_classes]
        
        return proposal_scores, class_scores

"""
时间动作定位的评估:

  mAP@IoU:
    计算不同 IoU 阈值下的平均精度
    
    IoU 阈值: 0.5, 0.75, 0.95
    
    tIoU = |预测 ∩ 真实| / |预测 ∪ 真实|
"""

5. 视频分割

5.1 视频目标分割

复制代码
视频目标分割 (Video Object Segmentation, VOS):

  任务: 在视频中分割特定目标

  类型:
    1. 半监督 VOS: 给定第一帧的掩码,跟踪分割后续帧
    2. 无监督 VOS: 自动分割显著目标
    3. 参考 VOS: 根据参考图像分割

  挑战:
    - 目标形变
    - 遮挡
    - 快速运动
    - 相似物体干扰
python 复制代码
class VideoObjectSegmentation(nn.Module):
    """
    视频目标分割
    
    半监督: 给定第一帧掩码,分割后续帧
    
    理论:
      记忆网络: 存储历史帧的特征和掩码
      匹配: 当前帧与记忆匹配
      分割: 基于匹配结果分割
    """
    def __init__(self, feature_dim=256):
        super().__init__()
        
        # 特征编码器
        self.encoder = nn.Sequential(
            nn.Conv2d(3, 64, 3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, feature_dim, 3, padding=1),
            nn.ReLU()
        )
        
        # 记忆网络
        self.memory_key = nn.Linear(feature_dim, feature_dim)
        self.memory_value = nn.Linear(feature_dim, feature_dim)
        
        # 分割头
        self分割_head = nn.Sequential(
            nn.Conv2d(feature_dim * 2, 128, 3, padding=1),
            nn.ReLU(),
            nn.Conv2d(128, 1, 1),
            nn.Sigmoid()
        )
    
    def forward(self, frame, memory_frames, memory_masks):
        """
        frame: [B, 3, H, W] 当前帧
        memory_frames: [B, N, 3, H, W] 记忆帧
        memory_masks: [B, N, 1, H, W] 记忆掩码
        """
        # 当前帧特征
        query = self.encoder(frame)
        
        # 记忆特征
        memory_features = []
        for i in range(memory_frames.shape[1]):
            feat = self.encoder(memory_frames[:, i])
            memory_features.append(feat)
        memory_features = torch.stack(memory_features, dim=1)
        
        # 匹配 (注意力)
        query_flat = query.flatten(2).permute(0, 2, 1)  # [B, HW, D]
        memory_flat = memory_features.flatten(3).permute(0, 1, 3, 2)  # [B, N, D, HW]
        
        # 注意力匹配
        attn = torch.bmm(query_flat, memory_flat.flatten(0, 1)).view(
            query_flat.shape[0], query_flat.shape[1], memory_features.shape[1], -1
        )
        attn = torch.softmax(attn, dim=-1)
        
        # 加权聚合记忆
        memory_values = self.memory_value(memory_flat.flatten(0, 1))
        aggregated = torch.bmm(attn.flatten(2), memory_values).view(query.shape)
        
        # 分割
        combined = torch.cat([query, aggregated], dim=1)
        mask = self分割_head(combined)
        
        return mask

"""
视频分割的挑战:

  1. 目标形变: 目标形状变化
  2. 遮挡: 目标被遮挡
  3. 快速运动: 目标移动快
  4. 相似物体: 背景中有相似物体
  
  解决:
    - 记忆网络: 存储历史信息
    - 注意力匹配: 灵活的特征匹配
    - 在线更新: 随时更新目标模型
"""

5.2 全景视频分割

python 复制代码
class PanopticVideoSegmentation(nn.Module):
    """
    全景视频分割
    
    统一语义分割和实例分割的视频版本
    
    理论:
      stuff (背景): 语义分割 + 时序一致性
      things (物体): 实例分割 + 跟踪
    """
    def __init__(self, num_things, num_stuff):
        super().__init__()
        
        self.num_things = num_things
        self.num_stuff = num_stuff
        
        # 语义分割分支
        self.semantic_head = SemanticHead(num_things + num_stuff)
        
        # 实例分割分支
        self.instance_head = InstanceHead(num_things)
        
        # 跟踪分支
        self.tracking_head = TrackingHead()
    
    def forward(self, video):
        """
        video: [B, C, T, H, W]
        """
        # 语义分割
        semantic_logits = self.semantic_head(video)
        
        # 实例分割
        instance_masks, instance_ids = self.instance_head(video)
        
        # 跟踪
        tracks = self.tracking_head(instance_masks)
        
        return semantic_logits, instance_masks, tracks

6. 视频生成基础

6.1 视频生成任务

复制代码
视频生成任务:

  1. 文本到视频 (Text-to-Video):
     输入: 文本描述
     输出: 视频
     
  2. 图像到视频 (Image-to-Video):
     输入: 单张图像
     输出: 视频
     
  3. 视频预测 (Video Prediction):
     输入: 历史帧
     输出: 未来帧
     
  4. 视频插值 (Video Interpolation):
     输入: 起始帧和结束帧
     输出: 中间帧
     
  5. 视频编辑 (Video Editing):
     输入: 视频 + 编辑指令
     输出: 编辑后的视频

6.2 视频生成的挑战

复制代码
视频生成的挑战:

  1. 时间一致性:
     相邻帧应该平滑过渡
     物体应该保持一致
     
  2. 运动合理性:
     运动应该符合物理规律
     物体应该有合理的轨迹
     
  3. 计算量:
     生成 T 帧比生成 1 帧难 T 倍
     需要大量显存
     
  4. 长视频:
     生成长视频容易累积误差
     需要特殊的策略

7. 扩散模型视频生成

7.1 视频扩散模型

复制代码
视频扩散模型的核心思想:
  将扩散模型扩展到视频
  在时空维度上进行扩散

  前向过程:
    对视频的每一帧添加噪声
    
  反向过程:
    从噪声中恢复视频
    
  关键: 如何建模帧间关系
python 复制代码
class VideoDiffusionModel(nn.Module):
    """
    视频扩散模型
    
    核心组件:
      1. 时空 UNet: 处理视频的去噪网络
      2. 时间注意力: 建模帧间关系
      3. 条件注入: 文本/图像条件
    """
    def __init__(self, in_channels=3, model_channels=128, 
                 out_channels=3, num_frames=16):
        super().__init__()
        
        self.num_frames = num_frames
        
        # 时空 UNet
        self.unet = SpatioTemporalUNet(
            in_channels=in_channels,
            model_channels=model_channels,
            out_channels=out_channels,
            num_frames=num_frames
        )
        
        # 时间嵌入
        self.time_embed = nn.Sequential(
            SinusoidalPositionEmbedding(model_channels),
            nn.Linear(model_channels, model_channels * 4),
            nn.SiLU(),
            nn.Linear(model_channels * 4, model_channels)
        )
    
    def forward(self, x, t, text_embedding=None):
        """
        x: [B, C, T, H, W] 噪声视频
        t: [B] 时间步
        text_embedding: [B, L, D] 文本嵌入 (可选)
        """
        # 时间嵌入
        t_emb = self.time_embed(t)
        
        # 去噪
        noise_pred = self.unet(x, t_emb, text_embedding)
        
        return noise_pred

class SpatioTemporalUNet(nn.Module):
    """
    时空 UNet
    
    在空间 UNet 的基础上添加时间注意力
    
    结构:
      空间卷积 → 时间注意力 → 空间卷积 → ...
    """
    def __init__(self, in_channels, model_channels, out_channels, num_frames):
        super().__init__()
        
        # 空间编码器
        self.spatial_enc = nn.ModuleList([
            ResBlock(in_channels, model_channels),
            ResBlock(model_channels, model_channels * 2),
            ResBlock(model_channels * 2, model_channels * 4)
        ])
        
        # 时间注意力层
        self.time_attns = nn.ModuleList([
            TemporalAttention(model_channels),
            TemporalAttention(model_channels * 2),
            TemporalAttention(model_channels * 4)
        ])
        
        # 瓶颈
        self.bottleneck = ResBlock(model_channels * 4, model_channels * 4)
        
        # 空间解码器
        self.spatial_dec = nn.ModuleList([
            ResBlock(model_channels * 8, model_channels * 2),
            ResBlock(model_channels * 4, model_channels),
            ResBlock(model_channels * 2, model_channels)
        ])
        
        # 输出
        self.out = nn.Conv3d(model_channels, out_channels, 1)
    
    def forward(self, x, t_emb, text_embedding=None):
        """
        x: [B, C, T, H, W]
        t_emb: [B, D]
        """
        B, C, T, H, W = x.shape
        
        # 编码器
        skips = []
        for enc, t_attn in zip(self.spatial_enc, self.time_attns):
            x = enc(x)
            
            # 时间注意力
            x_flat = x.flatten(3).permute(0, 2, 3, 1)  # [B, T, HW, C]
            x_flat = t_attn(x_flat)
            x = x_flat.permute(0, 3, 1, 2).view(B, -1, T, H, W)
            
            skips.append(x)
        
        # 瓶颈
        x = self.bottleneck(x)
        
        # 解码器
        for dec in self.spatial_dec:
            skip = skips.pop()
            x = torch.cat([x, skip], dim=1)
            x = dec(x)
        
        # 输出
        x = self.out(x)
        
        return x

"""
视频扩散模型的关键技术:

  1. 时间注意力:
     建模帧间关系
     保持时间一致性
     
  2. 分层生成:
     先生成低分辨率视频
     再逐步超分辨率
     
  3. 条件注入:
     文本条件: CLIP 文本嵌入
     图像条件: 参考图像特征
"""

7.2 Stable Video Diffusion

复制代码
Stable Video Diffusion (SVD):

  基于 Stable Diffusion 的视频生成模型

  架构:
    图像条件 → 图像编码器 → 条件嵌入
                                      ↓
    噪声 → 时空 UNet → 去噪视频
              ↑
    时间步 + 文本嵌入

  训练策略:
    1. 图像预训练: 在图像上预训练 UNet
    2. 视频微调: 在视频上微调
    3. 高质量数据: 使用高质量视频数据集
python 复制代码
class StableVideoDiffusion(nn.Module):
    """
    Stable Video Diffusion
    
    基于图像条件的视频生成
    
    理论:
      使用预训练的图像扩散模型
      添加时间层进行视频生成
    """
    def __init__(self):
        super().__init__()
        
        # 图像编码器 (冻结)
        self.image_encoder = CLIPImageEncoder()
        
        # 视频 UNet (从图像 UNet 初始化)
        self.unet = SpatioTemporalUNet(
            in_channels=4,  # 潜在空间
            model_channels=320,
            out_channels=4,
            num_frames=25
        )
        
        # VAE
        self.vae = AutoencoderKL()
    
    def forward(self, video, image_condition):
        """
        video: [B, C, T, H, W]
        image_condition: [B, C, H, W] 参考图像
        """
        # 编码参考图像
        image_emb = self.image_encoder(image_condition)
        
        # 编码视频到潜在空间
        video_latent = self.vae.encode(video)
        
        # 扩散过程
        t = torch.randint(0, 1000, (video.shape[0],))
        noise = torch.randn_like(video_latent)
        noisy_latent = self.q_sample(video_latent, t, noise)
        
        # 去噪
        noise_pred = self.unet(noisy_latent, t, image_emb)
        
        return noise_pred

"""
SVD 的应用:

  1. 图像动画:
     给定一张图片,生成动画
     
  2. 视频编辑:
     编辑视频内容
     
  3. 视频插值:
     生成中间帧
"""

8. 视频预测与插值

8.1 视频预测

复制代码
视频预测 (Video Prediction):

  输入: 历史帧 [f₁, f₂, ..., f_t]
  输出: 未来帧 [f_{t+1}, f_{t+2}, ..., f_{t+T}]

  方法:
    1. 确定性预测: 直接预测未来帧
    2. 随机预测: 从分布中采样
    3. 条件预测: 基于动作/文本预测
python 复制代码
class VideoPredictionModel(nn.Module):
    """
    视频预测模型
    
    输入历史帧,预测未来帧
    
    理论:
      编码器提取历史特征
      解码器生成未来帧
    """
    def __init__(self, input_frames=4, future_frames=4):
        super().__init__()
        
        self.input_frames = input_frames
        self.future_frames = future_frames
        
        # 编码器
        self.encoder = nn.Sequential(
            nn.Conv3d(3, 64, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.MaxPool3d(kernel_size=(2, 2, 2))
        )
        
        # 循环网络 (LSTM)
        self.rnn = nn.LSTM(128, 256, batch_first=True)
        
        # 解码器
        self.decoder = nn.Sequential(
            nn.ConvTranspose3d(256, 128, kernel_size=(2, 2, 2), stride=(2, 2, 2)),
            nn.ReLU(),
            nn.Conv3d(128, 64, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.ReLU(),
            nn.Conv3d(64, 3, kernel_size=(3, 3, 3), padding=(1, 1, 1)),
            nn.Sigmoid()
        )
    
    def forward(self, history_frames):
        """
        history_frames: [B, C, T, H, W]
        """
        # 编码历史帧
        features = self.encoder(history_frames)
        
        # 重塑为序列
        B, C, T, H, W = features.shape
        features = features.flatten(3).permute(0, 2, 1, 3).reshape(B, T, -1)
        
        # RNN 处理
        output, (h, c) = self.rnn(features)
        
        # 生成未来帧
        future_features = []
        for _ in range(self.future_frames):
            output, (h, c) = self.rnn(output[:, -1:], (h, c))
            future_features.append(output)
        
        future_features = torch.cat(future_features, dim=1)
        future_features = future_features.reshape(B, -1, C, H, W).permute(0, 2, 1, 3, 4)
        
        # 解码
        future_frames = self.decoder(future_features)
        
        return future_frames

"""
视频预测的挑战:

  1. 不确定性: 未来有多种可能
  2. 模糊: 预测往往模糊
  3. 累积误差: 自回归生成会累积误差
  4. 长期预测: 长期预测困难
"""

8.2 视频插值

python 复制代码
class VideoInterpolation(nn.Module):
    """
    视频插值模型
    
    输入两帧,生成中间帧
    
    理论:
      光流估计: 估计两帧之间的运动
      融合: 基于光流融合两帧
    """
    def __init__(self):
        super().__init__()
        
        # 光流估计网络
        self.flow_estimator = FlowEstimationNet()
        
        # 融合网络
        self融合_net = nn.Sequential(
            nn.Conv2d(3 * 2 + 2, 64, 3, padding=1),  # 两帧 + 光流
            nn.ReLU(),
            nn.Conv2d(64, 64, 3, padding=1),
            nn.ReLU(),
            nn.Conv2d(64, 3, 3, padding=1),
            nn.Sigmoid()
        )
    
    def forward(self, frame1, frame2):
        """
        frame1: [B, 3, H, W]
        frame2: [B, 3, H, W]
        """
        # 估计光流
        flow_forward = self.flow_estimator(frame1, frame2)
        flow_backward = self.flow_estimator(frame2, frame1)
        
        # 变形
        warped1 = warp_frame(frame1, flow_forward * 0.5)
        warped2 = warp_frame(frame2, flow_backward * 0.5)
        
        # 融合
        combined = torch.cat([warped1, warped2, flow_forward], dim=1)
        interpolated = self融合_net(combined)
        
        return interpolated

"""
视频插值的方法:

  1. 基于光流: 估计运动,变形融合
  2. 基于核: 学习插值核
  3. 基于相位: 频域方法
  4. 基于深度学习: 端到端学习
"""

9. 评估指标与数据集

9.1 评估指标

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                    视频任务评估指标                                  │
├─────────────────┬───────────────────────────────────────────────────┤
│  任务            │  指标                                            │
├─────────────────┼───────────────────────────────────────────────────┤
│  动作识别        │  Top-1 Accuracy, Top-5 Accuracy                 │
│                 │  mAP (多标签分类)                                 │
├─────────────────┼───────────────────────────────────────────────────┤
│  时间动作定位    │  mAP@tIoU (0.5, 0.75, 0.95)                     │
│                 │  Average mAP                                      │
├─────────────────┼───────────────────────────────────────────────────┤
│  视频生成        │  FVD (Frechet Video Distance)                    │
│                 │  IS (Inception Score)                             │
│                 │  LPIPS, SSIM, PSNR                                │
├─────────────────┼───────────────────────────────────────────────────┤
│  视频分割        │  mIoU (语义), AP (实例)                          │
│                 │  J&F (VOS 指标)                                   │
├─────────────────┼───────────────────────────────────────────────────┤
│  视频预测        │  SSIM, PSNR, LPIPS                               │
│                 │  FVD                                               │
└─────────────────┴───────────────────────────────────────────────────┘
python 复制代码
class VideoMetrics:
    """视频评估指标"""
    
    @staticmethod
    def top_k_accuracy(predictions, labels, k=1):
        """
        Top-K 准确率
        """
        _, pred_topk = predictions.topk(k, dim=1)
        correct = pred_topk.eq(labels.view(-1, 1).expand_as(pred_topk))
        return correct.float().sum(1).mean().item()
    
    @staticmethod
    def temporal_iou(pred_segments, gt_segments):
        """
        时间 IoU
        
        tIoU = |预测 ∩ 真实| / |预测 ∪ 真实|
        """
        intersection_start = torch.max(pred_segments[:, 0], gt_segments[:, 0])
        intersection_end = torch.min(pred_segments[:, 1], gt_segments[:, 1])
        
        intersection = torch.clamp(intersection_end - intersection_start, min=0)
        
        pred_duration = pred_segments[:, 1] - pred_segments[:, 0]
        gt_duration = gt_segments[:, 1] - gt_segments[:, 0]
        
        union = pred_duration + gt_duration - intersection
        
        iou = intersection / (union + 1e-8)
        
        return iou
    
    @staticmethod
    def fvd(real_features, fake_features):
        """
        FVD (Frechet Video Distance)
        
        类似于 FID,但用于视频
        
        FVD = ‖μ_r - μ_f‖² + Tr(Σ_r + Σ_f - 2(Σ_r Σ_f)^(1/2))
        """
        mu_real = real_features.mean(dim=0)
        mu_fake = fake_features.mean(dim=0)
        
        sigma_real = torch.cov(real_features.T)
        sigma_fake = torch.cov(fake_features.T)
        
        diff = mu_real - mu_fake
        
        covmean = torch.linalg.sqrtm(sigma_real @ sigma_fake)
        
        fvd = diff @ diff + torch.trace(sigma_real + sigma_fake - 2 * covmean)
        
        return fvd.real

"""
FVD 的理论:

  FVD 衡量生成视频与真实视频的分布距离
  
  使用视频特征 (如 I3D 特征)
  计算 Fréchet 距离
  
  越低越好
"""

9.2 主要数据集

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                    视频数据集                                        │
├─────────────────┬───────────┬───────────────────────────────────────┤
│  数据集          │  规模     │  用途                                 │
├─────────────────┼───────────┼───────────────────────────────────────┤
│  Kinetics-400   │  300K 视频│  动作识别 (400 类)                    │
│  Kinetics-700   │  650K 视频│  动作识别 (700 类)                    │
│  UCF-101        │  13K 视频 │  动作识别 (101 类)                    │
│  HMDB-51        │  7K 视频  │  动作识别 (51 类)                     │
│  ActivityNet    │  20K 视频 │  时间动作定位                         │
│  THUMOS         │  1K 视频  │  时间动作定位                         │
│  DAVIS          │  60 视频  │  视频目标分割                         │
│  YouTube-VOS    │  4K 视频  │  视频目标分割                         │
│  WebVid-10M     │  10M 视频 │  视频生成预训练                       │
│  UCF-101        │  13K 视频 │  视频生成评估                         │
└─────────────────┴───────────┴───────────────────────────────────────┘

10. 应用与前沿

10.1 应用领域

复制代码
视频理解与生成的应用:

  1. 自动驾驶:
     视频理解: 场景理解、行为预测
     3D 检测: 多帧融合
     
  2. 安防监控:
     行为分析: 异常检测
     人员跟踪: 跨摄像头跟踪
     
  3. 短视频:
     内容理解: 标签、分类
     推荐: 基于内容的推荐
     生成: 自动剪辑
     
  4. 影视制作:
     视频生成: AI 生成视频
     视频编辑: 自动编辑
     特效: 视觉特效
     
  5. 医学:
     手术视频: 动作识别
     医学影像: 时序分析
     
  6. 体育:
     动作分析: 运动员动作
     战术分析: 比赛分析

10.2 前沿方向

复制代码
视频理解与生成的前沿:

  1. 长视频理解:
     处理数分钟甚至数小时的视频
     层次化表示
     
  2. 高质量视频生成:
     Sora 等模型
     长视频生成
     
  3. 视频编辑:
     文本引导的视频编辑
     保持一致性
     
  4. 多模态视频理解:
     视觉 + 音频 + 文本
     统一理解
     
  5. 实时视频处理:
     边缘设备部署
     低延迟推理
     
  6. 3D 视频:
     3D 场景视频
     自由视角视频

附录

A. 视频技术发展时间线

复制代码
2014  ──┬──  双流网络
        │
2015  ──┼──  C3D (3D 卷积)
        │
2017  ──┼──  I3D (膨胀 3D 卷积)
        │
2019  ──┼──  SlowFast
        │
2020  ──┼──  X3D (高效 3D 网络)
        │
2021  ──┼──  TimeSformer (视频 Transformer)
        │
2022  ──┼──  VideoMAE (掩码自编码器)
        │
2023  ──┼──  Stable Video Diffusion
        │
2024  ──┼──  Sora (大规模视频生成)
        │
2025+ ──┴──  更长、更高质量的视频生成

B. 核心公式速查

公式 含义
C® = ∫ T(t)·σ·c dt 体渲染方程
tIoU = |P∩G| / |P∪G| 时间交并比
FVD = ‖μ_r-μ_f‖² + Tr(Σ_r+Σ_f-2√(Σ_rΣ_f)) Frechet 视频距离
Attention(Q,K,V) = softmax(QK^T/√d)V 注意力机制

C. 推荐资源

  • Feichtenhofer, C., et al. (2019). SlowFast Networks
  • Bertasius, G., et al. (2021). TimeSformer
  • Tong, Z., et al. (2022). VideoMAE
  • Blattmann, A., et al. (2023). Stable Video Diffusion
相关推荐
韦胖漫谈IT1 小时前
Transformer:一篇论文如何改变 AI 世界
人工智能·深度学习·transformer
中科院提名者1 小时前
BERT 模型的运行机制及DistilBERT 的蒸馏压缩过程
人工智能·深度学习·bert
Deitymoon1 小时前
RV1126——音视频开发环境搭建、固件烧录、网络调试、demo运行
音视频
西安同步高经理1 小时前
国产音频频谱分析仪使用案例,多通道音频分析仪,音频频谱分析仪
大数据·人工智能·音视频
chenying9981791 小时前
掩码扩散语音克隆:参考音频为什么会被噪声“污染“?
人工智能·音视频·语音合成
极光代码工作室2 小时前
基于深度学习的文本自动摘要系统
人工智能·python·深度学习·神经网络
古道青阳2 小时前
构建工业级短视频生成流水线:Playwright + FFmpeg 自动化指南
运维·自动化·音视频
蒟蒻的贤2 小时前
从线性分类器到两层神经网络:为什么我们需要非线性?
人工智能·深度学习·神经网络
zy_destiny2 小时前
【大模型应用】用千问大模型实现屋顶材质分类算法实现
人工智能·深度学习·机器学习·计算机视觉·数据挖掘·材质·通义千问