跳转至

高分辨率与视频理解技术

更新日期:2026-04-15


一、高分辨率图像处理

1.1 问题

ViT 通常训练在 224/336 像素。直接 resize 丢失细节(尤其 OCR、细粒度识别)。

1.2 主流方案对比


二、AnyRes (LLaVA-NeXT)

def anyres_process(image, base_res=336, max_tiles=6):
    W, H = image.size

    # 找最优分割
    best_grid = find_best_grid(W, H, base_res, max_tiles)
    # 例: 1344×672 → (4,2), 1008×504 → (3,2)

    # 生成两种视图
    global_view = resize(image, (base_res, base_res))
    local_views = []
    for r in range(best_grid[0]):
        for c in range(best_grid[1]):
            tile = crop(image, r, c, base_res)
            local_views.append(tile)

    return [global_view] + local_views

# 输入 token 数: 576 × (1 + n_tiles)
# 典型: 576 × 7 = 4032 tokens per image
# 1344x672 图片 → 5 tiles → ~3456 tokens

三、Qwen2-VL 的 Native Dynamic

Qwen2-VL 用 2D-RoPE 让 ViT 原生支持任意分辨率。参考 Qwen2-VL (Bai et al., 2024)

def qwen2vl_vision(image):
    # 1. Smart resize: 保持宽高比
    H, W = smart_resize(image, 
        min_pixels=2562828,   # 最小分辨率
        max_pixels=12802828,  # 最大分辨率
        patch_size=14
    )
    image = resize(image, (H, W))

    # 2. Patch embed
    patches = patch_embed_14x14(image)  # (H/14) × (W/14) patches

    # 3. 2D-RoPE 位置编码 (关键!)
    #    前半维度编码行位置 y
    #    后半维度编码列位置 x
    positions_2d = make_2d_positions(H//14, W//14)
    patches = apply_2d_rope(patches, positions_2d)

    # 4. 2×2 Pooling 压缩
    patches = pool_2x2(patches)  # (H/28) × (W/28)

    return patches


四、视频理解

4.1 核心挑战

挑战 描述 后果
Token 爆炸 1 分钟 24fps 视频 = 1440 帧 × 576 patches = ~830k tokens 长 context 模型也爆
冗余 相邻帧 95%+ 相似 浪费 attention compute
时序 vs 空间 哪个 patch 跟哪个相关?跨帧还是跨位置? 简单 flatten 丢时序
关键帧检测 哪些帧最 informative? 需要 priori 或 learned

4.2 视频处理策略

flowchart LR
    raw["1 分钟<br/>24 fps × 256² 视频"]
    s1["策略 1<br/>均匀采样<br/>16 帧"]
    s2["策略 2<br/>关键帧<br/>动作 / 场景变化"]
    s3["策略 3<br/>低 fps + token 压缩<br/>(Qwen2-VL)"]
    s4["策略 4<br/>3D Conv tokenizer<br/>(Cosmos)"]

    raw --> s1
    raw --> s2
    raw --> s3
    raw --> s4

    classDef stage fill:#fff,stroke:#cc785c,color:#1a1a1a;
    class raw,s1,s2,s3,s4 stage
策略 Token 数(1 分钟) 信息保留 适合
均匀采样 16 帧 ~9k 中(错过细节) 短视频 QA
关键帧采样 ~9k 高(自适应) 长视频摘要
Qwen2-VL 低 fps + 压缩 ~5-30k 长视频理解
3D 卷积 token ~3-10k 极高 视频生成 / 世界模型

4.3 策略实现

# 策略 1: 均匀采样 (最常用)
def uniform_sample(video, n_frames=16):
    total = len(video)
    indices = linspace(0, total-1, n_frames).int()
    frames = [video[i] for i in indices]
    # 每帧独立编码
    tokens = [vision_encoder(f) for f in frames]
    return concat(tokens)
    # 16 frames × 576 tokens = 9216 tokens

# 策略 2: 关键帧
def keyframe_sample(video, n_frames=16):
    # 用 motion/scene change 检测关键帧
    diffs = [frame_diff(video[i], video[i+1]) for i in range(len(video)-1)]
    keyframe_idx = find_peaks(diffs, top_k=n_frames)
    return [vision_encoder(video[i]) for i in keyframe_idx]

# 策略 3: 低帧率 + Token 压缩 (Qwen2-VL)
def qwen2vl_video(video, fps=2):
    frames = sample_at_fps(video, fps)
    frame_tokens = [vision_encoder(f) for f in frames]
    # 时序压缩: 相邻帧相似 token 合并
    compressed = temporal_merge(frame_tokens, threshold=0.9)
    return compressed

五、时序建模

5.1 时间编码

# 方法 1: 简单的时间戳作为 prompt
# "Frame 1 (0.0s): [tokens]  Frame 2 (0.5s): [tokens] ..."

# 方法 2: 时间 RoPE (3D-RoPE)
# 将 2D-RoPE 扩展到 3D: (T, H, W)
def apply_3d_rope(tokens, t, h, w):
    # tokens 按 (T, H, W) 排列
    # 将维度分为三份, 分别编码 t, h, w
    d_per_dim = d // 3
    tokens[:, :d_per_dim] = rotate(tokens[:, :d_per_dim], t * theta)
    tokens[:, d_per_dim:2d_per_dim] = rotate(tokens[:, d_per_dim:2d_per_dim], h * theta)
    tokens[:, 2d_per_dim:] = rotate(tokens[:, 2d_per_dim:], w * theta)
    return tokens

# Qwen2-VL 使用类似的 mRope (Multimodal RoPE)

5.2 长视频理解

flowchart LR
    long["1+ 小时<br/>视频"]
    chunk["分块<br/>(每 10 分钟一段)"]
    sum["每段摘要<br/>(LLM)"]
    global["全局上下文<br/>(摘要拼接)"]
    qa["问答<br/>(检索 + 生成)"]

    long --> chunk --> sum --> global --> qa

    classDef stage fill:#fff,stroke:#cc785c,color:#1a1a1a;
    class long,chunk,sum,global,qa stage

长视频(电影、监控、讲座)的处理策略:

  • 分层摘要:分块 → 段摘要 → 视频级摘要
  • 检索增强:把每段当 RAG document,问答时检索相关段落
  • 状态压缩:类似 RNN 的 hidden state,每段更新一个紧凑 representation

5.3 代表模型

模型 视频上下文上限 策略
Qwen2.5-VL 60 分钟 低 fps + 时序 RoPE + token 压缩
Gemini 1.5 Pro 2 小时 1M context window 直接装
InternVL Video 30 分钟 关键帧采样 + 时序 attention
LongVA 2 小时 DPO 长视频对齐
MovieChat 长电影 分层 memory(短期 + 长期)

六、视频生成

视频生成属于另一个领域,但正在与 VLM 融合。参考 F5 文档深入。


七、追问延伸

问题 方向 为什么 / 深入分析
视频理解的 scaling law 是什么样? 研究较少,初步发现性能主要受 帧数 x 帧分辨率 x 模型规模 三者制约 视频 token 数 = 帧数 x 每帧 token 数,增加任一维度都需要更大上下文窗口和计算量;目前缺乏像 Chinchilla 那样的系统性 scaling 研究
如何处理超长视频(电影级)? 分段摘要(hierarchical summarization)/ 依赖 1M+ 超长上下文窗口 2 小时电影即使 1fps 也有 7200 帧,token 数超过百万;分段摘要是信息有损的折中方案,超长上下文是终极方向但推理成本极高
视频生成和理解会统一吗? 趋势是统一(如 Emu、CoDi 等尝试),但当前生成和理解仍是独立模型 生成需要逐像素重建(decoder 重),理解只需语义提取(encoder 轻),两者计算模式差异大;统一架构的效率问题尚未解决
实时视频理解如何做? 流式编码(逐帧/逐段送入 ViT)+ 滑动窗口维护有限历史上下文 实时要求延迟 <100ms,不可能等待完整视频;滑动窗口保证内存常量,但会丢失早期信息

参考文献

  • [1] Bai et al. Qwen2-VL. 2024. 论文

  • [2] Liu et al. LLaVA-NeXT. 2024. 博客

  • [3] Chen et al. InternVL. 2023. 论文

  • [4] Lin et al. Video-LLaVA. 2023. 论文

  • [5] Zhang et al. LongVA. 2024. 论文

  • [6] OpenAI. Sora. 2024. 博客

  • [7] HunyuanVideo. 2024. 论文


上级 · F. 多模态 VLM