介绍

你如何描述一个场景?这听起来像是一个简单的问题,但试着精确一点。想象一下,你刚从复活节岛旅行归来,想向朋友描述著名的阿胡阿基维 (Ahu Akivi) 遗址。你可能会说: “有七尊摩艾石像排成一排,面朝同一个方向。”

你的朋友问: “什么是摩艾石像?” 你回答: “它是一种由石头雕刻而成的巨型人形雕像,头很大,没有腿。” “它们看起来完全一样吗?” “不,”你犹豫了一下。“它们拥有相同的结构,但每一尊都有略微不同的风化纹理和独特的身份特征。”

这个场景凸显了我们在表示视觉世界时的一个根本性脱节。自然语言非常擅长表达高层语义 (“摩艾石像”) ,但在精确的空间排列 (“七个排成一排”) 方面很吃力,而且往往无法捕捉特定实例的微妙视觉身份 (这块特定石头的独特纹理) 。

在计算机视觉和3D生成的世界里,这个问题是介于优质图像与可控、高保真3D场景之间的瓶颈。我们拥有的工具往往擅长其中一方面,但很少能兼顾这三者。

在这篇博文中,我们将深入探讨一篇题为 “The Scene Language: Representing Scenes with Programs, Words, and Embeddings” 的论文,作者来自斯坦福大学和加州大学伯克利分校的研究人员。他们提出了一种新颖的表示方法,不是在这些模态之间做选择,而是将它们结合起来。

图1. 使用场景语言进行结构化场景生成和编辑。该系统使用程序定义结构 (左) ,自然语言定义语义,嵌入定义视觉风格 (右) ,从而实现精确编辑,如风格迁移。

如图1所示,这种新的“场景语言 (Scene Language) ”允许生成复杂的3D场景,用户可以通过编辑代码来更改布局,或通过替换嵌入来更改艺术风格——所有这些都可以从文本或图像中推断出来。

背景: 场景表示的三难困境

要理解为什么“场景语言”是如此重要的一步,我们首先需要看看现有方法的局限性。一个完整的场景表示需要捕捉三种类型的信息:

  1. 结构性知识 (Structural Knowledge) : 实例的联合分布。例如,“一排雕像”或“桌子周围的椅子”。这是关系性和层次性的。
  2. 类别级语义 (Category-Level Semantics) : 事物是什么。如“椅子”或“树”的概念。
  3. 实例级本质特征 (Instance-Level Intrinsics) : 特定的身份。如桌子上确切的木纹或叶子上特定的光照。

现代AI通常孤立地解决这些问题:

  • 程序 (Programs) : 程序化生成和形状程序 (如ShapeAssembly) 在处理结构方面表现出色。它们可以定义循环、重复和对称。然而,它们通常是“盲目”的——它们处理的是长方体和几何基元,缺乏逼真的纹理和外观。
  • 场景图 (Scene Graphs) : 这些图将场景表示为节点 (物体) 和边 (关系) 。虽然它们捕捉了“A在B之上”这样的关系,但往往过于粗糙。它们遗漏了精确的几何细节和物体微妙的视觉“氛围”。
  • 神经嵌入/潜变量 (Neural Embeddings/Latents) : 生成模型 (如Stable Diffusion) 使用高维向量来捕捉令人难以置信的视觉细节。然而,这些潜在空间是非结构化的。你无法轻易地进入一个潜在向量并说: “把第三个物体向左移动五个单位”。

该论文的作者认为,仅靠这些方法中的任何一种都是不够的。我们需要一种混合方法。

核心方法: 场景语言 (Scene Language)

研究人员介绍了 场景语言 (Scene Language) , 表示为 \(\Phi(s)\)。它整合了三种模态来填补其他方法留下的空白。

图2. 概览。场景语言用三个组件表示场景: 由实体函数组成的程序、一组单词和通过嵌入列表。

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

定义场景语言为单词、程序和嵌入的元组的方程。

