介绍
你如何描述一个场景?这听起来像是一个简单的问题,但试着精确一点。想象一下,你刚从复活节岛旅行归来,想向朋友描述著名的阿胡阿基维 (Ahu Akivi) 遗址。你可能会说: “有七尊摩艾石像排成一排,面朝同一个方向。”
你的朋友问: “什么是摩艾石像?” 你回答: “它是一种由石头雕刻而成的巨型人形雕像,头很大,没有腿。” “它们看起来完全一样吗?” “不,”你犹豫了一下。“它们拥有相同的结构,但每一尊都有略微不同的风化纹理和独特的身份特征。”
这个场景凸显了我们在表示视觉世界时的一个根本性脱节。自然语言非常擅长表达高层语义 (“摩艾石像”) ,但在精确的空间排列 (“七个排成一排”) 方面很吃力,而且往往无法捕捉特定实例的微妙视觉身份 (这块特定石头的独特纹理) 。
在计算机视觉和3D生成的世界里,这个问题是介于优质图像与可控、高保真3D场景之间的瓶颈。我们拥有的工具往往擅长其中一方面,但很少能兼顾这三者。
在这篇博文中,我们将深入探讨一篇题为 “The Scene Language: Representing Scenes with Programs, Words, and Embeddings” 的论文,作者来自斯坦福大学和加州大学伯克利分校的研究人员。他们提出了一种新颖的表示方法,不是在这些模态之间做选择,而是将它们结合起来。

如图1所示,这种新的“场景语言 (Scene Language) ”允许生成复杂的3D场景,用户可以通过编辑代码来更改布局,或通过替换嵌入来更改艺术风格——所有这些都可以从文本或图像中推断出来。
背景: 场景表示的三难困境
要理解为什么“场景语言”是如此重要的一步,我们首先需要看看现有方法的局限性。一个完整的场景表示需要捕捉三种类型的信息:
- 结构性知识 (Structural Knowledge) : 实例的联合分布。例如,“一排雕像”或“桌子周围的椅子”。这是关系性和层次性的。
- 类别级语义 (Category-Level Semantics) : 事物是什么。如“椅子”或“树”的概念。
- 实例级本质特征 (Instance-Level Intrinsics) : 特定的身份。如桌子上确切的木纹或叶子上特定的光照。
现代AI通常孤立地解决这些问题:
- 程序 (Programs) : 程序化生成和形状程序 (如ShapeAssembly) 在处理结构方面表现出色。它们可以定义循环、重复和对称。然而,它们通常是“盲目”的——它们处理的是长方体和几何基元,缺乏逼真的纹理和外观。
- 场景图 (Scene Graphs) : 这些图将场景表示为节点 (物体) 和边 (关系) 。虽然它们捕捉了“A在B之上”这样的关系,但往往过于粗糙。它们遗漏了精确的几何细节和物体微妙的视觉“氛围”。
- 神经嵌入/潜变量 (Neural Embeddings/Latents) : 生成模型 (如Stable Diffusion) 使用高维向量来捕捉令人难以置信的视觉细节。然而,这些潜在空间是非结构化的。你无法轻易地进入一个潜在向量并说: “把第三个物体向左移动五个单位”。
该论文的作者认为,仅靠这些方法中的任何一种都是不够的。我们需要一种混合方法。
核心方法: 场景语言 (Scene Language)
研究人员介绍了 场景语言 (Scene Language) , 表示为 \(\Phi(s)\)。它整合了三种模态来填补其他方法留下的空白。

如图2所示,场景语言使用一个包含三个组件的元组来表示场景。形式上定义为:

让我们分解这三大支柱:
- \(W\) (单词) : 这些是自然语言中的短语 (例如,“pawn” (兵) ,“board” (棋盘) ) ,表示实体的语义类别。它们提供了高层次的“是什么”。
- \(P\) (程序) : 这是一组编码结构的函数。它指定了实体的存在、它们的层次结构以及它们的空间关系 (外参) 。
- \(Z\) (嵌入) : 这些是神经嵌入,捕捉低级视觉细节和特定身份 (内参) 。
1. 程序 (\(P\)) 与结构
程序是场景的骨架。它描述了部分如何组合成整体。在场景语言中,程序由 实体函数 (Entity Functions) 组成。
一个实体函数,记作 \(f_w\),定义了一类实体 (由单词 \(w\) 标记) 。它接受神经嵌入作为输入,并输出一个特定的实体 \(h\)。关键在于,这是递归的。一个物体 (如棋盘) 由子物体 (方格和棋子) 组成,而子物体又由基元组成。
实体函数的递归定义在数学上形式化为:

