高分辨率与视频理解技术¶
更新日期: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