将艺术风格迁移到3D Gaussian Splatting(3DGS)场景中,本质是在保持显式几何结构不变的前提下,对场景的颜色外观进行风格化重映射。3DGS用大量三维高斯函数表示场景,每个高斯包含位置、协方差、球谐系数和不透明度等参数,其中颜色由球谐系数编码。风格迁移需要调整这些颜色相关参数,同时避免破坏高斯的位置和形状,否则渲染结果会出现几何崩塌或多视角不一致。

一、3DGS风格迁移的核心难点
3DGS的每个高斯携带球谐系数来表示视角相关的颜色,这意味着从不同角度观察同一个高斯时,其颜色会发生符合物理规律的轻微变化。二维图像风格迁移通常只修改一张固定视角的像素值,而3DGS风格迁移需要修改球谐系数或引入视角无关的风格特征。如果直接把渲染图像的RGB颜色替换为风格化结果,再反投影到高斯颜色上,很可能破坏球谐系数的连续性,导致视角转动时颜色跳变。
多视角一致性是另一个关键约束。逐帧对3DGS渲染结果应用风格迁移算法,看似简单,但每帧独立处理会引入噪声和风格漂移,最终视频序列出现明显的闪烁。要获得稳定结果,必须在场景参数层面进行优化,让所有视角共享同一组风格化后的高斯颜色属性。这要求风格损失函数能够聚合多个视角的渲染结果,而不是只优化单张图像。
几何保持同样不可忽视。3DGS的可微栅格化过程中,颜色参数和几何参数存在一定耦合。如果优化颜色时反向传播的梯度不小心影响了协方差或位置,高斯点可能发生漂移、膨胀甚至消失。因此风格迁移实践中通常会冻结位置、协方差和不透明度参数,只更新球谐系数或额外附加的颜色偏移量,从而把风格化限制在外观层面。
二、基于特征统计的优化方法
最早将二维风格迁移引入三维场景的做法,是利用预训练卷积神经网络提取内容特征与风格特征。内容损失选择VGG19的中间层特征,计算风格化图像与原始内容图像之间的特征差异;风格损失则通过Gram矩阵刻画特征通道之间的相关性,衡量纹理和色彩分布的相似程度。把这两个损失组合后,可以对3DGS渲染出的图像进行反向传播,并将梯度累积到高斯颜色参数上。
具体实现时,可以先从风格图像中提取VGG各层的特征统计量,然后对每个训练视角渲染出的图像计算内容损失和风格损失。内容损失保持场景结构不丢失,风格损失推动颜色分布向目标风格靠拢。通常风格损失的权重需要高于内容损失,因为三维场景的结构信息相对稳定,而风格化需要更强的颜色变化。优化过程中可以加入总变差正则项,抑制渲染图像中的高频噪声。
这类方法的优点是原理直观、实现门槛低,只需要在原有3DGS训练框架中加入风格损失即可。缺点也很明显:VGG特征统计无法描述复杂的语义风格,比如把场景变成宫崎骏动画或赛博朋克夜景时,仅靠Gram矩阵往往只能得到颜色纹理的简单迁移,难以改变物体材质和光照氛围。此外,每次优化都需要大量迭代,训练时间明显增加。
下面是一段计算风格损失的PyTorch示例代码,展示了如何从VGG19中提取特征并构造Gram矩阵。
import torch
import torch.nn as nn
import torchvision.models as models
class StyleLoss(nn.Module):
def __init__(self):
super().__init__()
vgg = models.vgg19(weights=models.VGG19_Weights.IMAGENET1K_V1).features
self.slice1 = vgg[:4]
self.slice2 = vgg[4:9]
self.slice3 = vgg[9:18]
self.slice4 = vgg[18:27]
for param in self.parameters():
param.requires_grad = False
def gram_matrix(self, x):
b, c, h, w = x.size()
features = x.view(b, c, h * w)
gram = torch.bmm(features, features.transpose(1, 2))
return gram / (c * h * w)
def extract_features(self, x):
results = []
x = self.slice1(x)
results.append(x)
x = self.slice2(x)
results.append(x)
x = self.slice3(x)
results.append(x)
x = self.slice4(x)
results.append(x)
return results
def forward(self, rendered, style_img):
content_feats = self.extract_features(rendered)
style_feats = self.extract_features(style_img)
style_loss = 0.0
for cf, sf in zip(content_feats, style_feats):
gram_c = self.gram_matrix(cf)
gram_s = self.gram_matrix(sf)
style_loss += torch.nn.functional.mse_loss(gram_c, gram_s)
return style_loss
在3DGS优化循环中,可以只对颜色相关参数开启梯度,位置和协方差保持冻结。代码结构大致如下:
# 假设 scene 是3DGS场景,renderer 为可微栅格化器
style_weight = 0.8
content_weight = 0.2
for epoch in range(500):
for viewpoint in scene.get_viewpoints():
rendered = renderer(viewpoint, scene.gaussians)
content_loss = compute_content_loss(rendered, viewpoint.reference_image)
style_loss = style_loss_fn(rendered, style_image)
total_loss = content_weight * content_loss + style_weight * style_loss
total_loss.backward()
# 只更新球谐系数,冻结几何参数
optimizer.step()
optimizer.zero_grad()
三、生成式风格化与CLIP引导
针对特征统计方法表现力不足的问题,生成式模型为3DGS风格迁移提供了更丰富的语义控制能力。一种做法是利用扩散模型或ControlNet对3DGS的多视角渲染图进行风格化,再把风格化后的图像作为监督信号,重新优化高斯颜色参数。由于扩散模型能够根据文本提示生成具有明确艺术风格的图像,这种方案可以把任意文字描述转化为场景外观约束。
CLIP引导是另一种轻量级文本驱动方案。将渲染图像和文本提示分别输入CLIP的图像编码器和文本编码器,计算两者嵌入向量的余弦相似度,并将其作为风格损失的一部分。例如输入提示词“梵高油画风格”或“赛博朋克霓虹夜景”,优化过程会推动高斯颜色向这些语义方向变化。相比扩散模型,CLIP损失计算更快,可以在每次迭代中直接使用,不需要生成中间图像。
生成式风格化的优势在于可以产生更大幅度的外观变化,甚至改变光照和材质属性。但它也面临多视角一致性的挑战。如果对每个视角独立使用扩散模型风格化,得到的图像之间可能存在内容漂移,导致优化后的3DGS场景在不同视角下风格不一致。一种缓解办法是先生成少量关键视角的风格化图像,再用这些关键帧训练一个一致性更强的生成模型,或者引入视角条件让扩散模型感知相机姿态。
四、风格迁移后的质量评估与调优建议
评估3DGS风格迁移结果不能只看单张渲染图,必须从多个视角检查颜色稳定性和几何完整性。可以固定一条相机轨迹,渲染连续帧并计算相邻帧之间的光流或像素差异,如果差异曲线出现剧烈波动,说明多视角一致性不足。同时也要观察高斯点云是否出现异常漂移,这通常意味着反向传播时几何参数没有被完全冻结。
调优时可以先降低风格权重,让内容损失占主导,然后逐步提高风格权重直到视觉效果满意。对于颜色变化较大的风格,建议使用分层优化策略:先在小分辨率渲染图上调整全局颜色分布,再逐步提高渲染分辨率细化纹理。这样可以避免高分辨率图像上的风格损失梯度过于稀疏,导致优化不稳定。
如果希望风格迁移实时化,可以考虑训练一个轻量级颜色预测网络,把每个高斯的位置和视角作为输入,直接输出风格化后的球谐系数。这种网络可以作为3DGS的附加模块,在推理阶段快速生成不同风格的场景外观,而无需每次重新优化。训练数据可以来自离线优化得到的高质量风格化高斯颜色参数,使实时切换风格成为可能。