第七篇:视觉大模型时代#

从多模态基础模型到视觉AGI的演进之路

篇章概述#

视觉大模型(Vision-Language Model, VLM)是2023-2024年计算机视觉领域最重要的技术突破。本篇深入讲解:

  • 多模态基础模型(CLIP、BLIP、LLaVA)
  • 前沿视觉大模型(Florence-2、GPT-4V、Gemini)
  • 3D视觉与视频理解新进展

为什么学习视觉大模型?#

  1. 范式转变: 从单一任务模型到统一多模态模型
  2. 零样本能力: 无需训练即可完成新任务
  3. 产业应用: 正在重塑计算机视觉应用格局
  4. 技术前沿: 是通向AGI的重要路径

章节组织#

第16章:多模态基础模型#

核心主题: CLIP、BLIP、LLaVA三大基础模型

  • 16.1 CLIP:视觉-语言对比学习

    • 对比学习原理与双编码器架构
    • 零样本分类、图像检索
    • transformers库实战
  • 16.2 BLIP系列:视觉问答

    • BLIP-2架构:Q-Former设计
    • 图像描述、VQA任务
    • 量化优化与部署
  • 16.3 LLaVA:大语言模型+视觉

    • 视觉指令微调方法
    • 多模态对话系统
    • LLaVA 1.5/1.6新特性
  • 16.4 实战:多模态理解应用

    • 商品图像搜索
    • 智能客服机器人
    • 图像内容审核

技术栈: transformers, torch, PIL, accelerate

代码文件:

  • code/clip_zero_shot.py - CLIP零样本分类
  • code/blip2_vqa.py - BLIP-2视觉问答
  • code/llava_chat.py - LLaVA多模态对话
  • code/multimodal_app.py - 综合应用示例

第17章:视觉大模型前沿#

核心主题: 工业级VLM与商业API

  • 17.1 Florence-2:微软视觉基础模型

    • 统一提示词范式
    • 支持10+视觉任务
    • 开源可商用(MIT协议)
  • 17.2 GPT-4V/GPT-4o:多模态GPT

    • Vision API调用方法
    • 提示词工程技巧
    • 实际应用案例
  • 17.3 Gemini Vision:Google多模态

    • Gemini 1.5/2.0对比
    • 原生多模态能力
    • 视频理解特性
  • 17.4 实战:VLM API调用与应用

    • 文档理解与OCR
    • 视频分析应用
    • 成本优化策略

技术栈: openai, google-generativeai, anthropic

代码文件:

  • code/florence2_demo.py - Florence-2多任务演示
  • code/gpt4v_api.py - GPT-4V API调用
  • code/gemini_vision.py - Gemini Vision使用
  • code/vlm_comparison.py - VLM性能对比

第18章:3D视觉与视频理解#

核心主题: 从2D到3D/4D的扩展

  • 18.1 NeRF:神经辐射场

    • 隐式3D表示
    • 体渲染原理
    • Instant-NGP加速
  • 18.2 Gaussian Splatting:3D重建新范式

    • 显式3D高斯表示
    • 实时渲染能力
    • 与NeRF对比
  • 18.3 Video Understanding:视频分类与检测

    • TimeSformer、VideoMAE
    • 视频VLM(Video-LLaVA)
    • 时序动作检测
  • 18.4 实战:3D重建项目

    • 手机拍摄到3D模型
    • 场景重建流程
    • Web可视化展示

技术栈: torch, trimesh, open3d, gradio

代码文件:

  • code/nerf_basic.py - NeRF基础实现
  • code/gaussian_splatting.py - 3DGS演示
  • code/video_vlm.py - 视频理解模型
  • code/3d_reconstruction.py - 3D重建流程

技术路线图#

传统CV              多模态基础           视觉大模型              未来方向
  |                    |                    |                      |
ImageNet          CLIP(2021)         Florence-2(2024)      视觉AGI
ResNet            BLIP(2022)         GPT-4V(2023)          具身智能
Detection    -->  LLaVA(2023)   -->  Gemini(2024)    -->   世界模型
Segmentation      BLIP-2(2023)       GPT-4o(2024)          多模态推理

环境配置#

基础依赖#

# 核心库
pip install transformers>=4.35.0 torch torchvision
pip install accelerate bitsandbytes  # 量化加速
pip install pillow requests datasets

# API客户端
pip install openai>=1.0.0
pip install google-generativeai
pip install anthropic

# 3D/视频
pip install open3d trimesh
pip install opencv-python decord

GPU要求#

模型最小显存推荐显存量化方案
CLIP2GB4GB-
BLIP-26GB12GBint8/int4
LLaVA-7B14GB24GB4bit量化
Florence-24GB8GBfloat16

学习建议#

学习路径#

  1. Week 1-2: 第16章多模态基础

    • 理解对比学习原理
    • 掌握CLIP、BLIP使用
    • 完成零样本分类实验
  2. Week 3: 第17章前沿VLM

    • 学习Florence-2统一范式
    • 实践商业API调用
    • 对比不同VLM性能
  3. Week 4: 第18章3D/视频

    • 理解NeRF/3DGS原理
    • 尝试3D重建项目
    • 探索视频VLM应用

实践项目推荐#

  1. 初级: CLIP图像搜索引擎
  2. 中级: LLaVA多模态客服
  3. 高级: Florence-2通用视觉助手
  4. 进阶: 3D场景重建系统

参考资源#

论文必读#

开源项目#

在线资源#

关键技术对比#

VLM模型选型指南#

模型开源参数量优势适用场景
CLIP0.4B零样本分类强图像搜索、检索
BLIP-24BVQA性能优秀视觉问答、描述生成
LLaVA7-13B对话能力强多模态助手
Florence-20.77B统一多任务通用视觉API
GPT-4V-综合能力最强复杂推理、文档理解
Gemini-原生多模态、视频理解长视频分析、多模态生成

应用场景匹配#

  • 电商搜索: CLIP(以图搜图) + Florence-2(商品属性提取)
  • 智能客服: LLaVA(多轮对话) + GPT-4V(复杂问题)
  • 内容审核: Florence-2(快速检测) + Gemini(视频审核)
  • 文档理解: GPT-4V(表格/图表) + Florence-2(OCR)
  • 3D重建: NeRF/3DGS(场景重建) + VLM(语义理解)

本篇特色#

  1. 全栈覆盖: 从开源模型到商业API
  2. 代码可运行: 所有示例基于最新版本
  3. 实战导向: 每章包含完整应用案例
  4. 性能对比: 详细评测数据与成本分析
  5. 前沿跟踪: 涵盖2024年最新进展

学习提示:

  • 视觉大模型是快速发展的领域,建议关注Hugging Face和ArXiv最新论文
  • 商业API(GPT-4V/Gemini)需要付费,可先用开源模型学习
  • 3D视觉部分计算密集,建议在GPU环境运行

下一步: 开始学习第16章:多模态基础模型,掌握CLIP、BLIP、LLaVA核心技术!


第16章:多模态基础模型#

CLIP、BLIP、LLaVA - 连接视觉与语言的桥梁

本章概述#

多模态基础模型是视觉大模型时代的基石。本章深入讲解三个里程碑式的模型:

  • CLIP: OpenAI的对比学习范式,开启零样本视觉新时代
  • BLIP系列: Salesforce的视觉问答专家
  • LLaVA: 将大语言模型与视觉完美结合的开创者

通过本章学习,你将掌握多模态模型的核心原理、使用方法和实际应用。

16.1 CLIP:视觉-语言对比学习#

核心思想#

CLIP(Contrastive Language-Image Pre-training)通过对比学习将图像和文本映射到同一语义空间,实现零样本分类。

关键创新:

  1. 在4亿图像-文本对上训练
  2. 双编码器架构(Image Encoder + Text Encoder)
  3. 对比损失函数建立视觉-语言对齐

模型架构#

Image Input                Text Input
     |                          |
Image Encoder              Text Encoder
(ViT-L/14)                (Transformer)
     |                          |
  Image                      Text
Embedding                 Embedding
     |                          |
     +--------Cosine Sim--------+
              (Similarity Score)

技术细节:

  • Image Encoder: Vision Transformer (ViT-L/14, 400M参数)
  • Text Encoder: Transformer with masked self-attention
  • 训练目标: InfoNCE对比损失
  • 输出维度: 768维特征向量

使用transformers库#

from transformers import CLIPProcessor, CLIPModel
import torch
from PIL import Image

# 加载模型(自动下载)
model = CLIPModel.from_pretrained("openai/clip-vit-large-patch14")
processor = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")

# 准备输入
image = Image.open("image.jpg")
text_candidates = ["a photo of a cat", "a photo of a dog", "a photo of a bird"]

# 编码
inputs = processor(
    text=text_candidates,
    images=image,
    return_tensors="pt",
    padding=True
)

# 推理
with torch.no_grad():
    outputs = model(**inputs)
    logits_per_image = outputs.logits_per_image  # (1, 3)
    probs = logits_per_image.softmax(dim=1)  # (1, 3)

# 结果
print(f"概率分布: {probs[0].tolist()}")
predicted_label = text_candidates[probs.argmax()]
print(f"预测类别: {predicted_label}")

零样本分类原理#