让我们解读这个方程:
- \(\Psi_{\text{union}}\) : 此操作将多个子实体组合成单个父实体。
- \(\Psi_{\text{transform}}\) : 此操作将空间位姿 (平移、旋转、缩放) ,记作 \(t^{(i)}(z)\),应用于子实体。
- 递归 : 子实体 \(h^{(i)}\) 本身是另一个实体函数 \(f_{w^{(i)}}\) 的结果。
这种结构自然地反映了现实世界的层次性质。“一套餐桌椅”不仅仅是一堆像素;它是一张桌子和几把椅子。“椅子”是由腿、座面和靠背组成的。程序 \(P\) 捕捉了这种显式的依赖结构。
2. 嵌入 (\(Z\)) 与视觉身份
虽然程序定义了物体 在哪里 以及逻辑上 是什么,但嵌入定义了它们 看起来如何。
该系统使用 CLIP嵌入 (\(Z_{\text{CLIP}}\)) 。这些嵌入非常强大,因为它们连接了文本和图像。嵌入 \(z\) 捕捉了特定的属性——比如“红木”或“生锈的金属”——这些属性很难在程序中显式编码,但对于神经网络来说很容易理解。
通过使用这些嵌入来参数化实体函数,场景语言允许在一个结构主题上进行“无限”变体。你可以重用“一排雕像”的结构代码,但将嵌入 \(z\) 从“石头摩艾”换成“金色机器人”,场景会立即更新,同时保持布局不变。
3. 领域特定语言 (DSL)
为了使其可操作,研究人员将场景语言实现为Python中的一种领域特定语言 (DSL) 。该DSL包含映射到我们讨论过的数学运算的宏:
union: 组合实体。transform: 应用位姿矩阵。union-loop: 程序化循环 (例如,“重复此列4次”) ,捕捉结构规律性。call: 检索绑定到单词的函数并将其应用于嵌入。

表5 (上图) 详细说明了语法。这不仅仅是理论上的;它看起来像Lisp风格或Python风格的代码。例如,创建一个物体排列的函数可能看起来像 (union-loop 7 create-moai),这使得场景结构具有可读性和可编辑性。
渲染: 从代码到像素
一旦我们要么有了场景语言表示 \(\Phi(s)\),我们如何将其转化为图像?这个过程称为 渲染 。
该框架被设计为与渲染器无关。它将渲染引擎视为一个模块。

如图3所示,该过程有几个不同的步骤:
- 程序执行: 解释器使用嵌入 \(Z\) 运行程序 \(P\)。这将循环和函数调用展开为静态的 计算图 或实体树 (图3b) 。
- 重参数化: 这是巧妙的部分。通用的实体需要被翻译成图形引擎的特定语言。
- 渲染操作 (\(\mathcal{R}\)): 引擎获取参数并生成图像。
论文展示了几种不同的渲染器,总结在表2中:

案例研究: 3D高斯泼溅 (基于SDS)
论文中最令人印象深刻的实现之一是使用通过分数蒸馏采样 (SDS) 优化的 3D高斯泼溅 (3D Gaussian Splatting) 。
在这个设置中:
- 基元: 实体树的“叶子”表示为3D高斯 (椭球体) 簇。
- 优化: 系统优化这些高斯的参数,以便在渲染时,它们与关联的CLIP嵌入 \(z\) 相匹配。
- 数学: 渲染操作 \(\mathcal{R}\) 遵循标准的高斯泼溅公式:

重要的是,因为场景语言显式处理变换,变换后的物体 \(G_t\) 可以通过将变换矩阵 \(t\) 应用于高斯参数 (均值和协方差) 来数学推导:

这意味着神经网络不需要“学习”旋转物体。程序在数学上处理旋转,而神经网络专注于纹理和形状。
优化过程最小化一个损失函数 (\(\mathcal{L}\)) ,该函数结合了SDS损失 (确保图像看起来像文本描述) 和几何正则化:

