Thinking with Camera: A Unified Multimodal Model for Camera-Centric Understanding and Generation
Paper: arXiv:2510.08673 Code: KangLiao929/Puffin Code reference:
main@6da4f08f(2026-02-18)
1. Motivation (研究动机)
这篇论文要解决的问题不是单纯的“相机参数估计”或“带相机条件的图像生成”,而是把这两个长期分离的方向放进一个统一的多模态框架里。作者把 camera-centric understanding 定义为:给定一张图像,模型不仅要描述场景,还要估计 camera roll、pitch、FoV 等相机参数;把 camera-centric generation 定义为:给定文本与相机条件,生成与目标视角、重力方向、视场范围一致的图像。过去这两类任务通常分属不同系统:理解侧更多依赖 vanishing point、horizon line、gravity direction、semantic layout 等几何/视觉特征回归;生成侧则把 camera pose 或 camera trajectory 当作额外控制信号接入扩散模型。这样做的局限是明显的:理解模型缺少语言层面的空间推理,生成模型缺少对“摄影术语—视觉线索—几何参数”之间关系的可解释中间表征。

Figure 1 解读:这张 teaser 把 Puffin 的目标压缩成四类能力:camera-controllable generation、camera understanding、thinking mode、cross-view applications。它不是只展示生成质量,而是在同一个模型里同时展示“从相机参数生成图像”和“从图像反推相机参数/空间解释”。这也是本文与 CameraCtrl、PreciseCam、GeoCalib 等单任务模型的根本区别:Puffin 试图把相机当作一种可被语言模型读写的条件,而不是一个只在视觉网络或扩散控制分支里存在的数值向量。
作者认为现有方法的核心瓶颈来自 camera modality gap。相机参数在数学上很清楚,但对 LMM 来说并不自然:20° roll、wide FoV、tilt-up、Dutch angle 这些描述既涉及几何,也涉及摄影经验和画面构图。若直接把数值条件塞给生成模型,模型可能忽略或误解这些精细差异;若只训练视觉回归器,模型又容易停留在低/中层几何线索,比如边缘、消失点或地平线,而不能把 sky、floor、ceiling、foreground-background ratio、object scale 等更抽象的空间证据组织成连贯推理。因此本文提出 “Thinking with Camera”:把 camera 参数序列化成语言,借助 spatially grounded visual cues、professional photographic terms 和 geometric context,让模型先在语言空间里解释 camera,再输出参数或生成条件。
这个问题值得做,是因为 camera 是空间智能中连接二维图像与三维世界的关键接口。理解 camera 可以服务 single-view calibration、horizon prediction、摄影指导、AIGC 图像几何诊断;生成 camera 可以服务可控图像合成、跨视角世界探索、3D object insertion、机器人/具身系统中的观察视角模拟。更重要的是,统一模型带来的收益不只是“省一个模型”:理解侧的空间推理能给生成侧提供语义计划,生成侧的 camera map 和扩散训练又能逼迫模型学到更细粒度的相机—像素对应。本文的贡献因此可以概括为三点:提出 Puffin 统一架构;提出 Puffin-4M 与 Puffin-Und/Puffin-Gen 评测;用 staged training 让 camera-as-language、geometry-aligned vision encoder 和 diffusion generation 协同工作。
2. Idea (核心思想)
核心思想是:把 camera 从一个外部数值控制量变成多模态序列中的“语言”,同时保留像素级 camera map 作为生成时的连续几何条件。对于 understanding,Puffin 不再只做端到端回归,而是把图像、描述、推理过程和 roll/pitch/FoV 放在 next-token prediction 框架里学习;对于 generation,Puffin 用 LLM hidden states 和 learnable queries 形成 diffusion conditioning,再把 pixel-wise Perspective Field 经过 VAE 编码后作为额外 latent 条件注入 SD3 动态 transformer。换言之,Puffin 同时使用离散 camera tokens 和连续 camera latents:前者适合语言推理,后者适合图像生成的局部空间控制。
Figure 2 解读:框架图显示 Puffin 由 geometry-aligned vision encoder、LLM、connector、diffusion model 和 camera map pathway 组成。实线部分覆盖单视角 camera understanding 与 text-camera-to-image generation;虚线部分表示 instruction tuning 后扩展到 cross-view understanding/generation,例如 spatial imagination 与 world exploration。理解分支把 image token 接到 LLM,输出文本描述、reasoning 与 camera 参数;生成分支把文本/camera 条件经 LLM 和 connector 转成 SD3 可用的 pooled prompt 与 sequence prompt,再用 camera map latent 或 initial-view latent 做额外条件。
与常规 VLM fine-tuning 相比,Puffin 的新意不是“把 Qwen2.5-VL 换成另一个 backbone”,而是重新定义 camera 表征的粒度。论文指出,现有 VLM 的 vision encoder 往往为识别/语义任务压缩特征,几何细节不足;LLM 又缺少直接理解相机角度的先验。因此作者选择 C-RADIOv3-H 作为 geometry-aligned vision encoder,配合 Qwen2.5-1.5B-Instruct 做语言建模,并用 Stable Diffusion 3 Medium 做生成 backbone。这个组合把三类能力分开承担:RADIO 保留低/中层几何与语义特征,Qwen 负责 camera-as-language 的推理与参数序列化,SD3 负责高质量图像合成。关键连接件是两个 6-layer connector,把 LLM hidden states 投影成扩散模型需要的 pooled projection 与 joint attention conditioning。
Figure 3 解读:左侧代表传统 camera geometry learning:模型直接从图像提取几何或语义特征,再回归参数。右侧是本文的 thinking with camera:模型把图像中与重力、构图、视角相关的区域和摄影术语连接起来,并在 <think> 风格的推理中拆解 camera 参数,最后在 <answer> 中输出数值。这个差异很重要,因为 roll、pitch、FoV 的视觉证据并不完全一样:roll 常由 horizon/vertical line 支持,pitch 与 FoV 更依赖画面上下文、尺度、深度和构图。
从统一建模角度看,Puffin 做了一个折中:它没有试图把所有 camera 信息都离散化成文本,也没有只依赖 continuous control map。离散文本参数便于 LLM 与摄影术语对齐,例如 close-up、tilt-up、Dutch angle;连续 Perspective Field 则保留每个像素的 up-vector 与 latitude,用于扩散模型中的空间约束。这个双通路设计是本文最值得借鉴的地方:如果只做文本 camera prompt,生成模型可能学到粗糙的 global style;如果只做 camera map,模型很难解释为什么某个视角对应某种视觉现象。Puffin 把二者合并,使 reasoning 与 generation 可以互相提供监督。
3. Method (方法)
3.1 总体架构与输入/输出形式
Puffin 的输入输出根据任务切换。camera understanding 输入图像和问题,输出场景描述或空间推理,以及 roll、pitch、FoV;text-camera-to-image generation 输入场景 caption 和 camera 参数/相机图,输出符合目标视角的图像;instruction tuning 后的 cross-view generation 还会输入 initial view、target-view camera map 与可选文本描述,输出目标视角图像;cross-view understanding 则输入 initial view 与目标相机/位置,输出目标视角的想象描述或摄影建议。模型在代码中对应 src/models/puffin/model.py 的 Qwen2p5RadioStableDiffusion3HFDynamic,其 compute_loss() 会按 data_type 分发到 text2image_loss、cam2image_loss、image2image_loss、image2text_loss、text2text_loss 等路径。
模型配置来自 configs/models/qwen2_5_1_5b_radio_sd3_dynamic_puffin.py:LLM 是 Qwen/Qwen2.5-1.5B-Instruct,diffusion backbone 是 stabilityai/stable-diffusion-3-medium-diffusers,视觉编码器是 nvidia/C-RADIOv3-H。num_queries=64,两个 connector 都设为 hidden size 1024、intermediate size 4096、6 层、16 attention heads、FlashAttention2。camera 参数没有单独 tokenizer,而是被序列化为文本 token;camera map 则被 normalize 到 ,复用 VAE encoder,因为 Perspective Field 是三通道图。
3.2 Camera Understanding:把相机估计改写成 next-token prediction
理解分支把图像特征插入 LLM 输入序列,输出文本和 camera 参数。论文把 camera understanding 写成 image-conditioned QA:输出包含 concise description 或 spatial reasoning,再给出 roll、pitch、FoV。其训练目标在实现中对应 image2text_loss():代码先用视觉编码器得到 image_embeds,把 INPUT_IMAGE_TOKEN_INDEX 位置替换成图像 embedding,其他 token 走 LLM embedding,然后对 assistant 输出位置做 cross entropy。这个实现说明本文的“语言回归”不是额外接一个 MLP head 回归角度,而是让 LLM 通过文本序列预测 camera 参数。
def camera_understanding_loss(llm, vision_encoder, tokenizer, batch):
# Based on src/models/puffin/model.py:image2text_loss
input_ids = batch["input_ids"]
labels = batch["labels"]
pixel_values = batch["pixel_values"]
image_embeds = vision_encoder(pixel_values) # geometry-aware visual tokens
inputs_embeds = llm.get_input_embeddings()(input_ids)
image_pos = input_ids == INPUT_IMAGE_TOKEN_INDEX
inputs_embeds[image_pos] = image_embeds.flatten(0, 1)
logits = llm(inputs_embeds=inputs_embeds,
attention_mask=batch["attention_mask"]).logits
return F.cross_entropy(logits[:, :-1].reshape(-1, logits.size(-1)),
labels[:, 1:].reshape(-1),
ignore_index=-100)这里的关键不是公式本身,而是训练信号的组织。若 camera 参数直接作为回归标签,模型只能学“图像到角度”;若 camera 参数写进语言答案,模型被迫学习“图像线索—摄影术语—角度数值”的中间桥梁。论文中的 thinking captions 包含三类信息:spatially grounded visual cues,如 sky/floor/ceiling/ground 对 pitch 的提示;professional photographic terms,如 close-up、tilt-up、Dutch angle;geometric context,即 roll、pitch、FoV 之间的相互约束。这样做尤其有助于 pitch 和 FoV,因为它们比 roll 更依赖全局构图和对象尺度。
3.3 Camera-Controllable Generation:离散 camera token + 连续 camera map
生成分支面对的问题更难:文本可以描述场景语义,但 camera 控制要求图像中每个位置的空间关系正确。Puffin 因此把 camera 分为两种条件。第一种是离散 camera token,进入 LLM 与文本 prompt 一起建模;第二种是 pixel-wise Perspective Field,被 VAE 编码成 cam_latents,在扩散 denoising 时作为 cond_hidden_states 输入 transformer。数据构造中 Perspective Field 每个像素包含 up-vector 与 latitude :
其中 是 3D 点到像素的投影, 是该像素对应的光线, 是重力方向。直观理解是:up-vector 告诉模型每个像素处“向上”应该朝哪里,latitude 告诉模型该光线相对重力方向的仰角。它比全局 roll/pitch/FoV 更细,因为同一张图内部不同像素的空间方向不同。
def camera_conditioned_diffusion_loss(model, batch):
# Based on text2image_loss/cam2image_loss/image2image_loss and diff_loss
image_latents = model.pixels_to_latents(batch["target_image"])
camera_latents = model.pixels_to_latents(batch["camera_map"]) # Perspective Field as 3-channel map
input_ids, attention_mask = batch["input_ids"], batch["attention_mask"]
query = model.query_tokens.expand(input_ids.size(0), model.num_queries, -1)
inputs = model.prepare_forward_input(input_ids=input_ids,
attention_mask=attention_mask,
query_embeds=query)
pooled_prompt, sequence_prompt = model.forward_connector(inputs)
noise = torch.randn_like(image_latents)
timesteps = sample_flow_matching_timesteps(image_latents.size(0))
noisy_latents = (1 - sigma(timesteps)) * image_latents + sigma(timesteps) * noise
pred = model.transformer(hidden_states=noisy_latents,
timestep=timesteps,
encoder_hidden_states=sequence_prompt,
pooled_projections=pooled_prompt,
cond_hidden_states=camera_latents)
target = noise - image_latents
return F.mse_loss(pred, target)实现上,src/models/puffin/model.py:342 的 diff_loss() 使用 SD3 的 flow matching 训练形式;cam2image_loss() 在代码中把 camera map 作为 diffusion condition;image2image_loss() 进一步把 camera map 与 initial view latent 组合为 mix_latents,用于 cross-view generation。src/models/stable_diffusion3/transformer_sd3.py 和 transformer_sd3_dynamic.py 中的 cond_hidden_states 会接入 transformer hidden states,这使 camera map 不只是 prompt 文本,而是直接影响 denoising token 的空间结构。
3.4 Puffin-4M 数据构造与训练阶段
Figure 4 解读:Puffin-4M 是 4M 规模的 vision-language-camera triplets,覆盖不同场景和相机配置。图中不同颜色表示不同 camera configuration variant。这个数据集的价值在于同时给出图像、caption、全局 camera 参数和可生成 camera map 的信息,使 understanding 与 generation 可以共享相机语义。
Figure 5 解读:数据流水线分四步:收集和清洗 panorama;按 pinhole camera model 渲染 perspective crops;生成 scene caption 与 spatial reasoning caption;扩展 cross-view / photography guidance 数据。P2T 表示把数值 camera 参数映射成 professional photographic terms,这是 thinking with camera 的监督来源之一。
Puffin-4M 从公开全景数据和在线平台收集 panorama,随后按 vertical FoV、roll、pitch 采样生成 perspective images。采样范围是 roll 、pitch 、vertical FoV ;每个 panorama 生成多少 crop 取决于原始分辨率。caption 先由 Qwen2.5-VL-7B-Instruct 生成语义丰富描述,再由 Qwen2.5-7B-Instruct 压缩成更适合 text-to-image 的简洁句子;thinking captions 则使用 Qwen2.5-VL-32B-Instruct 生成,以便把视觉线索、摄影术语和 camera 数值联系起来。cross-view 数据加入 yaw,自初始标准视角渲染目标视角;photographic guidance 由专家/爱好者定义 viewpoint creativity、subject emphasis、compositional balance、spatial harmonization 四个美学方面,用 Qwen2.5-VL-32B-Instruct 对候选视角投票,取最高分视角相对初始视角的 pitch/yaw 偏移作为标签。
训练分四阶段,论文 Table 1 与 repo 配置相互对应:Stage I alignment 冻结 vision encoder、LLM、diffusion model,只训练 projector/connector 做理解与生成对齐;Stage II SFT 解冻除 VAE 外的主要模块,混合 base understanding 与 generation 数据;Stage III SFT w/ Thinking 引入 spatial reasoning captions 和 text-to-text 任务,把 thinking with camera 加进训练;
Stage IV instruction tuning 冻结 vision encoder,训练 cross-view understanding、cross-view generation、photography guidance。论文训练配置为:学习率 ,batch size 1024/1024/512/256,training steps 10K/30K/60K/20K,warm-up 1K/900/1.8K/600,AdamW、Cosine scheduler、weight decay 0.05、betas (0.9, 0.95)。
实验部分报告完整训练约 4 天,使用 64 张 NVIDIA A100 80GB。
Code reference:
main@6da4f08f(2026-02-18) — pseudocode and mapping based on this commit
| Paper concept | Repo evidence |
|---|---|
| Unified Puffin model | src/models/puffin/model.py → Qwen2p5RadioStableDiffusion3HFDynamic |
| Backbone config | configs/models/qwen2_5_1_5b_radio_sd3_dynamic_puffin.py |
| Stage I/II/III/IV training | configs/pipelines/stage_1_alignment.py, stage_2_base.py, stage_3_thinking.py, stage_4_instruction_tuning.py |
| Base data mix | configs/datasets/basic/concat_datasets_cam.py → image2text + cam2image, repeats [1,1], batch sizes [16,16] |
| Thinking data mix | configs/datasets/reasoning/concat_datasets.py → image2text, cam2image, text2text, repeats [1,1,1], batch sizes [8,8,8] |
| Instruction data mix | configs/datasets/instruction/concat_datasets.py → cross-view understanding, cross-view generation, photography guidance, repeats [8,8,1] |
| Camera map generation path | scripts/camera/cam_dataset.py; dataset configs expect Puffin-4M/training_data/cam_folder/ |
| Inference demos | scripts/demo/generation.py, understanding.py, world_exploration.py, spatial_imagination.py, photographic_guidance.py |
def staged_puffin_training():
# Stage I: align modality interfaces, not all backbones
train(config="configs/pipelines/stage_1_alignment.py",
trainable=["projector", "connector"],
tasks=["image2text", "cam2image"],
lr=1e-4, steps=10_000, batch_size=1024)
# Stage II: base SFT, all major modules except VAE are trainable
train(config="configs/pipelines/stage_2_base.py",
trainable=["vision_encoder", "llm", "sd3_transformer", "connector"],
tasks=["image2text", "cam2image"],
lr=2e-5, steps=30_000, batch_size=1024,
visual_encoder_grad_scale=0.1)
# Stage III: add thinking with camera
train(config="configs/pipelines/stage_3_thinking.py",
tasks=["image2text_with_reasoning", "cam2image_with_reasoning", "text2text"],
lr=1e-5, steps=60_000, batch_size=512)
# Stage IV: instruction tuning for cross-view and photography tasks
train(config="configs/pipelines/stage_4_instruction_tuning.py",
tasks=["cross_view_understanding", "cross_view_generation", "photographic_guidance"],
lr=5e-6, steps=20_000, batch_size=256,
freeze=["vision_encoder"])3.5 Inference 与 cross-view 扩展
推理时,generate() 会先可选地产生 reasoning 文本,再根据任务准备 diffusion condition:若是 camera map generation,则使用 target camera map latent;若是 cross-view generation,则额外加入 initial view latent;若是普通 text-to-image,则仅使用文本/camera token 经过 connector 得到的 prompt embeddings。understand() 则走 autoregressive decoding,默认 max_new_tokens=512,输出 camera 参数和描述。README 公开了 Puffin-Base、Puffin-Thinking、Puffin-Instruct 三个模型变体:Base 是统一基础模型,Thinking 加入 spatial reasoning,Instruct 支持 cross-view tasks 和复杂多模态交互。
Figure 10 解读:应用图展示 3D object insertion、world exploration、spatial imagination、photographic guidance 等扩展任务。它说明 Puffin 的 instruction tuning 并不是另起一套模型,而是在同一 camera-centric 表征上追加任务 token 与 prompt 模板,让模型能从 single-view calibration / text-to-image 控制扩展到跨视角推理。
4. Experimental Setup (实验设置)
实验设置可以分成 understanding、generation、ablation 三组。implementation details 中,Puffin 使用 C-RADIOv3-H、Qwen2.5-1.5B-Instruct、SD3-Medium 初始化三大模块;learnable queries 数量为 64,connector 为 6-layer transformer;图像和 camera maps 分辨率统一为 。camera 参数 tokenization 复用标准 text tokenizer;camera map 复用 VAE encoder。训练过程四阶段共约 4 天、64×A100 80GB。代码配置与论文 Table 1 的关键数值一致:Stage I/II 使用 base concat_datasets_cam,Stage III 使用 reasoning datasets,Stage IV 使用 instruction datasets。
camera understanding 的评测包括 public datasets MegaDepth、TartanAir、LaMAR,以及作者构建的 Puffin-Und。指标按 roll、pitch、FoV 分组,每组包含 mean error(degrees,越低越好)和 AUC@1/5/10 degrees(越高越好)。由于训练固定在 方图,非方图评测采用 central crop + resize,并按 crop ratio 调整 vertical FoV;作者明确指出这会在 aspect ratio 偏离 1 的数据上丢失有效内容,LaMAR 上的部分落后与此有关。
camera-controllable generation 的评测基准是 Puffin-Gen,包含 650 个 caption-camera pairs,覆盖不同场景和 camera configurations。比较对象包括 PreciseCam、GPT-4o、Qwen-Image、Nano Banana;对 multimodal models,论文把 camera 参数从 radians 转 degrees 或转成 professional photographic terms,以减轻提示格式差异。生成评价使用 GeoCalib 估计 pixel-wise camera maps,再和 GT maps 计算 up vector、latitude、gravity 的 mean/median error;同时用 FID 评价视觉质量。这里要注意,camera generation 的评价不是人工偏好分,而是借助离线 calibration 模型的几何误差,因此作者也把“生成图像中微小空间差异的评价歧义”列为未来挑战。
主要 baselines 覆盖三类:camera understanding 中的 DeepCalib、Perceptual、CTRL-C、MSCC、ParamNet、SVA、UVP、Perspective Fields、GeoCalib;generation 中的 PreciseCam 与通用强 multimodal/image generation models;architecture ablation 中的 InternVL3、Qwen2.5-VL、纯 Vision Encoder、Ours、Ours w/ Thinking。数据集对比表显示,GeoCalib 是 understanding-only,37K frames,包含 与 ;PreciseCam 是 generation-only,57K frames;Puffin-4M 是 unified,4M frames,intrinsics 为 ,extrinsics 为 ,并覆盖更多细节维度。这个设置支撑了作者的论点:Puffin 的优势来自统一任务定义、数据规模和 camera-as-language 训练,而不是只在某个 benchmark 上调参。
5. Experimental Results (实验结果)
5.1 Camera understanding 主结果
在 MegaDepth 上,Puffin 的 roll mean error/AUC@1/5/10 为 0.32/84.9/93.4/96.2,pitch 为 1.08/47.6/68.2/79.4,FoV 为 2.42/23.9/47.8/64.1,整体优于 GeoCalib 的 0.36、1.94、4.46 mean errors。TartanAir 上,Puffin 在 roll 和 pitch 上最好或接近最好:0.40/71.7/86.2/92.1 与 0.95/51.0/68.2/79.3;FoV mean error 为 7.48,低于 GeoCalib 的 4.90,但仍给出 16.3/28.5/39.0 的 AUC。LaMAR 上,Puffin 的 roll/pitch/FoV mean errors 为 0.38/0.71/3.62,其中 pitch 最好,但 roll 与 FoV 低于 GeoCalib 的 0.28/0.87/3.03;作者把这部分归因于固定方图训练与 central cropping 对非方图内容的损失。
在更贴近本文任务的 Puffin-Und 上,Puffin 明显领先:roll 为 0.41/78.3/91.0/95.2,pitch 为 0.74/60.2/81.2/90.0,FoV 为 1.21/42.4/70.5/84.3;GeoCalib 对应为 0.92、2.18、5.04 mean errors。这个结果比 public datasets 更能说明 thinking with camera 的收益,因为 Puffin-Und 更强调 diverse camera configurations 和挑战性视角。论文还观察到 roll 相对更容易,pitch/FoV 更难:roll 有明确的 horizon、vertical edges 等几何线索;pitch 和 FoV 则更依赖画面范围、前景背景比例、对象尺度和深度分布,单纯视觉回归更容易失败。
5.2 Camera-controllable generation 主结果