CLIP无需任何训练即可对新类别分类:

  1. 文本提示工程: 将类别转换为描述性文本

    # 基础提示
    texts = [f"a photo of a {label}" for label in class_names]
    
    # 高级提示(提升性能)
    templates = [
        "a photo of a {}",
        "a rendering of a {}",
        "a cropped photo of a {}",
        # ... 80个模板集成
    ]
  2. 相似度计算: 图像与所有文本的余弦相似度

  3. Softmax归一化: 得到概率分布

性能表现#

数据集准确率备注
ImageNet76.2%零样本(top-1)
CIFAR-1094.9%零样本
CIFAR-10077.4%零样本
Oxford-Pets93.8%零样本

对比: ResNet-50在ImageNet上需要100万标注样本才能达到76%。

应用场景#

  1. 以图搜图: 将图像和商品描述对齐
  2. 内容审核: 零样本检测不适内容
  3. 图像标注: 自动生成标签
  4. 跨模态检索: 文本搜索图像或反之

代码实战#

参见 code/chapter16_multimodal/clip_zero_shot.py - 完整的零样本分类示例,包括:

  • 多类别分类
  • 自定义提示模板
  • 批量图像处理
  • 可视化结果

16.2 BLIP系列:视觉问答#

BLIP-2架构#

BLIP-2(Bootstrapping Language-Image Pre-training v2)是Salesforce在2023年推出的视觉-语言模型。

核心创新: Q-Former

Frozen Image       Q-Former        Frozen LLM
Encoder          (Learnable)      (OPT-2.7B)
   |                 |                 |
 ViT-g      32个Query Tokens      Language
(1.4B)           (762M)            Model
   |                 |                 |
   +-------Cross Attention---------+
                     |
                Text Output

三大优势:

  1. 参数高效: 只训练Q-Former(762M),冻结图像/文本编码器
  2. 任务通用: 支持图像描述、VQA、对话
  3. 性能强大: 在多个基准上超越Flamingo(80B参数)

模型规格#

模型变体参数量LLM基座显存需求
blip2-opt-2.7b4BOPT-2.7B14GB
blip2-flan-t5-xl4BFlan-T515GB
blip2-opt-6.7b8BOPT-6.7B26GB

使用示例#

图像描述生成:

from transformers import Blip2Processor, Blip2ForConditionalGeneration
import torch

# 加载模型(推荐float16)
processor = Blip2Processor.from_pretrained("Salesforce/blip2-opt-2.7b")
model = Blip2ForConditionalGeneration.from_pretrained(
    "Salesforce/blip2-opt-2.7b",
    torch_dtype=torch.float16,
    device_map="auto"
)

# 生成描述
image = Image.open("image.jpg")
inputs = processor(image, return_tensors="pt").to("cuda", torch.float16)

generated_ids = model.generate(**inputs, max_new_tokens=50)
caption = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(f"图像描述: {caption}")

视觉问答(VQA):

# 提问
question = "What is the color of the car?"
inputs = processor(image, question, return_tensors="pt").to("cuda", torch.float16)

# 生成答案
generated_ids = model.generate(**inputs, max_new_tokens=20)
answer = processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
print(f"回答: {answer}")

量化优化#

8-bit量化(显存减半):

model = Blip2ForConditionalGeneration.from_pretrained(
    "Salesforce/blip2-opt-2.7b",
    load_in_8bit=True,
    device_map="auto"
)
# 显存: 14GB -> 7GB

4-bit量化(显存1/4):

from transformers import BitsAndBytesConfig

quantization_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16
)

model = Blip2ForConditionalGeneration.from_pretrained(
    "Salesforce/blip2-opt-2.7b",
    quantization_config=quantization_config,
    device_map="auto"
)
# 显存: 14GB -> 3.5GB

性能基准#

任务数据集BLIP-2Flamingo-80B
VQAVQAv282.282.0
图像描述COCO144.5138.1
视觉推理NLVR285.384.0

代码实战#

参见 code/chapter16_multimodal/blip2_vqa.py - BLIP-2视觉问答完整示例:

  • 图像描述生成
  • 多轮问答对话
  • 量化加载与性能对比
  • 批量处理优化

16.3 LLaVA:大语言模型+视觉#

模型概述#

LLaVA(Large Language and Vision Assistant)是威斯康星大学在2023年提出的开源视觉对话模型。

核心思想: 将视觉编码器与大语言模型通过简单的线性层连接,在GPT-4生成的多模态指令数据上微调。

架构设计#

Image Input
    |
Vision Encoder ────────> Projection Layer ────> LLM
(CLIP ViT-L/14)         (Linear Layer)      (Vicuna-7B/13B)
    |                         |                    |
768D Embedding  ────>  4096D Embedding  ──> Text Generation

关键组件:

  1. Vision Encoder: 预训练CLIP ViT-L/14(冻结)
  2. Projection Layer: 简单线性层(768→4096),唯一训练的连接层
  3. LLM: Vicuna-7B/13B(LoRA微调)

训练流程#

两阶段训练:

  1. Stage 1: 特征对齐 (预训练)

    • 数据: 595K图像-文本对(CC3M过滤)
    • 训练: 只训练Projection Layer
    • 目标: 将视觉特征映射到LLM空间
  2. Stage 2: 指令微调

    • 数据: 158K多模态指令(GPT-4生成)
    • 训练: Projection + LLM(LoRA)
    • 目标: 提升对话和推理能力

使用transformers库#

LLaVA 1.5官方模型:

from transformers import AutoProcessor, LlavaForConditionalGeneration
import torch

# 加载模型
model_id = "llava-hf/llava-1.5-7b-hf"
model = LlavaForConditionalGeneration.from_pretrained(
    model_id,
    torch_dtype=torch.float16,
    device_map="auto"
)
processor = AutoProcessor.from_pretrained(model_id)

# 构建对话
conversation = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "描述这张图片中的内容。"}
        ]
    }
]

# 生成回复
prompt = processor.apply_chat_template(conversation, add_generation_prompt=True)
inputs = processor(images=image, text=prompt, return_tensors="pt").to("cuda", torch.float16)

output = model.generate(**inputs, max_new_tokens=200)
response = processor.decode(output[0], skip_special_tokens=True)
print(response)

LLaVA 1.5 vs 1.6 对比#

特性LLaVA 1.5LLaVA 1.6 (Next)
发布时间2023年10月2024年1月
基座LLMVicunaMistral/Nous
图像分辨率336×336672×672
多图支持
性能(MMBench)67.772.3

推荐: 生产环境使用LLaVA 1.5(更稳定),研究尝试1.6。

4-bit量化部署#

from transformers import BitsAndBytesConfig

# 配置4-bit量化
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.float16
)

# 加载量化模型
model = LlavaForConditionalGeneration.from_pretrained(
    "llava-hf/llava-1.5-7b-hf",
    quantization_config=bnb_config,
    device_map="auto"
)
# 显存: 28GB -> 5GB (减少82%)

性能基准#

任务数据集LLaVA 1.5GPT-4V
视觉问答VQAv278.577.2
视觉推理GQA62.0-
多模态基准MMBench67.775.1
OCRTextVQA58.278.0

亮点: 作为开源模型,LLaVA在某些任务上接近甚至超过闭源GPT-4V。

应用示例#

  1. 智能图像助手

    questions = [
        "图片中有什么物体?",
        "这些物体的位置关系是什么?",
        "根据图片内容,这可能是什么场景?"
    ]
  2. 视觉内容审核

    prompt = "请判断这张图片是否包含不适内容,并说明原因。"
  3. 教育辅助

    prompt = "这是一道数学题的图片,请解答并说明步骤。"

代码实战#

参见 code/chapter16_multimodal/llava_chat.py - LLaVA多模态对话系统:

  • 单轮/多轮对话
  • 图像理解与推理
  • 量化部署方案
  • Gradio界面集成

16.4 实战:多模态理解应用#

项目1: 商品图像搜索引擎#

需求: 用户上传商品图片,搜索相似商品。

技术方案:

# 1. 使用CLIP构建图像索引
image_features = model.get_image_features(pixel_values=images)
# 存入向量数据库(FAISS/Milvus)

# 2. 查询时编码并检索
query_features = model.get_image_features(pixel_values=query_image)
similar_indices = faiss_index.search(query_features, k=10)

# 3. BLIP-2生成商品描述
description = blip2_model.generate(query_image)

完整代码: code/chapter16_multimodal/multimodal_app.py

项目2: 智能客服机器人#

需求: 用户发送商品图片+文字问题,AI回答。

技术方案:

# 使用LLaVA处理多模态输入
conversation = [
    {
        "role": "user",
        "content": [
            {"type": "image"},
            {"type": "text", "text": "这个商品如何使用?"}
        ]
    }
]
response = llava_model.chat(conversation)

增强功能:

  • 多轮对话记忆
  • 商品知识库检索(RAG)
  • 情感分析与意图识别

项目3: 图像内容审核系统#

需求: 自动检测不适内容(暴力、色情、政治敏感)。

多模型集成:

# 1. CLIP快速初筛(零样本)
labels = ["正常内容", "暴力内容", "色情内容", "政治敏感"]
probs = clip_classify(image, labels)

# 2. 高置信度直接通过/拒绝
if probs.max() > 0.95:
    return probs.argmax()

# 3. 低置信度用LLaVA详细分析
analysis = llava_analyze(image, "请详细分析这张图片是否包含不适内容。")