让我们分解这三大支柱:

  1. \(W\) (单词) : 这些是自然语言中的短语 (例如,“pawn” (兵) ,“board” (棋盘) ) ,表示实体的语义类别。它们提供了高层次的“是什么”。
  2. \(P\) (程序) : 这是一组编码结构的函数。它指定了实体的存在、它们的层次结构以及它们的空间关系 (外参) 。
  3. \(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. 领域特定语言规范。

表5 (上图) 详细说明了语法。这不仅仅是理论上的;它看起来像Lisp风格或Python风格的代码。例如,创建一个物体排列的函数可能看起来像 (union-loop 7 create-moai),这使得场景结构具有可读性和可编辑性。

渲染: 从代码到像素

一旦我们要么有了场景语言表示 \(\Phi(s)\),我们如何将其转化为图像?这个过程称为 渲染

该框架被设计为与渲染器无关。它将渲染引擎视为一个模块。

图3. 渲染管线。(a) 场景语言代码。(b) 执行为实体树。(c) 针对特定渲染器的重参数化。(d) 最终图像输出。

如图3所示,该过程有几个不同的步骤:

  1. 程序执行: 解释器使用嵌入 \(Z\) 运行程序 \(P\)。这将循环和函数调用展开为静态的 计算图 或实体树 (图3b) 。
  2. 重参数化: 这是巧妙的部分。通用的实体需要被翻译成图形引擎的特定语言。
  3. 渲染操作 (\(\mathcal{R}\)): 引擎获取参数并生成图像。

论文展示了几种不同的渲染器,总结在表2中:

表2. 图形渲染器示例,包括基于基元的、基于资产的、基于SDS的和T2I模型。

案例研究: 3D高斯泼溅 (基于SDS)

论文中最令人印象深刻的实现之一是使用通过分数蒸馏采样 (SDS) 优化的 3D高斯泼溅 (3D Gaussian Splatting)

在这个设置中:

  • 基元: 实体树的“叶子”表示为3D高斯 (椭球体) 簇。
  • 优化: 系统优化这些高斯的参数,以便在渲染时,它们与关联的CLIP嵌入 \(z\) 相匹配。
  • 数学: 渲染操作 \(\mathcal{R}\) 遵循标准的高斯泼溅公式:

3D高斯函数的方程。

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

显示如何计算变换后高斯的方程。

这意味着神经网络不需要“学习”旋转物体。程序在数学上处理旋转,而神经网络专注于纹理和形状。

优化过程最小化一个损失函数 (\(\mathcal{L}\)) ,该函数结合了SDS损失 (确保图像看起来像文本描述) 和几何正则化:

总损失函数的方程,结合了用于全局和局部一致性的SDS损失与正则化项。

结果呢?生成了清晰、3D一致的场景,其中结构由代码强制执行,而外观由现代扩散模型生成。

推理: “免训练”生成

这可能是论文中最现代的转折点: 首先你是如何得到场景语言代码的? 你不需要训练一个庞大的新网络来输出代码。你只需要询问大型语言模型 (LLM) 。

作者提出了一个 免训练推理模块 。 他们向预训练的LLM (如GPT-4或Claude) 提供DSL规范和一些示例。然后,给定一个文本提示 (例如,“为比赛设置好的棋盘”) ,LLM编写定义结构的Python脚本。

  • 对于文本输入: LLM构想出程序结构并建议用于嵌入的单词。
  • 对于图像输入: 系统使用视觉语言模型来分割图像,识别物体,然后 (通过文本反转) 优化嵌入以匹配输入图像的视觉风格。

这利用了LLM的“常识”推理能力。LLM知道“桌子”通常有四条腿和一个平坦的顶部,所以它会编写一个带有 union-loop 的程序来生成腿。

实验与结果

研究人员在多个任务中评估了场景语言: 文本提示生成、图像提示生成和场景编辑。

1. 文本提示生成

主要的对比对象是 MVDream (一种没有结构表示的直接文本到3D方法) 和 GraphDreamer (使用场景图) 。

图4. 文本提示场景生成。对比显示场景语言产生比基线更准确的计数和结构。

看图4。提示语“15个可乐罐堆成金字塔”是对计数和结构的压力测试。

  • MVDream 创建了杂乱的一堆。它理解“罐子”,但不理解金字塔的精确几何形状。
  • GraphDreamer 建立了一个结构,但在确切数量或排列上经常失败,因为场景图太抽象了。
  • Ours (场景语言) : 生成了一个精确的数学金字塔。因为LLM写了一个循环来堆叠它们,结构是完美的。

定量结果 (表3,通过视觉结果隐式引用) 表明,场景语言在计数准确性和与用户提示的对齐方面显著优于基线。

2. 跨渲染器的一致性

最酷的功能之一是能够切换渲染器。同一个 程序可以渲染为高保真的高斯泼溅、块状的Minecraft建筑或矢量风格的Mitsuba渲染。

图5. 跨图形渲染器的渲染。相同的底层表示以不同的风格渲染 (高斯 vs. Minecraft/Mitsuba) 。

图5展示了这种多功能性。无论是网球场还是阶梯教室,结构完整性在不同的视觉领域中保持一致。

3. 场景编辑

这就是“语言”部分发光的地方。因为场景被表示为代码,编辑是直观的。

  • 指令: “将分支结构改为三叉。”
  • 动作: LLM将代码中的 loop 计数从2修改为3。

图7. 使用语言指令进行场景编辑。展示了如修改楼梯半径或Jenga塔层数等编辑。

在图7 (顶部) 中,用户要求“将楼梯半径缩小80%”。在基于像素的生成模型中,这可能会扭曲楼梯或破坏纹理。在场景语言中,这只是脚本中的参数更改。楼梯缩小了,但纹理和光照 (嵌入) 保持完美一致。

他们还演示了 基于图像的编辑 (风格迁移) 。通过用从用户照片中提取的新嵌入替换特定物体的嵌入 \(z\),他们可以仅更改“摩艾石像”的风格,而保持平台不变。

图8. 使用图像指令进行场景编辑。替换嵌入允许在保留几何结构的同时进行有针对性的风格迁移。

4. 4D生成 (动画)

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

图6. 文本提示4D场景生成。轨迹跟踪显示动态场景中的连贯运动。

图6显示了一个移动的旋转木马和风力涡轮机。因为运动是以编程方式定义的 (例如,rotation_matrix(time * speed)) ,所以运动是平滑且物理上合理的,不像视频生成模型中经常看到的“抖动”运动。

结论与启示

“场景语言”论文为计算机视觉中的 神经符号AI (neuro-symbolic AI) 提供了一个令人信服的案例。它表明我们不应该在所有事情上都仅仅依赖神经网络这个“黑盒子”。

通过解耦 结构 (由程序/LLM处理) 、语义 (由单词处理) 和 外观 (由嵌入处理) ,我们获得了所有世界的最佳结合:

  1. 精度: 代码保证了直线、确切的计数和完美的对称性。
  2. 保真度: 神经嵌入提供了手工编码资产所缺乏的照片级逼真纹理。
  3. 可控性: 用户可以通过更改文本、代码或参考图像来编辑场景。

这项工作为“逆向图形学 (Inverse Graphics) ”管线铺平了道路,我们可以将现实世界解构为可编辑的代码,本质上将现实变成一个可编程引擎。对于学生和研究人员来说,它凸显了一个令人兴奋的方向: 不再仅仅将生成视为像素预测,而是将其视为程序合成。