资讯动态

3D高斯泼溅场景编辑实战:删除、移动与语义修改原理与坑位

发布时间:2026/10/21 11:55:00 来源:尧图企业网站定制
上个月处理了一个挺有代表性的项目一个展厅场景已经重建成了3D高斯泼溅3D Gaussian Splatting简称3D GS模型客户临时要求撤掉展厅中间一个展台还要给部分墙面换个颜色。按传统流程这几乎等于重新做一遍场景重建——回到现场拍摄、重跑位姿解算、再训一轮可现场早就拆掉了。最后是靠3D GS编辑救回来的在重建好的高斯场景里选中展台对应的一堆高斯点直接删除再对墙面点位做颜色方向操作前后只花了两天。这篇文章想把这类编辑技术从原理到落地讲透包括高斯点结构、常见的删除/移动/语义编辑思路、训练约束细节以及我实际踩过的一些坑。适合做三维重建的算法工程师、CG流程开发以及想把GS模型真正用到数字化交付项目里的朋友。1. 为什么重建好的场景改不动才是真正的项目瓶颈1.1 一个“改一个物体就要重做整个场景”的典型困境只看演示视频的话3D GS重建已经足够惊艳拿几十张照片进去几十分钟出来一个可以自由转视角的真实场景。可真到项目交付层面情况会变得很不友好。我遇到的真实需求通常是这几类场景布局变了要挪家具现场出现临时车辆、杂物、行人要清掉品牌方想统一改掉某个展台的表面颜色或者干脆要把一批原本不存在的物件合成进去。这时候场景表示方式就决定了改造成本。拿传统mesh来说你还能靠选面、刷权重、补洞去凑合工作量虽然烦但至少能下手。而GS这类显式辐射场重建结果几乎所有像素都是成百上千个高斯点共同贡献的结果直接在三维层面删掉一块渲染时周围马上渗出空白和伪影。行业内最常见的应对办法就是“回去重拍”。但这意味着重新采集照片、重新解算相机位姿、重新训练模型一套流程走下来少则半天多则两天。如果场景本身是临时搭建的、外地快闪布置或者拍摄许可只有一次重拍成本的代价很可能比需求本身还高。我做过的另一个项目更是典型当时是一批历史建筑外观的扫描数据采集窗口只有两天后期甲方要求把其中一栋建筑旁边的临时脚手架去掉。数据已经封存现场已经清场根本不可能回拍。这个时候能在已有GS模型上做局部编辑就从一个“加分项”变成了“救命项”。所以我说重建速度只是3D GS的上半场下半场拼的是编辑能力。1.2 局部修改为什么在辐射场里特别难要理解这个“难”得先分清楚几种三维表示方式的差异。NeRF这类隐式场本质是一个MLP网络输入空间坐标和时间输出颜色和密度。你想删掉一辆车原则上只能靠额外训一个空间掩码或者把场景拆成前后两个场。单物体NeRF这样做没问题场景一复杂前景背景互相遮挡空间掩码立刻不稳定经常把不该删的墙也删掉一块。GS不一样。它的场景是一堆显式分布、带属性的高斯点。删除某个物体数据结构上就是移除一批点换颜色就是改一批点的球谐系数。听起来比隐式场简单很多但这里有一个迷惑性渲染是全局的点之间有大量重叠和覆盖删完之后暴露出来的空缺需要重新“补”出来这个补的过程依然要跑优化。只是说GS在“可局部定位”这件事上比隐式场扎实太多了。我整理过一个对比方便理解各种表示方式在编辑场景下的差异表示方式局部修改难度修改后是否需要重新训练典型交付方向传统mesh中等受限于拓扑和UV通常不用但补洞很烦CAD、工业模型NeRF隐式场难空间掩码不稳定几乎总需要光场展示3D GS相对容易直接操作离散点需要小规模微调实景复刻、数字化交付我在项目里一旦遇到“以后大概率会改”的场景现在会优先考虑GS管线不是因为它重建得最好而是因为它给后期留了操作空间。这个思维转变比单纯调参重要得多。2. 高斯点是一批可以单独下手的小代理2.1 一个高斯点在内存里到底存了什么想做好GS编辑不能只把高斯点当成“一堆粒子”。每个点在数据结构上是一个携带属性的三维高斯分布核心字段包括中心位置向量决定这个点在空间中的坐标协方差矩阵决定它在三个方向上的尺寸和姿态颜色系数通常用球谐函数表示通俗讲就是不同视角下颜色如何变化不透明度控制这个点对最终像素的贡献权重。训练完成后我们拿到手的就是这样一张大表几万到几百万行每行是一个点的全部属性。渲染时系统按当前视角把所有高斯点投影到屏幕平面变成交叠的椭圆按深度排序再从远到近做alpha合成。整个过程是可微的这也是编辑的基础——你可以渲染出图像计算与目标图的差异然后把梯度回传去修改点属性。我建议工程人员拿到GS模型后第一步不是急着看效果而是把属性表导出成结构化格式比如二进制点云加一份json记录每个字段的含义。这样后续编辑就不需要依赖原始训练仓库可以用脚本独立读写。这个习惯帮我避过很多次“改完发现原始仓库已经删了”的尴尬。2.2 可微渲染等于给了编辑器一把手术刀传统三维编辑器里你移动一个mesh顶点顶点的位置变了面的形状跟着变。GS编辑器里你移动一个高斯点的位置它对所有视角的贡献都会随之变化但具体会变成什么样需要跑一次可微渲染算出来。这里有一个很重要的设计思想编辑本质上是一种带约束的训练。自由变量是选中高斯点的属性固定变量是其余所有点的属性损失函数是渲染图像与目标编辑结果的差异再加上若干正则项。整个优化流程和最初训练GS模型高度相似但关键在于约束范围。很多教程只讲怎么渲染和怎么反传梯度不讲约束结果就是改了目标区域背景跟着一起糊。我后面会专门展开这个问题。2.3 为什么改着改着没选中的背景反而被弄坏了这是新手做GS编辑最容易踩的第一个大坑。最初我在一个街景项目里尝试删除路灯只把路灯位置附近的高斯点选了出来然后直接跑微调。渲染出来发现路灯确实淡了但整片天空变成脏兮兮的灰色旁边建筑物的纹理也花了。原因很简单渲染损失是所有点共同承担的梯度回传时未选中的点也会收到更新信号。它们在优化器眼里同样是参数同样会让损失变小。如果放开全局更新模型自然倾向于“让所有点都挪一挪、改一改”来适配新的渲染目标。解决思路不是调低学习率而是明确告诉优化器一部分点不许动。也就是把优化器的参数列表只放进选中点的属性或者干脆在反传之前手动把冻结点的梯度清零。做GS编辑和做重建在工程习惯上最大的分水岭就是你能不能把这个“冻结集合”管得足够干净。3. 从零到可用的三步重建、选中、微调3.1 第一步拿到一份“能编辑”的GS场景GS编辑的前提是先有GS模型但采集质量直接决定后续编辑好不好做。我反复对团队讲过一句话重建得快的项目不一定能编辑采集得干净的项目一定容易编辑。具体到操作层面有几个要点值得注意。多视角覆盖要足够特别是被编辑物体周边如果某个角度完全没拍到那它在渲染里就是靠插值猜出来的编辑时很容易穿帮。采集时尽量固定曝光和白平衡画面忽明忽暗会让点属性学习到错误的信息。训练时不要一股脑把视频全部抽帧丢进去按场景复杂程度抽帧复杂区域密一点平坦区域疏一点否则场景点密度分布太不均匀等于给编辑埋雷。还有初始化。GS训练普遍依赖一个稀疏三维点云作为初始结构业界通常用通用运动恢复结构工具先算出相机位姿并生成稀疏点。这一步的质量会一路传导到最终的高斯点分布上。我见过不少编辑后出现大片黑色孔洞的案例追根溯源是初始化点就缺了一块而不是编辑操作本身的问题。3.2 第二步目标物体怎么从“画一笔”变成“一堆点”这是GS编辑流程里最繁琐、也最影响成败的环节。你要把用户在图像上画的一笔或者一句“把中间那个展台删掉”翻译成具体的高斯点索引集合。目前比较稳的做法是走多视角联合投票。先在若干关键视角上把目标物体用分割模型抽成2D掩码然后把每个视角的掩码反投影到3D空间落在哪些高斯点附近就代表这个点被该视角“看到”并被选中。统计所有参与视角的结果让每个高斯点获得一个被选次数然后设定一个阈值比如超过百分之八十的视角都认为属于目标才把它加入选中集合。这个流程对遮挡频繁的场景尤其重要因为某个视角看不到的物体区域可能只是被挡住了并不代表那里不该被编辑。另一种思路是直接在三维层面做语义分类。先跑一遍二维分割模型得到全帧逐像素标签再把标签传播到高斯点上做一个概率投票最后得到每个点属于哪个语义类别。这种方式好处是一次性可以把“行人”“车辆”“墙面”都标出来坏处是需要额外跑大量帧的分割计算时间明显变长。我一般根据场景体量选择点少用直接投影法点多用语义传播法。3.3 第三步执行编辑操作并且只放开局部训练选中集合确定后编辑操作本身并不复杂复杂的是之后的微调策略。我的标准流程是这样的先把当前所有点属性备份一份然后把优化器参数限制到选中点集合再对选中点执行删除、移动或者颜色修改最后开始小规模微调。微调阶段有几个参数可以给参考迭代步数一般控制在三百到八百步远小于重建时的几万步学习率取重建时的十分之一到百分之一常见值是一乘十的负四次方级别损失函数可以同时用L1颜色误差和SSIM结构误差再叠加不透明度正则和尺度正则。尺度正则尤其重要它防止某些点在补洞过程中膨胀成巨大的“模糊团块”那几乎是所有GS编辑翻车的共同画面。下面是我经常用的一段最小代码骨架以PyTorch风格的伪代码为例# 假设 gs 对象保存了所有点的属性 # selected_ids 是编辑目标的高斯点索引列表 optimized_params [] # 第一步默认冻结全部 for name in [xyz, opacity, scales, quats, shs]: tensor getattr(gs, name) tensor.requires_grad_(False) # 第二步只放开选中的点 for i in selected_ids: for name in [xyz, opacity, scales, quats, shs]: getattr(gs, name)[i].requires_grad_(True) optimized_params.append(getattr(gs, name)[i]) optimizer torch.optim.Adam(optimized_params, lr1e-4) for step in range(500): rendered render(gs, viewpoint) loss l1(rendered, target_image) ssim(rendered, target_image) loss 0.001 * gs.opacity[selected_ids].mean() loss 0.001 * (gs.scales[selected_ids] ** 2).sum() optimizer.zero_grad() loss.backward() optimizer.step()这段代码最关键的地方就是前面两段循环先全冻结再按需解冻。很多二次开发的朋友拿现成训练代码改忘了冻结跑的其实依然是常规重建优化那编辑结果当然不可控。4. 删除、移动、语义替换三类典型编辑操作的实现逻辑4.1 删除物体真正的难点不是删而是补洞删掉一批高斯点渲染时会露出什么露出原本被物体遮挡的背景。可背景区域在原始图像里根本没显示全模型没有学过那里应该是什么。这是删除类编辑的核心矛盾。目前我常用的处理方式是两阶段。第一阶段不要把点直接删除而是先把选中点的透明度逐步降低到零同时渲染当前视角把生成图里目标区域挖出来用周围的背景信息做一个inpainting生成一个“目标参考图”。第二阶段保留一小部分低透明度点作为“种子”微调时让它们适当增加尺寸和不透明度向参考图方向补齐漏洞。这样比完全清空后再让模型无中生有要稳定得多。这个方案有个好处删除是渐变的不会出现渲染帧与帧之间突然跳变。视频交付项目最怕删除后一动视角某个角度突然蹦出一片黑斑渐变处理能显著降低这种概率。如果你直接把选中的点彻底删掉再跑优化等于逼模型从零猜测一个大缺口优化难度和伪影概率都会高很多。4.2 移动物体变换矩阵加重投影监督移动物体听起来最直观——把选中点的新位置算出来赋回去微调一下结束。实际做的时候会发现两个麻烦物体一旦移动原先遮挡的背景就暴露了物体会在新位置遮挡住原本能看到的东西。这两类变化都缺少真实的参考像素直接算距离损失会把结果带偏。我的做法是拆成两步。先把物体从原始位置“摘下”用类似4.1的补洞流程把旧位置背景修好然后把物体点集应用旋转矩阵和平移向量移动到新位置再渲染新视角让新位置的遮挡关系自然形成。最后微调时给选中物体点集加一个局部刚性正则也就是要求每对相邻点在变换后仍保持相对距离避免物体像液体一样摊开或者缩成一小团。这个正则项的权重需要现场试太大会导致物体无法适应新场景光照太小则直接变形。还有一个很多人忽略的细节旋转物体时协方差矩阵里的旋转部分也要同步更新否则渲染出来的椭圆还是原来的朝向物体看起来像是被“拉伸”过。换个说法高斯点不仅有位置和颜色它本身是一个有姿态的椭圆体移动时必须把位置、姿态、尺寸三者作为一个整体变换。4.3 语义改写颜色方向与特征驱动的局部更新墙面改色、路面材质替换、甚至把某个物体的风格改成“复古风”都属于语义编辑。这个方向现在很多论文在探索但落到工程上最稳定可控的其实是颜色与特征方向编辑。举一个我实际做过的例子展厅里有一面米黄色背景墙客户要求改成偏冷灰蓝。做法是先选中墙面对应的高斯点冻结几何属性只放行球谐颜色系数然后渲染几张固定视角的图片计算当前颜色与目标颜色之间的距离最后用梯度更新选中点颜色。整个过程中不透明度、位置、尺度一概不动效果就非常干净。如果要表达的是“变成一种风格”而不仅仅是单一颜色需要引入外部特征模型比如用对比语言-图像预训练模型把渲染图和目标文本编码到同一个特征空间再算特征余弦距离作为损失。这个方案效果上限高但训练稳定性差经常出现颜色失控或者纹理乱飞。我的建议是对外交付或者走量项目优先用颜色迁移和直方图匹配稳定且可解释只有做探索性Demo再用特征方向推理。冻结未选点这条铁律在语义编辑里尤其明显因为颜色梯度非常容易顺着边缘渗出你不冻结几轮迭代后整面墙都会变色。操作类型核心动作微调时需要关注的位置最常见伪影删除透明化/删点旧位置的边界空洞、半透明雾移动位置与姿态变换新旧位置背景拉伸、破洞语义改写颜色/特征更新目标区域内部颜色渗出、纹理漂移5. 实操里常见的七个问题以及我是怎么排查的5.1 选了物体但3D点怎么也选不干净这是最挫败的情况分割图看着很准投影到高斯点上却总有零星的漏选或者误选。根因大多是多视角掩码不一致物体在某个视角自遮挡严重分割结果断断续续。排查办法是不要只用两三个视角至少拉六个以上均匀分布的视角做联合投票同时把阈值调高一点宁可少选不可多选。多选的补救是靠后续微调慢慢修正但误选进背景区域的话冻结集合会被污染背景也跟着动。5.2 编辑完边缘糊成一团打开渲染视频看到目标物体边缘像是融化了一样。这个大概率是微调步数太长或者学习率太大。GS重建的训练目标是整个场景收敛而编辑只需要局部小幅调整过大的学习率会把边界点推离原来的位置。遇到这种情况我会先看未选点有没有被解冻确认冻结没问题后就把学习率下调到原来的四分之一再降迭代步数。5.3 删完物体后留下雾状半透明影子渲染时物体不见了但那个区域有一层淡淡的颜色雾镜头转起来尤其明显。这是典型的透明度残留在作怪删除过程中选点的不透明度没有真正归零或者优化器又在后续步骤里把这些点的透明度拉了回来。排查思路很简单导出编辑结果里那条区域的透明度数值看看有没有大量中间值。有的话强制给未满零的点加一次截断。5.4 背景亮度被目标区域带偏编辑展台或者删除车辆之后整张图的光线氛围不对了。这种现象在删除类编辑里很常见因为补背景时参考的是周围像素而周围像素本身是被原物体照亮的区域补出来的结果自然带着原物体环境光。需要做的不是继续调补洞策略而是回到目标参考图生成阶段把参考图的光照做一次全局校正或者引入环境光估计否则微调阶段再怎么调都只是在修错误的光照前提。5.5 移动物体出现巨大的黑色空洞移动后新位置背景露出来了但渲染出来是一大片黑这通常不是微调不够而是补洞阶段根本没给那个区域提供有效的监督信号。黑色最直接的原因数值上代表不透明度缺失和辐射度归零。解决办法是先把新位置周围的点做一次密度补全比如用深度图先填补出一个粗糙几何再交给GS微调去细化。不要指望纯梯度优化能无中生有地生成一个结实的墙面。5.6 多个物体一起编辑时互相干扰有些项目要求同时删掉三个临时障碍物再改一个展台颜色。如果把它们合并成一个选中集合一次优化往往会互相争夺梯度导致每个区域都改得不够彻底。更稳的做法是分批编辑先删障碍物一补洞完成再删障碍物二全部几何操作结束后最后做颜色编辑。每批之间保留编辑记录出问题时可以回滚到前一步。5.7 坐标尺度和真实世界对不上移动距离完全算错GS重建出来的场景通常没有物理尺标不同模型之间的尺度可能差好几倍。如果想把A场景里一个物体搬进B场景直接复制坐标会得到匪夷所思的结果。这个问题在处理跨场景复用时特别容易翻车。我会在采集前放一个已知尺寸的标定物或者采集后用实际距离测量做一次全局缩放。没有标定信息时只能靠匹配场景里某个已知物体的尺寸来估。6. 把这套编辑能力工程化的最后一公里6.1 数据资产应该按“操作记录”管理而不是只存结果GS编辑最容易陷入的混乱是直接在点集文件上改来改去改完只存一个结果等发现某个操作错了没有中间版本可以退回。我的建议是每个GS场景以“原始点集编辑记录链”的方式管理。原始点集只读编辑记录链是一个JSON序列记录每一次选中的掩码文件路径、操作类型、变换矩阵、微调参数和迭代步数。每次交付时再按记录链重新计算最终点集。这个习惯让团队协作变得简单。视觉同事负责画掩码算法同事负责调参数谁都不用等谁因为每个操作都是独立可回放的。遇到甲方的反复修改我也只需要改JSON里对应的一条记录而不是重跑一遍整个优化。6.2 局部渲染是提高编辑效率的关键GPU资源不是瓶颈的时候很多人都倾向于每次微调把所有视角都渲染一遍然后算全局损失。但在GS编辑场景下这其实是在浪费算力并且可能让远离编辑区域的点也接收到微小梯度。我的做法是先根据选中点的三维包围盒筛选出能够“看到”这个包围盒的相机视角微调时只用这些视角。这样既能减少计算量又能避免无关区域被扰动。实测一套几十万点、百余视角的场景局部视角训练相比全局训练能快三到五倍效果也更干净。6.3 跨场景复制物体时光照和尺度的处理顺序不能反GS编辑能做的事不局限于修改现有场景也可以从另一个场景“剪”一个物体过来。这个需求在数字化展厅、游戏资产生成里越来越常见。实际操作时我会按照尺度对齐、光照适配、边缘融合的顺序来处理。先用标定物统一尺度然后对物体点集做整体亮度-色温匹配最后在边缘做一层透明度渐变。反过来的话会先遇到边缘接缝再发现整体色调不对又要回头重做效率低很多。6.4 交付前检查清单最后分享一份我自己每次交付前都要过的检查清单。先转一圈渲染视频重点看编辑区域的边缘轮廓是否稳定再检查透明度图确认没有大面积残余雾然后对比编辑前后的画像素差异排除意外改动最后检查点集总量和文件体积删除掉那些不透明度极低且影响微小的高斯点减小交付包。这个流程看起来麻烦但能避免大量售后反馈。这些年做三维重建项目我的体感是重建算法本身的差距正在快速缩小新的开源方案一个接一个出现真正拉开交付差距的反而是你拿到一个场景之后能不能低成本地改它。GS编辑目前还有很多粗糙的地方比如分割选点要手动盯、补洞结果需要反复抽检、语义编辑不稳定等等。但方向上它让三维场景从“一次性重建品”变成了“可修图的三维素材”这个变化对实际项目的影响是很大的。如果你正准备入这个方向我的建议很直接先拿一个小场景跑通这个流程不要急着接大场景。把选点、冻结、微调这三个基本功练稳再谈复杂的多物体编辑。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