性能优化:

  • CLIP处理: 10ms/张(GPU)
  • LLaVA处理: 500ms/张(仅5%需要)
  • 平均延迟: ~30ms/张

关键技术点#

1. 批量处理

# CLIP批量推理(提升10x)
inputs = processor(text=texts, images=images, return_tensors="pt", padding=True)
outputs = model(**inputs)

2. 特征缓存

# 预计算文本特征(类别固定时)
with torch.no_grad():
    text_features = model.get_text_features(**text_inputs)
    # 缓存,后续只需计算图像特征

3. 混合精度

# 使用torch.autocast加速
with torch.autocast(device_type='cuda', dtype=torch.float16):
    outputs = model(**inputs)

部署建议#

场景推荐模型硬件配置并发能力
图像搜索CLIP1×T4(16GB)100 QPS
视觉问答BLIP-2 (4bit)1×A10(24GB)10 QPS
对话系统LLaVA (4bit)1×A100(40GB)5 QPS
高并发场景CLIP + APIServerless1000+ QPS

成本对比:

  • 自建GPU: $1-3/小时(云服务器)
  • OpenAI GPT-4V: $0.01-0.03/图像
  • Google Gemini: $0.0025-0.01/图像

本章总结#

核心要点#

  1. CLIP: 零样本分类的开创者,适合快速原型和图像检索
  2. BLIP-2: VQA专家,Q-Former架构实现参数高效训练
  3. LLaVA: 开源对话模型,接近闭源GPT-4V性能

技术选型建议#

需求推荐模型理由
零样本分类CLIP快速、简单、效果好
图像描述生成BLIP-2专门优化,生成质量高
复杂视觉推理LLaVA强大的LLM推理能力
生产环境(性能优先)CLIP + API自建CLIP + 调用GPT-4V
生产环境(成本优先)LLaVA 4bit开源可控,显存需求低

学习路径#

  1. 初学者: 从CLIP零样本分类开始,理解对比学习
  2. 进阶: 尝试BLIP-2的VQA任务,掌握量化技术
  3. 高级: 部署LLaVA对话系统,优化推理性能

扩展资源#


下一章预告: 第17章:视觉大模型前沿 - 探索Florence-2、GPT-4V、Gemini等前沿VLM,学习商业API调用与提示词工程!


第17章:视觉大模型前沿#

Florence-2、GPT-4o、Gemini - 工业级VLM的巅峰之作

本章概述#

本章深入讲解2024-2025年最前沿的视觉大模型:

  • Florence-2: 微软开源的统一视觉基础模型
  • GPT-4o: OpenAI的原生多模态GPT
  • Gemini: Google的原生多模态模型

这些模型代表了当前VLM的最高水平,掌握它们的使用方法对于实际应用至关重要。

17.1 Florence-2:微软视觉基础模型#

Florence-2是微软2024年发布的开源视觉基础模型,采用统一的提示词范式处理10+视觉任务。

17.1.1 核心特性#

关键优势:

  • MIT开源协议: 可商用,无license限制
  • 统一任务范式: 一个模型完成所有视觉任务
  • 提示词驱动: 通过不同prompt切换任务
  • 高效参数: 0.77B参数,性能优异

17.1.2 模型变体#

模型参数量用途推荐场景
Florence-2-base0.23B预训练基础资源受限环境
Florence-2-large0.77B预训练基础通用场景
Florence-2-base-ft0.23B任务微调版快速部署
Florence-2-large-ft0.77B任务微调版最佳性能

17.1.3 支持的任务与提示词#

视觉理解任务:

任务提示词功能输出格式示例用途
<CAPTION>基础描述文本图像标注
<DETAILED_CAPTION>详细描述文本内容分析
<MORE_DETAILED_CAPTION>全面分析文本深度理解
<OD>目标检测bbox + 类别物体定位
<DENSE_REGION_CAPTION>区域级描述区域+描述细粒度分析
<REGION_PROPOSAL>候选区域bbox列表检测预处理

定位与文字识别任务:

任务提示词功能输出格式示例用途
<CAPTION_TO_PHRASE_GROUNDING>短语定位文本→bbox视觉定位
<OCR>文字识别文本文档OCR
<OCR_WITH_REGION>OCR+位置文本+四边形票据识别
<REFERRING_EXPRESSION_SEGMENTATION>指称分割mask交互分割
<OPEN_VOCABULARY_DETECTION>开放词汇检测bbox灵活检测

17.1.4 完整使用示例#

基础设置:

from transformers import AutoProcessor, AutoModelForCausalLM
import torch
from PIL import Image

# 加载模型(推荐使用large-ft版本)
model_id = "microsoft/Florence-2-large-ft"
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.float16,
    trust_remote_code=True
).to("cuda")

processor = AutoProcessor.from_pretrained(model_id, trust_remote_code=True)

def run_florence(image, task_prompt, text_input=None):
    """通用Florence-2推理函数"""
    if text_input:
        prompt = task_prompt + text_input
    else:
        prompt = task_prompt

    inputs = processor(text=prompt, images=image, return_tensors="pt").to("cuda", torch.float16)

    generated_ids = model.generate(
        input_ids=inputs["input_ids"],
        pixel_values=inputs["pixel_values"],
        max_new_tokens=1024,
        num_beams=3
    )

    generated_text = processor.batch_decode(generated_ids, skip_special_tokens=False)[0]
    parsed_result = processor.post_process_generation(
        generated_text,
        task=task_prompt,
        image_size=(image.width, image.height)
    )
    return parsed_result

任务示例:

image = Image.open("example.jpg")

# 1. 图像描述
caption = run_florence(image, "<CAPTION>")
print(f"基础描述: {caption}")
# 输出: {'<CAPTION>': 'A cat sitting on a red sofa in a living room.'}

detailed = run_florence(image, "<DETAILED_CAPTION>")
print(f"详细描述: {detailed}")

# 2. 目标检测
detection = run_florence(image, "<OD>")
print(f"检测结果: {detection}")
# 输出: {'<OD>': {'bboxes': [[x1, y1, x2, y2], ...], 'labels': ['cat', 'sofa', ...]}}

# 3. OCR文字识别
ocr_result = run_florence(image, "<OCR>")
print(f"识别文字: {ocr_result}")

# 4. OCR带位置
ocr_with_region = run_florence(image, "<OCR_WITH_REGION>")
print(f"文字+位置: {ocr_with_region}")

# 5. 短语定位(Grounding)
grounding = run_florence(image, "<CAPTION_TO_PHRASE_GROUNDING>", "a cat")
print(f"定位结果: {grounding}")

# 6. 开放词汇检测
open_det = run_florence(image, "<OPEN_VOCABULARY_DETECTION>", "cat, dog, person")
print(f"开放检测: {open_det}")

# 7. 区域级描述
dense_caption = run_florence(image, "<DENSE_REGION_CAPTION>")
print(f"区域描述: {dense_caption}")

17.1.5 结果可视化#

import matplotlib.pyplot as plt
import matplotlib.patches as patches

def visualize_detection(image, result, task="<OD>"):
    """可视化检测结果"""
    fig, ax = plt.subplots(1, figsize=(12, 8))
    ax.imshow(image)

    data = result[task]
    bboxes = data.get('bboxes', [])
    labels = data.get('labels', [])

    colors = plt.cm.Set3(range(len(bboxes)))

    for bbox, label, color in zip(bboxes, labels, colors):
        x1, y1, x2, y2 = bbox
        rect = patches.Rectangle(
            (x1, y1), x2-x1, y2-y1,
            linewidth=2, edgecolor=color, facecolor='none'
        )
        ax.add_patch(rect)
        ax.text(x1, y1-5, label, fontsize=10, color='white',
                bbox=dict(boxstyle='round', facecolor=color, alpha=0.8))

    ax.axis('off')
    plt.tight_layout()
    plt.savefig('detection_result.png', dpi=150, bbox_inches='tight')
    plt.show()

# 使用
detection_result = run_florence(image, "<OD>")
visualize_detection(image, detection_result)

17.1.6 性能基准#

任务数据集Florence-2-L对比模型
图像描述COCO135.6 CIDErBLIP-2: 144.5
目标检测COCO37.5 mAP-
VQAVQAv281.7% (ft)LLaVA: 78.5%
OCRTextVQA63.0%-

优势: 单一模型实现多任务,部署简单,资源需求低。

17.1.7 实战应用场景#

1. 智能文档处理:

def process_document(image_path):
    """文档智能处理流程"""
    image = Image.open(image_path)

    # OCR识别
    text = run_florence(image, "<OCR>")

    # 带位置的OCR(用于表格等)
    ocr_regions = run_florence(image, "<OCR_WITH_REGION>")

    # 图表/图像检测
    objects = run_florence(image, "<OD>")

    return {
        "text": text,
        "regions": ocr_regions,
        "objects": objects
    }

2. 电商图像分析:

def analyze_product_image(image_path):
    """电商商品图分析"""
    image = Image.open(image_path)

    # 商品描述
    description = run_florence(image, "<DETAILED_CAPTION>")

    # 检测商品主体
    detection = run_florence(image, "<OD>")

    # 提取商品上的文字(品牌、规格等)
    text_info = run_florence(image, "<OCR>")

    return {
        "description": description,
        "objects": detection,
        "text": text_info
    }