Figure 6 解读:这组图展示生成图像、估计 camera map、GT camera map 和误差图。它强调 Puffin 的优势不是只生成看起来合理的图片,而是在 latitude/up-vector 这样的像素级几何指标上更接近目标相机。用误差图可见,通用生成模型即使语义对齐,也可能在重力方向或视场变化上错位。
在 Puffin-Gen 上,Puffin 的 up-vector mean/median error 为 11.94/10.12,latitude 为 6.34/4.04,gravity 为 6.79/3.43,FID 为 69.46;PreciseCam 分别为 18.66/17.47、12.49/9.99、18.39/15.34、FID 90.91;Qwen-Image* 的 up-vector、latitude、gravity mean errors 为 23.80、15.76、27.75,FID 83.31。Puffin 同时在几何误差和 FID 上领先,说明它没有通过牺牲视觉质量换几何控制,也没有只靠通用模型的美学先验获得较低 FID。论文讨论中特别指出 roll 生成比 pitch/FoV 更难,因为 roll 会改变图像中“重力方向”的常识布局,例如 Dutch angle 可能让海平面看似高于 horizon;这种变化与摄影美学数据分布中的 near-level bias 冲突。
Figure 7 解读:预测相机参数与 GT 的散点/分布对比进一步说明 Puffin 对 camera conditions 的响应更线性、更稳定。对于通用生成模型,camera prompt 往往被当作弱文本属性,生成结果的相机估计会向常见构图回归;Puffin 因为有 camera map latent 和 camera tokens 的双约束,偏移更小。
5.3 Ablation 与组件贡献
camera understanding ablation 显示,直接 fine-tune InternVL3 或 Qwen2.5-VL 并不可靠:InternVL3 的 roll/pitch/FoV mean errors 为 0.91/1.72/2.96,Qwen2.5-VL 为 0.79/1.61/2.91;纯 Vision Encoder 为 0.55/1.00/1.87;Ours 为 0.47/0.91/1.48;Ours w/ Thinking 进一步降到 0.41/0.74/1.21。AUC 也同步提升:Ours w/ Thinking 在 FoV 上达到 42.4/70.5/84.3,而 Ours 为 38.0/66.2/81.5。这组结果支持作者的两个判断:一是现成 VLM vision encoder 对几何信息压缩过度,直接 SFT 可能不如专门视觉模型;二是 thinking captions 给 pitch/FoV 这类需要全局空间语义的参数带来额外收益。
Figure 8 解读:生成 ablation 主要验证 thinking mode 和 precise camera map 的作用。thinking mode 提供语义规划,帮助模型先解释视觉/摄影线索;camera map 提供 pixel-level 几何约束,减少只靠文本参数导致的空间漂移。二者互补:thinking 改善 prompt-level spatial reasoning,camera map 改善 denoising-level local control。
5.4 应用、局限与可复现性判断
Puffin-Instruct 展示了 spatial imagination、world exploration、photographic guidance 等应用。world exploration 可以迭代生成新视角并用 VGGT 重建 3D,spatial imagination 可以从初始视角和目标位置描述目标视角,photographic guidance 可以建议 pitch/yaw 调整以提高美学。README 中对应 demo 包括 scripts/demo/world_exploration.py、world_exploration_3D.py、spatial_imagination.py、photographic_guidance.py,模型权重在 HuggingFace KangLiao/Puffin,数据集在 KangLiao/Puffin-4M。
论文的局限也比较清楚。第一,训练数据固定 ,所以生成目前受限于单尺度,理解侧对非方图需要 central crop + resize;这会丢信息,尤其影响 LaMAR 这类 aspect ratio 差异较大的数据。第二,generation evaluation 依赖离线 camera calibration model,生成图像中细微空间差异是否真的对应错误 camera map 仍有歧义。第三,当前 camera model 主要是 ideal pinhole,radial distortion 只作为未来工作;而真实相机/手机图像往往存在畸变。第四,cross-view 能力仍是 instruction tuning 扩展,离真正长时序、多视角一致的视频世界模型还有距离。总体看,Puffin 的主要贡献在于把 camera-centric understanding/generation 做成统一可训练系统,并给出代码、模型、数据和 benchmark;若要复现,最关键的不是重写推理脚本,而是获得 Puffin-4M、camera map 生成流水线和四阶段训练资源。
def puffin_inference_router(model, task, batch):
if task == "understanding":
return model.understand(prompt=batch["question"],
pixel_values=batch["image"],
max_new_tokens=512)
if task == "generation_base":
return model.generate(prompt=batch["caption"],
camera=batch["roll_pitch_fov"],
camera_map=batch["camera_map"],
thinking=False)
if task == "generation_thinking":
reasoning = model.understand(prompt=batch["reasoning_prompt"],
pixel_values=batch.get("reference_image"),
max_new_tokens=512)
return model.generate(prompt=batch["caption"],
camera=batch["roll_pitch_fov"],
camera_map=batch["camera_map"],
prompt_reasoning=reasoning,
thinking=True)
if task == "cross_view_generation":
return model.generate(prompt=batch.get("caption"),
init_view=batch["initial_image"],
camera_map=batch["target_camera_map"],
yaw=batch["target_yaw"],
cross_view=True)
raise ValueError(task)从 taxonomy 来看,本文最合适放在 Multimodal Generation / Pretraining & Architecture,而不是单纯 World Model 或 Physical AI。原因是主贡献是统一多模态架构、数据与训练范式:Puffin 当然服务于空间智能和跨视角生成,但论文中心不是机器人策略、视频世界模型或 3D simulation,而是 camera-as-language 的 multimodal understanding/generation pretraining architecture。对后续工作,最值得复用的是三件事:把非语言控制量转写成可推理 token;保留连续 map/latent 做像素级控制;用 staged training 逐步对齐 vision、language、diffusion,而不是一次性端到端混训。