结果呢?生成了清晰、3D一致的场景,其中结构由代码强制执行,而外观由现代扩散模型生成。
推理: “免训练”生成
这可能是论文中最现代的转折点: 首先你是如何得到场景语言代码的? 你不需要训练一个庞大的新网络来输出代码。你只需要询问大型语言模型 (LLM) 。
作者提出了一个 免训练推理模块 。 他们向预训练的LLM (如GPT-4或Claude) 提供DSL规范和一些示例。然后,给定一个文本提示 (例如,“为比赛设置好的棋盘”) ,LLM编写定义结构的Python脚本。
- 对于文本输入: LLM构想出程序结构并建议用于嵌入的单词。
- 对于图像输入: 系统使用视觉语言模型来分割图像,识别物体,然后 (通过文本反转) 优化嵌入以匹配输入图像的视觉风格。
这利用了LLM的“常识”推理能力。LLM知道“桌子”通常有四条腿和一个平坦的顶部,所以它会编写一个带有 union-loop 的程序来生成腿。
实验与结果
研究人员在多个任务中评估了场景语言: 文本提示生成、图像提示生成和场景编辑。
1. 文本提示生成
主要的对比对象是 MVDream (一种没有结构表示的直接文本到3D方法) 和 GraphDreamer (使用场景图) 。

看图4。提示语“15个可乐罐堆成金字塔”是对计数和结构的压力测试。
- MVDream 创建了杂乱的一堆。它理解“罐子”,但不理解金字塔的精确几何形状。
- GraphDreamer 建立了一个结构,但在确切数量或排列上经常失败,因为场景图太抽象了。
- Ours (场景语言) : 生成了一个精确的数学金字塔。因为LLM写了一个循环来堆叠它们,结构是完美的。
定量结果 (表3,通过视觉结果隐式引用) 表明,场景语言在计数准确性和与用户提示的对齐方面显著优于基线。
2. 跨渲染器的一致性
最酷的功能之一是能够切换渲染器。同一个 程序可以渲染为高保真的高斯泼溅、块状的Minecraft建筑或矢量风格的Mitsuba渲染。

图5展示了这种多功能性。无论是网球场还是阶梯教室,结构完整性在不同的视觉领域中保持一致。
3. 场景编辑
这就是“语言”部分发光的地方。因为场景被表示为代码,编辑是直观的。
- 指令: “将分支结构改为三叉。”
- 动作: LLM将代码中的
loop计数从2修改为3。

在图7 (顶部) 中,用户要求“将楼梯半径缩小80%”。在基于像素的生成模型中,这可能会扭曲楼梯或破坏纹理。在场景语言中,这只是脚本中的参数更改。楼梯缩小了,但纹理和光照 (嵌入) 保持完美一致。
他们还演示了 基于图像的编辑 (风格迁移) 。通过用从用户照片中提取的新嵌入替换特定物体的嵌入 \(z\),他们可以仅更改“摩艾石像”的风格,而保持平台不变。

4. 4D生成 (动画)
该表示法还支持时间。通过在程序的变换矩阵中添加时间参数,系统可以生成4D场景 (3D + 时间) 。

图6显示了一个移动的旋转木马和风力涡轮机。因为运动是以编程方式定义的 (例如,rotation_matrix(time * speed)) ,所以运动是平滑且物理上合理的,不像视频生成模型中经常看到的“抖动”运动。
结论与启示
“场景语言”论文为计算机视觉中的 神经符号AI (neuro-symbolic AI) 提供了一个令人信服的案例。它表明我们不应该在所有事情上都仅仅依赖神经网络这个“黑盒子”。
通过解耦 结构 (由程序/LLM处理) 、语义 (由单词处理) 和 外观 (由嵌入处理) ,我们获得了所有世界的最佳结合:
- 精度: 代码保证了直线、确切的计数和完美的对称性。
- 保真度: 神经嵌入提供了手工编码资产所缺乏的照片级逼真纹理。
- 可控性: 用户可以通过更改文本、代码或参考图像来编辑场景。
这项工作为“逆向图形学 (Inverse Graphics) ”管线铺平了道路,我们可以将现实世界解构为可编辑的代码,本质上将现实变成一个可编程引擎。对于学生和研究人员来说,它凸显了一个令人兴奋的方向: 不再仅仅将生成视为像素预测,而是将其视为程序合成。
](https://deep-paper.org/en/paper/2410.16770/images/cover.png)