17.2 GPT-4o:多模态GPT#

GPT-4o(omni)是OpenAI于2024年5月发布的原生多模态模型,将文本、视觉、音频能力融合到单一模型中。

17.2.1 核心特性#

相比GPT-4V的改进:

  • 速度: 响应速度提升2倍
  • 成本: API价格降低50%
  • 能力: 视觉理解能力显著提升
  • 多模态: 原生支持文本+图像+音频

模型选择:

模型特点成本推荐场景
gpt-4o最强能力$5/1M tokens复杂推理
gpt-4o-mini性价比高$0.15/1M tokens日常任务
gpt-4-turbo旧版本$10/1M tokens兼容需求

17.2.2 基础使用#

方式1: URL图像:

from openai import OpenAI
import os

client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))

def analyze_image_url(image_url, question):
    """使用URL分析图像"""
    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": question},
                    {
                        "type": "image_url",
                        "image_url": {"url": image_url}
                    }
                ]
            }
        ],
        max_tokens=500
    )
    return response.choices[0].message.content

# 使用示例
result = analyze_image_url(
    "https://example.com/image.jpg",
    "请详细描述这张图片中的内容"
)
print(result)

方式2: Base64编码图像:

import base64

def encode_image(image_path):
    """将本地图像编码为base64"""
    with open(image_path, "rb") as f:
        return base64.b64encode(f.read()).decode("utf-8")

def analyze_local_image(image_path, question):
    """分析本地图像"""
    base64_image = encode_image(image_path)

    # 自动检测图像格式
    if image_path.lower().endswith('.png'):
        media_type = "image/png"
    elif image_path.lower().endswith('.gif'):
        media_type = "image/gif"
    elif image_path.lower().endswith('.webp'):
        media_type = "image/webp"
    else:
        media_type = "image/jpeg"

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": question},
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:{media_type};base64,{base64_image}"
                        }
                    }
                ]
            }
        ],
        max_tokens=1000
    )
    return response.choices[0].message.content

# 使用
result = analyze_local_image("product.jpg", "这个商品的主要特点是什么?")

17.2.3 多图像分析#

def compare_images(image_paths, question):
    """多图像对比分析"""
    content = [{"type": "text", "text": question}]

    for path in image_paths:
        base64_image = encode_image(path)
        content.append({
            "type": "image_url",
            "image_url": {
                "url": f"data:image/jpeg;base64,{base64_image}"
            }
        })

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[{"role": "user", "content": content}],
        max_tokens=1500
    )
    return response.choices[0].message.content

# 对比两张图片
result = compare_images(
    ["before.jpg", "after.jpg"],
    "请对比这两张图片的差异,描述发生了什么变化"
)

17.2.4 图像细节控制#

GPT-4o支持控制图像处理的精细度:

def analyze_with_detail(image_path, question, detail="auto"):
    """
    控制图像分析精度
    detail参数:
    - "low": 512x512固定,65 tokens,快速便宜
    - "high": 最高2048x2048,详细分析,更多tokens
    - "auto": 自动选择(默认)
    """
    base64_image = encode_image(image_path)

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": question},
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}",
                            "detail": detail  # "low", "high", "auto"
                        }
                    }
                ]
            }
        ],
        max_tokens=1000
    )
    return response.choices[0].message.content

# 快速预览(省钱)
quick_result = analyze_with_detail("doc.jpg", "这是什么文档?", detail="low")

# 详细分析(精确)
detailed_result = analyze_with_detail("doc.jpg", "请提取文档中的所有文字", detail="high")

17.2.5 结构化输出#

import json

def extract_structured_info(image_path, schema_description):
    """提取结构化信息"""
    base64_image = encode_image(image_path)

    prompt = f"""分析这张图片,按照以下格式返回JSON:
{schema_description}

只返回JSON,不要其他内容。"""

    response = client.chat.completions.create(
        model="gpt-4o",
        messages=[
            {
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                    {
                        "type": "image_url",
                        "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
                    }
                ]
            }
        ],
        max_tokens=1000,
        response_format={"type": "json_object"}  # 强制JSON输出
    )

    return json.loads(response.choices[0].message.content)

# 提取商品信息
schema = """
{
    "product_name": "商品名称",
    "brand": "品牌",
    "price": "价格(如果可见)",
    "features": ["特点1", "特点2"],
    "category": "类别"
}
"""
product_info = extract_structured_info("product.jpg", schema)

17.2.6 已知限制#

GPT-4o Vision的局限性:

  1. 空间推理: 复杂位置关系可能出错
  2. 计数: 大量物体计数不准确
  3. 细小文字: 图像中的小字体可能识别不清
  4. 医疗图像: 不应用于医疗诊断
  5. CAPTCHA: 明确拒绝处理验证码

17.2.7 成本优化策略#

class GPT4VisionOptimizer:
    """GPT-4o Vision成本优化器"""

    def __init__(self):
        self.client = OpenAI()

    def preprocess_image(self, image_path, max_size=1024):
        """预处理图像以减少tokens"""
        from PIL import Image

        img = Image.open(image_path)

        # 调整大小
        if max(img.size) > max_size:
            ratio = max_size / max(img.size)
            new_size = (int(img.width * ratio), int(img.height * ratio))
            img = img.resize(new_size, Image.LANCZOS)

        # 转换为JPEG(通常更小)
        import io
        buffer = io.BytesIO()
        img.convert('RGB').save(buffer, format='JPEG', quality=85)
        return base64.b64encode(buffer.getvalue()).decode('utf-8')

    def smart_analyze(self, image_path, question, use_mini=True):
        """智能分析,根据任务选择模型"""
        # 简单任务用mini
        model = "gpt-4o-mini" if use_mini else "gpt-4o"
        base64_image = self.preprocess_image(image_path)

        response = self.client.chat.completions.create(
            model=model,
            messages=[
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": question},
                        {
                            "type": "image_url",
                            "image_url": {
                                "url": f"data:image/jpeg;base64,{base64_image}",
                                "detail": "low"  # 先用低精度
                            }
                        }
                    ]
                }
            ],
            max_tokens=300
        )
        return response.choices[0].message.content

# 使用
optimizer = GPT4VisionOptimizer()
result = optimizer.smart_analyze("image.jpg", "图片中有什么?", use_mini=True)

17.3 Gemini Vision#

Gemini是Google于2023年底发布的原生多模态模型,在视频理解方面具有独特优势。

17.3.1 模型系列#

模型特点上下文窗口推荐场景
gemini-2.5-flash最新快速版1M tokens日常任务
gemini-2.5-pro最强推理1M tokens复杂分析
gemini-2.0-flash平衡版1M tokens通用场景
gemini-1.5-pro稳定版2M tokens超长上下文

17.3.2 基础使用#

安装与配置:

pip install google-generativeai

基础图像分析:

from google import genai
from google.genai import types
import os

# 初始化客户端
client = genai.Client(api_key=os.environ.get("GOOGLE_API_KEY"))

def analyze_image_gemini(image_path, prompt):
    """使用Gemini分析图像"""
    with open(image_path, 'rb') as f:
        image_bytes = f.read()

    # 检测MIME类型
    if image_path.lower().endswith('.png'):
        mime_type = 'image/png'
    elif image_path.lower().endswith('.webp'):
        mime_type = 'image/webp'
    else:
        mime_type = 'image/jpeg'

    response = client.models.generate_content(
        model='gemini-2.5-flash',
        contents=[
            types.Part.from_bytes(data=image_bytes, mime_type=mime_type),
            prompt
        ]
    )
    return response.text

# 使用
result = analyze_image_gemini("photo.jpg", "描述这张照片中的场景")
print(result)

17.3.3 使用File API(大文件)#

def analyze_large_image(image_path, prompt):
    """使用File API处理大文件(推荐)"""
    # 上传文件
    uploaded_file = client.files.upload(file=image_path)

    # 等待处理完成
    import time
    while uploaded_file.state.name == "PROCESSING":
        time.sleep(1)
        uploaded_file = client.files.get(name=uploaded_file.name)

    # 生成内容
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=[uploaded_file, prompt]
    )

    # 可选:删除上传的文件
    # client.files.delete(name=uploaded_file.name)

    return response.text

# 使用
result = analyze_large_image("high_res_image.jpg", "详细分析这张图片")

17.3.4 多图像分析#

def compare_images_gemini(image_paths, prompt):
    """多图像对比分析"""
    contents = []

    for path in image_paths:
        with open(path, 'rb') as f:
            image_bytes = f.read()
        contents.append(types.Part.from_bytes(data=image_bytes, mime_type='image/jpeg'))

    contents.append(prompt)

    response = client.models.generate_content(
        model='gemini-2.5-flash',
        contents=contents
    )
    return response.text

# 使用
result = compare_images_gemini(
    ["img1.jpg", "img2.jpg", "img3.jpg"],
    "比较这三张图片的异同点"
)

17.3.5 视频理解(Gemini独有优势)#

Gemini原生支持视频理解,这是其独特优势:

def analyze_video(video_path, prompt):
    """分析视频内容"""
    # 上传视频
    video_file = client.files.upload(file=video_path)

    # 等待处理
    import time
    while video_file.state.name == "PROCESSING":
        time.sleep(2)
        video_file = client.files.get(name=video_file.name)

    if video_file.state.name == "FAILED":
        raise ValueError("视频处理失败")

    # 分析视频
    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=[video_file, prompt]
    )
    return response.text

# 使用
result = analyze_video("demo.mp4", "总结这个视频的主要内容")
print(result)

视频时间戳查询:

def query_video_timestamp(video_path, question):
    """查询视频特定时间点的内容"""
    video_file = client.files.upload(file=video_path)

    # 等待处理
    import time
    while video_file.state.name == "PROCESSING":
        time.sleep(2)
        video_file = client.files.get(name=video_file.name)

    prompt = f"""观看这个视频并回答问题。
如果问题涉及特定场景,请指出大概的时间点。

问题: {question}"""

    response = client.models.generate_content(
        model="gemini-2.5-flash",
        contents=[video_file, prompt]
    )
    return response.text

# 使用
result = query_video_timestamp("lecture.mp4", "讲师什么时候开始讲解神经网络?")

17.3.6 高级功能:目标检测与分割#

Gemini 2.0+支持目标检测,Gemini 2.5+支持分割:

def detect_objects_gemini(image_path, objects_to_detect):
    """使用Gemini进行目标检测"""
    with open(image_path, 'rb') as f:
        image_bytes = f.read()

    prompt = f"""检测图片中的以下物体: {objects_to_detect}

返回每个检测到的物体的边界框坐标,格式为:
物体名称: [x_min, y_min, x_max, y_max] (归一化到0-1000)"""

    response = client.models.generate_content(
        model='gemini-2.5-flash',
        contents=[
            types.Part.from_bytes(data=image_bytes, mime_type='image/jpeg'),
            prompt
        ]
    )
    return response.text

# 使用
result = detect_objects_gemini("street.jpg", "人, 车, 红绿灯")

17.3.7 成本与Token计算#

图像Token计算规则:

  • 图像 ≤384px(两边): 258 tokens
  • 更大图像: 按768×768 tiles切分,每tile 258 tokens

视频Token计算:

  • 每秒视频约263 tokens(1fps采样)
  • 1分钟视频 ≈ 15,780 tokens

价格对比(2024年):

模型输入价格输出价格
Gemini 2.5 Flash$0.075/1M$0.30/1M
Gemini 2.5 Pro$1.25/1M$10/1M
GPT-4o$2.50/1M$10/1M
GPT-4o-mini$0.15/1M$0.60/1M

结论: Gemini在图像/视频处理上比GPT-4o便宜约60-70%。


17.4 实战:VLM API调用与应用#

17.4.1 统一接口封装#

from abc import ABC, abstractmethod
from PIL import Image
import base64
import io

class VLMInterface(ABC):
    """VLM统一接口"""

    @abstractmethod
    def analyze(self, image_path: str, prompt: str) -> str:
        pass

    def _encode_image(self, image_path: str) -> str:
        with open(image_path, 'rb') as f:
            return base64.b64encode(f.read()).decode('utf-8')

class GPT4oVLM(VLMInterface):
    def __init__(self, api_key: str):
        from openai import OpenAI
        self.client = OpenAI(api_key=api_key)

    def analyze(self, image_path: str, prompt: str) -> str:
        base64_image = self._encode_image(image_path)
        response = self.client.chat.completions.create(
            model="gpt-4o",
            messages=[{
                "role": "user",
                "content": [
                    {"type": "text", "text": prompt},
                    {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}}
                ]
            }],
            max_tokens=1000
        )
        return response.choices[0].message.content

class GeminiVLM(VLMInterface):
    def __init__(self, api_key: str):
        from google import genai
        self.client = genai.Client(api_key=api_key)

    def analyze(self, image_path: str, prompt: str) -> str:
        from google.genai import types
        with open(image_path, 'rb') as f:
            image_bytes = f.read()
        response = self.client.models.generate_content(
            model='gemini-2.5-flash',
            contents=[types.Part.from_bytes(data=image_bytes, mime_type='image/jpeg'), prompt]
        )
        return response.text

class Florence2VLM(VLMInterface):
    def __init__(self):
        from transformers import AutoProcessor, AutoModelForCausalLM
        import torch
        self.model = AutoModelForCausalLM.from_pretrained(
            "microsoft/Florence-2-large-ft",
            torch_dtype=torch.float16,
            trust_remote_code=True
        ).to("cuda")
        self.processor = AutoProcessor.from_pretrained(
            "microsoft/Florence-2-large-ft",
            trust_remote_code=True
        )

    def analyze(self, image_path: str, prompt: str) -> str:
        image = Image.open(image_path)
        inputs = self.processor(text=prompt, images=image, return_tensors="pt").to("cuda")
        output = self.model.generate(**inputs, max_new_tokens=1024)
        return self.processor.batch_decode(output, skip_special_tokens=True)[0]

# 使用示例
def analyze_with_fallback(image_path, prompt, vlm_list):
    """带fallback的分析"""
    for vlm in vlm_list:
        try:
            return vlm.analyze(image_path, prompt)
        except Exception as e:
            print(f"{vlm.__class__.__name__} 失败: {e}")
            continue
    raise RuntimeError("所有VLM都失败了")

17.4.2 文档理解应用#

class DocumentAnalyzer:
    """文档智能分析器"""

    def __init__(self, vlm: VLMInterface):
        self.vlm = vlm

    def extract_text(self, image_path: str) -> str:
        """提取文档中的文字"""
        prompt = "提取图片中的所有文字,保持原有格式和布局"
        return self.vlm.analyze(image_path, prompt)

    def analyze_table(self, image_path: str) -> dict:
        """分析表格内容"""
        prompt = """分析图片中的表格,返回JSON格式:
{
    "headers": ["列1", "列2", ...],
    "rows": [["数据1", "数据2", ...], ...]
}
只返回JSON,不要其他内容。"""
        result = self.vlm.analyze(image_path, prompt)
        import json
        return json.loads(result)

    def summarize_document(self, image_path: str) -> dict:
        """文档摘要"""
        prompt = """分析这份文档,返回JSON格式:
{
    "type": "文档类型(如:发票/合同/报告)",
    "title": "文档标题",
    "date": "日期(如果有)",
    "summary": "主要内容摘要(100字以内)",
    "key_info": ["关键信息1", "关键信息2", ...]
}"""
        result = self.vlm.analyze(image_path, prompt)
        import json
        return json.loads(result)

# 使用
vlm = GPT4oVLM(api_key="your-key")
analyzer = DocumentAnalyzer(vlm)

# 分析发票
invoice_info = analyzer.summarize_document("invoice.jpg")
print(invoice_info)

17.4.3 视频分析应用(Gemini)#

class VideoAnalyzer:
    """视频智能分析器(仅支持Gemini)"""

    def __init__(self, api_key: str):
        from google import genai
        self.client = genai.Client(api_key=api_key)

    def _upload_video(self, video_path: str):
        """上传并等待视频处理完成"""
        import time
        video_file = self.client.files.upload(file=video_path)
        while video_file.state.name == "PROCESSING":
            time.sleep(2)
            video_file = self.client.files.get(name=video_file.name)
        return video_file

    def generate_summary(self, video_path: str) -> str:
        """生成视频摘要"""
        video_file = self._upload_video(video_path)
        response = self.client.models.generate_content(
            model="gemini-2.5-flash",
            contents=[video_file, "生成这个视频的详细摘要,包括主要内容、关键场景和结论"]
        )
        return response.text

    def extract_key_frames(self, video_path: str) -> list:
        """提取关键帧描述"""
        video_file = self._upload_video(video_path)
        prompt = """分析视频中的关键场景,返回JSON格式:
[
    {"timestamp": "MM:SS", "description": "场景描述"},
    ...
]
只返回JSON列表。"""
        response = self.client.models.generate_content(
            model="gemini-2.5-flash",
            contents=[video_file, prompt]
        )
        import json
        return json.loads(response.text)

    def answer_question(self, video_path: str, question: str) -> str:
        """视频问答"""
        video_file = self._upload_video(video_path)
        response = self.client.models.generate_content(
            model="gemini-2.5-flash",
            contents=[video_file, f"观看视频并回答问题: {question}"]
        )
        return response.text

# 使用
analyzer = VideoAnalyzer(api_key="your-google-key")
summary = analyzer.generate_summary("lecture.mp4")
print(summary)

17.4.4 VLM性能对比#

import time

def benchmark_vlms(image_path: str, prompt: str, vlms: dict) -> dict:
    """VLM性能基准测试"""
    results = {}

    for name, vlm in vlms.items():
        try:
            start = time.time()
            response = vlm.analyze(image_path, prompt)
            latency = time.time() - start

            results[name] = {
                "success": True,
                "latency": round(latency, 2),
                "response_length": len(response),
                "response_preview": response[:200] + "..."
            }
        except Exception as e:
            results[name] = {
                "success": False,
                "error": str(e)
            }

    return results

# 运行基准测试
vlms = {
    "GPT-4o": GPT4oVLM(api_key="..."),
    "Gemini": GeminiVLM(api_key="..."),
    "Florence-2": Florence2VLM()
}

results = benchmark_vlms("test_image.jpg", "描述这张图片", vlms)
for name, result in results.items():
    print(f"{name}: {result}")

本章小结#

核心要点#

  1. Florence-2: 开源统一视觉模型,通过提示词切换10+任务,适合部署和定制
  2. GPT-4o: 综合能力最强,适合复杂推理和高精度需求
  3. Gemini: 视频理解独特优势,成本最低,超长上下文

模型选择指南#

需求推荐模型理由
开源可控Florence-2MIT协议,可商用
最强推理GPT-4o综合能力最佳
视频分析Gemini原生视频支持
成本敏感Gemini Flash最便宜
快速原型GPT-4o-mini性价比高
本地部署Florence-2无API依赖

最佳实践#

  1. 成本优化: 简单任务用mini模型,复杂任务用标准模型
  2. 图像预处理: 压缩图像减少tokens消耗
  3. 批量处理: 使用异步调用提升吞吐
  4. Fallback策略: 主模型失败时切换备用模型
  5. 结果缓存: 相同图像+prompt缓存结果

参考资源#


第18章:3D视觉与视频理解#

从2D到3D/4D的视觉扩展

本章概述#

本章探索计算机视觉的前沿方向:

  • NeRF: 神经辐射场,隐式3D表示
  • 3D Gaussian Splatting: 显式3D重建新范式,实时渲染
  • Video Understanding: 视频分类与理解
  • Video VLM: 视频版大语言模型

这些技术代表了CV从2D向3D/4D演进的重要方向。


18.1 NeRF:神经辐射场#

NeRF(Neural Radiance Fields)是2020年ECCV提出的突破性工作,通过神经网络隐式表示3D场景,并获得了ECCV 2020最佳论文荣誉提名。

18.1.1 核心原理#

基本思想: 用一个神经网络学习从5D输入(3D位置 + 2D视角方向)到颜色和密度的映射。

输入: (x, y, z, θ, φ) - 空间位置 + 观察方向
    MLP网络
输出: (r, g, b, σ) - 颜色 + 密度

体渲染(Volume Rendering): 沿着每条射线积分颜色和密度,生成最终像素值:

C(r) = ∫ T(t) · σ(r(t)) · c(r(t), d) dt

其中:
- T(t): 透射率,光线到达t点的概率
- σ: 体积密度
- c: 颜色
- d: 视角方向

18.1.2 网络架构#

import torch
import torch.nn as nn

class NeRF(nn.Module):
    """简化版NeRF网络"""

    def __init__(self, D=8, W=256, input_ch=63, input_ch_views=27):
        """
        Args:
            D: 网络深度
            W: 隐藏层宽度
            input_ch: 位置编码后的位置维度
            input_ch_views: 位置编码后的方向维度
        """
        super().__init__()
        self.D = D
        self.W = W
        self.input_ch = input_ch
        self.input_ch_views = input_ch_views

        # 位置编码后的位置输入 -> 特征
        self.pts_linears = nn.ModuleList(
            [nn.Linear(input_ch, W)] +
            [nn.Linear(W, W) if i != 4 else nn.Linear(W + input_ch, W)
             for i in range(D - 1)]
        )

        # 方向相关的颜色预测
        self.views_linears = nn.ModuleList([nn.Linear(input_ch_views + W, W // 2)])

        # 输出层
        self.feature_linear = nn.Linear(W, W)
        self.alpha_linear = nn.Linear(W, 1)  # 密度
        self.rgb_linear = nn.Linear(W // 2, 3)  # 颜色

    def forward(self, x):
        # 分离位置和方向
        input_pts, input_views = torch.split(
            x, [self.input_ch, self.input_ch_views], dim=-1
        )

        h = input_pts
        for i, layer in enumerate(self.pts_linears):
            h = layer(h)
            h = torch.relu(h)
            if i == 4:
                h = torch.cat([input_pts, h], -1)

        # 密度输出(与视角无关)
        alpha = self.alpha_linear(h)

        # 颜色输出(与视角相关)
        feature = self.feature_linear(h)
        h = torch.cat([feature, input_views], -1)

        for layer in self.views_linears:
            h = layer(h)
            h = torch.relu(h)

        rgb = torch.sigmoid(self.rgb_linear(h))

        return torch.cat([rgb, alpha], -1)

18.1.3 位置编码(Positional Encoding)#

NeRF使用位置编码帮助网络学习高频细节:

class PositionalEncoding:
    """位置编码:将低维输入映射到高维空间"""

    def __init__(self, L=10):
        """
        Args:
            L: 编码频率数量
        """
        self.L = L
        self.freq_bands = 2.0 ** torch.linspace(0, L - 1, L)

    def encode(self, x):
        """
        Args:
            x: 输入坐标 [..., C]
        Returns:
            编码后的坐标 [..., C * (2L + 1)]
        """
        out = [x]
        for freq in self.freq_bands:
            out.append(torch.sin(freq * x))
            out.append(torch.cos(freq * x))
        return torch.cat(out, dim=-1)

# 使用示例
pos_encoder = PositionalEncoding(L=10)  # 位置用L=10
dir_encoder = PositionalEncoding(L=4)   # 方向用L=4

# 3D位置: 3 -> 3*(2*10+1) = 63
# 2D方向: 3 -> 3*(2*4+1) = 27

18.1.4 使用Nerfstudio#

Nerfstudio是最流行的NeRF工具箱,提供了统一的训练和可视化接口:

安装:

pip install nerfstudio

# 或从源码安装(获取最新功能)
git clone https://github.com/nerfstudio-project/nerfstudio.git
cd nerfstudio
pip install -e .

数据准备(使用COLMAP):

# 从视频提取帧并估计相机位姿
ns-process-data video --data ./input_video.mp4 --output-dir ./data/my_scene

# 或从图像文件夹处理
ns-process-data images --data ./images/ --output-dir ./data/my_scene

训练:

# 训练Nerfacto模型(推荐)
ns-train nerfacto --data ./data/my_scene

# 训练Instant-NGP(更快)
ns-train instant-ngp --data ./data/my_scene

# 指定输出目录
ns-train nerfacto --data ./data/my_scene --output-dir ./outputs/

可视化:

# 启动交互式查看器
ns-viewer --load-config outputs/my_scene/nerfacto/config.yml

# 渲染视频
ns-render camera-path --load-config outputs/my_scene/nerfacto/config.yml \
    --camera-path-filename camera_path.json \
    --output-path renders/output.mp4

18.1.5 Instant-NGP:1000倍加速#

NVIDIA的Instant-NGP使用多分辨率哈希编码,将NeRF训练从小时级缩短到分钟级:

核心创新:

  1. 多分辨率哈希编码: 用哈希表替代大型MLP,大幅加速查询
  2. 小型MLP: 只需要2层MLP(原版需要8层)
  3. CUDA优化: 高度优化的CUDA实现

使用方式:

# 下载并解压Instant-NGP
# 从 https://github.com/NVlabs/instant-ngp/releases 下载

# 启动GUI
./instant-ngp

# 拖拽数据文件夹到窗口即可开始训练
# 或使用命令行
./instant-ngp ./data/nerf/fox

性能对比:

方法训练时间渲染FPS质量(PSNR)
原版NeRF1-2天0.0331.0
Instant-NGP5分钟60+33.0
Nerfacto30分钟1-532.5

18.1.6 NeRF的局限性#

  1. 训练慢: 即使Instant-NGP也需要几分钟
  2. 渲染慢: 体渲染计算密集(除了Instant-NGP)
  3. 静态场景: 原版只能处理静态场景
  4. 采集要求: 需要高质量的多视角图像

18.2 3D Gaussian Splatting#

3D Gaussian Splatting(3DGS)是2023年SIGGRAPH的突破性工作,实现了高质量实时3D重建。

18.2.1 核心思想#

与NeRF的隐式表示不同,3DGS使用显式的3D高斯点云表示场景:

每个高斯的属性:

  • 位置: 3D中心点 (x, y, z)
  • 协方差: 3×3矩阵,定义高斯的形状和方向
  • 不透明度: α值
  • 球谐系数: 表示视角相关的颜色
场景 = {G₁, G₂, ..., Gₙ}
Gᵢ = (μᵢ, Σᵢ, αᵢ, SHᵢ)

其中:
- μ: 位置 (3D)
- Σ: 协方差矩阵 (表示为缩放+旋转)
- α: 不透明度
- SH: 球谐系数 (颜色)

18.2.2 渲染流程#

3DGS使用可微分光栅化而非体渲染:

# 伪代码:3DGS渲染流程
def render_gaussians(gaussians, camera):
    """
    1. 将3D高斯投影到2D
    2. 按深度排序
    3. Alpha混合
    """
    # 1. 投影
    projected_2d = project_to_2d(gaussians, camera)

    # 2. 排序(按深度)
    sorted_gaussians = sort_by_depth(projected_2d)

    # 3. 光栅化(Alpha混合)
    image = torch.zeros(H, W, 3)
    for gaussian in sorted_gaussians:
        contribution = gaussian.alpha * gaussian.color
        image = image * (1 - gaussian.alpha) + contribution

    return image

18.2.3 训练流程#

# 伪代码:3DGS训练流程
def train_3dgs(images, cameras, sfm_points):
    """
    Args:
        images: 训练图像
        cameras: 相机参数
        sfm_points: SfM稀疏点云(初始化)
    """
    # 1. 初始化高斯点
    gaussians = initialize_from_sfm(sfm_points)

    optimizer = torch.optim.Adam(gaussians.parameters(), lr=0.001)

    for iteration in range(30000):
        # 随机选择视角
        camera = random.choice(cameras)
        gt_image = images[camera]

        # 前向渲染
        rendered = render_gaussians(gaussians, camera)

        # 计算损失
        loss = l1_loss(rendered, gt_image) + ssim_loss(rendered, gt_image)

        # 反向传播
        loss.backward()
        optimizer.step()

        # 自适应密度控制(关键!)
        if iteration % 100 == 0:
            densify_and_prune(gaussians)  # 分裂/克隆/删除高斯

    return gaussians

18.2.4 安装与使用#

环境要求:

  • CUDA 11.0+
  • Python 3.8+
  • PyTorch 2.0+

安装:

# 克隆仓库(注意递归克隆)
git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive
cd gaussian-splatting

# 安装依赖
pip install -r requirements.txt

# 安装子模块
pip install submodules/diff-gaussian-rasterization
pip install submodules/simple-knn

数据准备:

# 使用COLMAP处理数据
# 需要:images/文件夹下的图像

python convert.py -s ./data/my_scene

训练:

# 基础训练
python train.py -s ./data/my_scene

# 指定输出和迭代次数
python train.py -s ./data/my_scene -m ./output/my_scene --iterations 30000

# 使用稀疏Adam优化器(2.7倍加速)
python train.py -s ./data/my_scene --optimizer_type sparse_adam

渲染:

# 渲染训练视角
python render.py -m ./output/my_scene

# 交互式查看器
# 需要安装SIBR viewer
./SIBR_viewers/install/bin/SIBR_gaussianViewer_app -m ./output/my_scene

18.2.5 Python API使用#

import torch
from scene import Scene, GaussianModel
from gaussian_renderer import render

# 加载训练好的模型
gaussians = GaussianModel(3)  # sh_degree=3
gaussians.load_ply("output/my_scene/point_cloud/iteration_30000/point_cloud.ply")

# 设置相机
from utils.graphics_utils import getProjectionMatrix, getWorld2View2
viewpoint_camera = create_camera(...)  # 创建相机对象

# 渲染
rendering = render(viewpoint_camera, gaussians, pipe, background)
image = rendering["render"]  # [3, H, W]

# 保存图像
from torchvision.utils import save_image
save_image(image, "rendered.png")

18.2.6 3DGS vs NeRF对比#

特性NeRF3D Gaussian Splatting
表示方式隐式(MLP)显式(点云)
渲染方法体渲染(射线采样)光栅化(Splatting)
训练时间小时级分钟级(~30min)
渲染速度慢(~0.1 FPS)实时(100+ FPS)
质量更高
编辑性困难容易(点云操作)
存储大小小(~5MB)大(~100MB+)
动态场景需要扩展需要扩展

选择建议:

  • 需要实时渲染 → 3DGS
  • 存储空间有限 → NeRF
  • 需要编辑场景 → 3DGS
  • 研究/学习目的 → 两者都尝试

18.2.7 3DGS扩展与应用#

1. Dynamic 3DGS(动态场景):

# 动态高斯:每个高斯有时间相关属性
class DynamicGaussian:
    def __init__(self):
        self.position = nn.Parameter(...)  # 基础位置
        self.deformation = DeformationNetwork()  # 变形网络

    def get_position(self, time):
        # 根据时间获取当前位置
        delta = self.deformation(self.position, time)
        return self.position + delta

2. SuGaR(网格提取): 从3DGS中提取可编辑的网格:

# 安装SuGaR
git clone https://github.com/Anttwo/SuGaR
cd SuGaR

# 训练并提取网格
python train.py -s ./data/my_scene -r "density" --export_obj

3. GaussianEditor(场景编辑):

# 删除特定区域的高斯
mask = create_mask_from_text("remove the car")
gaussians.prune_by_mask(mask)

# 复制高斯
new_gaussians = gaussians.clone()
new_gaussians.translate([1, 0, 0])  # 移动

18.3 视频理解(Video Understanding)#

视频理解是将VLM能力扩展到时序数据的重要方向。

18.3.1 视频理解任务#

任务描述输出
视频分类识别视频类别类别标签
动作识别识别人体动作动作类别
时序动作检测检测动作起止时间时间段+类别
视频描述生成视频描述文本
视频问答回答关于视频的问题文本
视频摘要提取关键片段视频片段

18.3.2 VideoMAE:视频自监督学习#

VideoMAE是视频版的MAE,通过掩码自编码学习视频表示:

安装:

pip install transformers decord av

视频分类:

from transformers import VideoMAEForVideoClassification, VideoMAEImageProcessor
import torch
import numpy as np
import av

def read_video_pyav(video_path, num_frames=16):
    """使用PyAV读取视频帧"""
    container = av.open(video_path)
    stream = container.streams.video[0]

    # 计算采样间隔
    total_frames = stream.frames
    indices = np.linspace(0, total_frames - 1, num_frames, dtype=int)

    frames = []
    for i, frame in enumerate(container.decode(video=0)):
        if i in indices:
            frames.append(frame.to_ndarray(format="rgb24"))
        if len(frames) >= num_frames:
            break

    return np.stack(frames)  # [T, H, W, C]

# 加载模型
model_name = "MCG-NJU/videomae-base-finetuned-kinetics"
processor = VideoMAEImageProcessor.from_pretrained(model_name)
model = VideoMAEForVideoClassification.from_pretrained(model_name)

# 读取视频
video = read_video_pyav("video.mp4", num_frames=16)

# 预处理
inputs = processor(list(video), return_tensors="pt")

# 推理
with torch.no_grad():
    outputs = model(**inputs)
    logits = outputs.logits

# 获取预测类别
predicted_class_idx = logits.argmax(-1).item()
print(f"预测类别: {model.config.id2label[predicted_class_idx]}")

VideoMAE性能:

模型Kinetics-400Something-Something V2
videomae-base81.5%70.8%
videomae-large85.2%75.3%
videomae-huge86.6%77.4%

18.3.3 TimeSformer:时空Transformer#

TimeSformer将ViT扩展到视频,使用分离的时空注意力:

from transformers import TimesformerModel, AutoImageProcessor
import torch

# 加载模型
processor = AutoImageProcessor.from_pretrained("facebook/timesformer-base-finetuned-k400")
model = TimesformerModel.from_pretrained("facebook/timesformer-base-finetuned-k400")

# 准备视频(假设已读取为numpy数组)
# video: [T, H, W, C], T通常为8或16帧
video_frames = read_video_pyav("video.mp4", num_frames=8)

# 预处理
inputs = processor(list(video_frames), return_tensors="pt")

# 特征提取
with torch.no_grad():
    outputs = model(**inputs)
    features = outputs.last_hidden_state  # [B, T*patches+1, D]

# 使用CLS token作为视频表示
video_embedding = features[:, 0]  # [B, D]

18.3.4 Video-LLaVA:视频语言模型#

Video-LLaVA是LLaVA的视频版本,支持视频问答和描述:

安装:

pip install transformers accelerate

使用示例:

from transformers import VideoLlavaProcessor, VideoLlavaForConditionalGeneration
import torch
import numpy as np
import av

def read_video_for_llava(video_path, num_frames=8):
    """为Video-LLaVA读取视频"""
    container = av.open(video_path)
    stream = container.streams.video[0]
    total_frames = stream.frames

    indices = np.linspace(0, total_frames - 1, num_frames, dtype=int)

    frames = []
    container.seek(0)
    for i, frame in enumerate(container.decode(video=0)):
        if i in indices:
            frames.append(frame.to_ndarray(format="rgb24"))
        if len(frames) >= num_frames:
            break

    return np.stack(frames)

# 加载模型
model_id = "LanguageBind/Video-LLaVA-7B-hf"
processor = VideoLlavaProcessor.from_pretrained(model_id)
model = VideoLlavaForConditionalGeneration.from_pretrained(
    model_id,
    torch_dtype=torch.float16,
    device_map="auto"
)

# 读取视频
video = read_video_for_llava("demo.mp4", num_frames=8)

# 构建对话
prompt = "USER: <video>请详细描述这个视频的内容。 ASSISTANT:"

# 处理输入
inputs = processor(
    text=prompt,
    videos=video,
    return_tensors="pt"
).to(model.device, torch.float16)

# 生成
output = model.generate(
    **inputs,
    max_new_tokens=256,
    do_sample=True,
    temperature=0.7
)

# 解码
response = processor.decode(output[0], skip_special_tokens=True)
print(response.split("ASSISTANT:")[-1].strip())

视频问答:

def video_qa(video_path, question):
    """视频问答"""
    video = read_video_for_llava(video_path, num_frames=8)
    prompt = f"USER: <video>{question} ASSISTANT:"

    inputs = processor(
        text=prompt,
        videos=video,
        return_tensors="pt"
    ).to(model.device, torch.float16)

    output = model.generate(**inputs, max_new_tokens=128)
    response = processor.decode(output[0], skip_special_tokens=True)
    return response.split("ASSISTANT:")[-1].strip()

# 使用
answer = video_qa("cooking.mp4", "视频中的人在做什么菜?用了哪些食材?")
print(answer)

18.3.5 视频分析最佳实践#

1. 帧采样策略:

def uniform_sample(video_path, num_frames=16):
    """均匀采样"""
    # 最常用,适合大多数任务
    pass

def keyframe_sample(video_path, num_frames=16):
    """关键帧采样"""
    # 适合快速变化的视频
    import cv2
    cap = cv2.VideoCapture(video_path)
    frames = []
    prev_frame = None

    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break

        if prev_frame is not None:
            # 计算帧差
            diff = cv2.absdiff(frame, prev_frame).mean()
            if diff > threshold:
                frames.append(frame)

        prev_frame = frame

    cap.release()
    return select_frames(frames, num_frames)

def scene_based_sample(video_path, num_frames=16):
    """场景切换采样"""
    # 适合包含多个场景的视频
    pass

2. 长视频处理:

def process_long_video(video_path, chunk_duration=30):
    """分块处理长视频"""
    import av
    container = av.open(video_path)
    duration = container.duration / 1000000  # 秒

    results = []
    for start in range(0, int(duration), chunk_duration):
        end = min(start + chunk_duration, duration)
        chunk = extract_chunk(video_path, start, end)

        # 处理每个块
        chunk_result = analyze_video_chunk(chunk)
        results.append({
            "start": start,
            "end": end,
            "result": chunk_result
        })

    # 合并结果
    return merge_results(results)

3. 批量推理:

def batch_video_inference(video_paths, batch_size=4):
    """批量视频推理"""
    results = []

    for i in range(0, len(video_paths), batch_size):
        batch_paths = video_paths[i:i + batch_size]
        batch_videos = [read_video(p) for p in batch_paths]

        # 批量处理
        inputs = processor(
            videos=batch_videos,
            return_tensors="pt",
            padding=True
        ).to(device)

        with torch.no_grad():
            outputs = model(**inputs)

        results.extend(process_outputs(outputs))

    return results

18.4 实战:3D重建项目#

18.4.1 完整3D重建流程#

手机拍摄 → 图像预处理 → SfM位姿估计 → 3DGS/NeRF训练 → 渲染/导出

18.4.2 数据采集指南#

拍摄技巧:

  1. 覆盖全面: 围绕物体/场景拍摄,覆盖所有角度
  2. 重叠率高: 相邻图像重叠70%以上
  3. 光照一致: 避免强烈阴影和高光
  4. 稳定清晰: 避免运动模糊
  5. 数量适中: 50-150张图像为佳

使用手机:

# 使用Record3D(iOS)直接导出
# 支持LiDAR深度数据

# 或使用Polycam等App

18.4.3 使用COLMAP进行SfM#

# 安装COLMAP
# macOS
brew install colmap

# Ubuntu
sudo apt install colmap

# 或下载预编译版本

自动流程:

# 自动重建流程
colmap automatic_reconstructor \
    --workspace_path ./workspace \
    --image_path ./images \
    --camera_model OPENCV \
    --single_camera 1

分步流程(更多控制):

# 1. 特征提取
colmap feature_extractor \
    --database_path ./database.db \
    --image_path ./images \
    --ImageReader.camera_model OPENCV \
    --ImageReader.single_camera 1

# 2. 特征匹配
colmap exhaustive_matcher \
    --database_path ./database.db

# 3. 稀疏重建
mkdir sparse
colmap mapper \
    --database_path ./database.db \
    --image_path ./images \
    --output_path ./sparse

# 4. 导出为文本格式(用于3DGS)
colmap model_converter \
    --input_path ./sparse/0 \
    --output_path ./sparse_txt \
    --output_type TXT

18.4.4 3DGS训练脚本#

# train_3dgs.py
import os
import subprocess
import argparse

def prepare_data(image_folder, output_folder):
    """使用COLMAP准备数据"""
    os.makedirs(output_folder, exist_ok=True)

    # 运行COLMAP
    subprocess.run([
        "colmap", "automatic_reconstructor",
        "--workspace_path", output_folder,
        "--image_path", image_folder,
        "--camera_model", "OPENCV",
        "--single_camera", "1"
    ])

def train_gaussians(data_path, output_path, iterations=30000):
    """训练3D Gaussian Splatting"""
    subprocess.run([
        "python", "train.py",
        "-s", data_path,
        "-m", output_path,
        "--iterations", str(iterations),
        "--save_iterations", "7000", "15000", "30000"
    ])

def render_video(model_path, output_video):
    """渲染视频"""
    subprocess.run([
        "python", "render.py",
        "-m", model_path,
        "--skip_train",
        "--skip_test"
    ])

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--images", required=True, help="图像文件夹路径")
    parser.add_argument("--output", required=True, help="输出路径")
    parser.add_argument("--iterations", type=int, default=30000)
    args = parser.parse_args()

    # 1. 准备数据
    print("步骤1: 准备数据...")
    data_path = os.path.join(args.output, "data")
    prepare_data(args.images, data_path)

    # 2. 训练
    print("步骤2: 训练3DGS...")
    model_path = os.path.join(args.output, "model")
    train_gaussians(data_path, model_path, args.iterations)

    # 3. 渲染
    print("步骤3: 渲染结果...")
    render_video(model_path, os.path.join(args.output, "video.mp4"))

    print(f"完成! 结果保存在: {args.output}")

if __name__ == "__main__":
    main()

18.4.5 Web可视化#

使用Three.js展示3DGS结果:

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>3D Gaussian Splatting Viewer</title>
    <script src="https://cdn.jsdelivr.net/npm/three@0.150.0/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.150.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
    <canvas id="canvas"></canvas>
    <script>
        // 初始化场景
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
        const renderer = new THREE.WebGLRenderer({canvas: document.getElementById('canvas')});
        renderer.setSize(window.innerWidth, window.innerHeight);

        // 控制器
        const controls = new THREE.OrbitControls(camera, renderer.domElement);

        // 加载PLY点云(简化版本)
        const loader = new THREE.PLYLoader();
        loader.load('point_cloud.ply', function(geometry) {
            const material = new THREE.PointsMaterial({
                size: 0.01,
                vertexColors: true
            });
            const points = new THREE.Points(geometry, material);
            scene.add(points);
        });

        camera.position.z = 5;

        // 渲染循环
        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>
</html>

使用专业查看器:

18.4.6 导出与部署#

导出为网页格式:

# 导出为压缩的.splat格式
def export_splat(gaussians, output_path):
    """导出为Web友好的格式"""
    import numpy as np
    import struct

    # 提取高斯属性
    positions = gaussians.get_xyz.detach().cpu().numpy()
    colors = gaussians.get_features.detach().cpu().numpy()
    opacities = gaussians.get_opacity.detach().cpu().numpy()
    scales = gaussians.get_scaling.detach().cpu().numpy()
    rotations = gaussians.get_rotation.detach().cpu().numpy()

    # 按不透明度排序
    sorted_indices = np.argsort(-opacities.flatten())

    # 写入二进制文件
    with open(output_path, 'wb') as f:
        for idx in sorted_indices:
            # 位置 (float32 x 3)
            f.write(struct.pack('fff', *positions[idx]))
            # 缩放 (float32 x 3)
            f.write(struct.pack('fff', *scales[idx]))
            # 颜色 (uint8 x 4)
            rgb = (colors[idx, :3] * 255).astype(np.uint8)
            alpha = (opacities[idx] * 255).astype(np.uint8)
            f.write(struct.pack('BBBB', *rgb, alpha))
            # 旋转 (int8 x 4)
            rot = (rotations[idx] * 127).astype(np.int8)
            f.write(struct.pack('bbbb', *rot))

    print(f"导出完成: {output_path}")

本章小结#

核心知识点#

  1. NeRF: 隐式3D表示,体渲染,Instant-NGP加速
  2. 3DGS: 显式高斯表示,实时渲染,可编辑
  3. VideoMAE: 视频自监督学习,掩码自编码
  4. Video-LLaVA: 视频语言模型,问答和描述

技术对比#

技术优势劣势适用场景
NeRF高质量,存储小训练慢,渲染慢高质量重建
3DGS实时渲染,可编辑存储大实时应用
VideoMAE自监督,预训练仅分类视频分类
Video-LLaVA视频理解资源需求大视频问答

实践建议#

  1. 3D重建:

    • 新手先用Nerfstudio
    • 需要实时渲染用3DGS
    • 注意数据采集质量
  2. 视频理解:

    • 分类任务用VideoMAE
    • 问答描述用Video-LLaVA
    • 长视频分块处理

参考资源#


第七篇总结#

学习成果#

通过本篇学习,你已掌握:

  1. 多模态基础模型: CLIP、BLIP、LLaVA的原理和使用
  2. 前沿VLM: Florence-2、GPT-4o、Gemini的API调用
  3. 3D视觉: NeRF和3DGS的原理与实践
  4. 视频理解: VideoMAE和Video-LLaVA的应用

技术栈总结#

图像理解: CLIP → BLIP → LLaVA → GPT-4o/Gemini
3D重建:  COLMAP → NeRF/3DGS → 渲染/导出
视频理解: VideoMAE → Video-LLaVA → Gemini Video

下一步#

  • 深入研究特定领域(医疗、自动驾驶)的VLM应用
  • 探索多模态生成(图像+视频生成)
  • 关注具身智能(Embodied AI)的发展
  • 学习第八篇:生产实践与工程化
[统计组件仅在生产环境显示]