光照解耦和重照明

项目地址:

GitHub - NJU-3DV/Relightable3DGaussian: [ECCV2024] 可重新照明的 3D 高斯:使用 BRDF 分解和光线追踪的实时点云重新照明

可优化参数

gaussians.training_setup(opt)

if is_pbr:: direct_env_light.training_setup(opt)

光照解耦

update_visibility

分块处理高斯

对每个高斯体,采样 sample_num 个入射方向,计算每个方向的可见性(是否被遮挡)、方向向量、该方向在球面上的面积权重,并将这些结果保存下来

 fibonacci_sphere_sampling斐波那契球面采样

输出

  1. incident_dirs:每个点/法线的 sample_num 个采样方向(单位向量),用于模拟不同角度的入射光。
  2.  normals 是 [N, 3],则输出 incident_dirs 是 [N, sample_num, 3]
  3. incident_areas:每个采样方向的面积权重(都相同),用于积分时加权。
  4. incident_dirs形状[N, sample_num, 1]

在 fibonacci_sphere_sampling 代码中,采样方向是围绕每个高斯体的法线方向生成的:

  • 首先在 z 轴方向上生成均匀分布的球面采样(fibonacci sphere)。
  • 然后通过旋转,把这些方向对齐到每个高斯体的法线方向(rotation_between_z(normals))。
  • 如果 random_rotate=True,还会加上一个随机旋转,使得每个高斯体的采样方向分布更加均匀、随机。

rotation_matrix = rotation_between_z(normals)

incident_dirs = rotation_matrix @ z_samples

  • 这里 rotation_matrix 是针对每个高斯体的法线单独计算的。
  • 所以 incident_dirs 是每个高斯体独立的一组方向。

render(is_training=true)

render_pkg = render_fn(viewpoint_cam, gaussians, pipe, background,opt=opt, is_training=True, dict_params=pbr_kwargs, iteration=iteration)pbr_kwargs['sample_num'] = pipe.sample_num#64pbr_kwargs["env_light"] = direct_env_light

高斯增加优化属性

  1. _base_color:表面基础色(反射率/漫反射色),PBR渲染的核心属性。
  2. _roughness:表面粗糙度,影响高光和反射的模糊程度。
  3. _incidents_dc/incidents_rest:每个高斯体的入射光照分布(用球谐函数表示),用于高效地近似全局光照。
  4. _visibility_dc/visibility_rest:每个高斯体的可见性分布(同样用球谐函数表示),用于阴影和遮挡的近似。
 first_iter = gaussians.create_from_ckpt(args.checkpoint, restore_optimizer=True)

 初始化这些属性为0

环境光照(IBL - Image-Based Lighting)​

  • 模拟全局光照​:环境贴图存储了来自各个方向的环境光强度与颜色,为物体表面提供非直接光照(如漫反射、镜面反射)。
  • PBR 材质依赖​:在基于物理的渲染中,环境贴图是计算材质反射、折射的基础输入(如金属高光、玻璃透射)

PBR最终像素颜色和渲染方程Rendering equation

 参考彻底看懂PBR/BRDF方程 - 张亚坤的文章 - 知乎
https://zhuanlan.zhihu.com/p/158025828

 base_color:点云的“固有色”。

 pbr:这个点在当前光照、视角、材质等条件下,真实应该呈现出来的颜色。

pbr​:最终像素颜色(Lambert 漫反射 + GGX 镜面反射)

输出结果brdf_color和extra_results

    extra_results = {"incident_dirs": incident_dirs,"incident_lights": incident_lights,"local_incident_lights": local_incident_lights,"global_incident_lights": global_incident_lights,"incident_visibility": incident_visibility,"diffuse_light": diffuse_light,"specular": specular,}

基于物理的渲染方程(PBR)​​:

其中:

    f_d = base_color[:, None] / np.pi

    f_s = GGX_specular(normals, viewdirs, incident_dirs, roughness, fresnel=0.04)

  • Lo​:出射光(最终颜色)
  • fdiffuse​:漫反射 BRDF
  • fspecular​:镜面反射 BRDF
  • Li​:入射光强度
  • n⋅ωi​:​余弦项​(法线与入射光方向的点积)

diffuse_light = transport.mean(dim=-2):: 表示表面接收到的总光照强度

rasterizer结果

变量名说明典型形状
num_rendered渲染的高斯点总数标量/int
num_contrib每像素有贡献的高斯点数[H, W]
rendered_image渲染出的RGB图像[3, H, W]
rendered_opacity渲染出的不透明度图[1, H, W]
rendered_depth渲染出的深度图[1, H, W]
rendered_feature渲染出的特征图(多通道)[C, H, W]
rendered_pseudo_normal渲染出的伪法线图[3, H, W]
rendered_surface_xyz渲染出的表面3D坐标[3, H, W]
weights高斯点对像素的贡献权重[N, H, W]
radii高斯点在屏幕上的半径[N]

render输出results

feature和rendered_image、rendered_pbr

   if is_training:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness, extra_results["diffuse_light"], extra_results["incident_visibility"].mean(-2)], dim=-1)else:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness,extra_results["diffuse_light"], extra_results["specular"], extra_results["incident_lights"].mean(-2),extra_results["local_incident_lights"].mean(-2),extra_results["global_incident_lights"].mean(-2),extra_results["incident_visibility"].mean(-2)], dim=-1)

 在gaussian_renderer\neilf.py里的render_view

 在gaussian_renderer\r3dg_rasterization.py中

num_rendered, num_contrib, color, opacity, depth, feature, normal, surface_xyz, weights, radii, geomBuffer, binningBuffer, imgBuffer = _C.rasterize_gaussians(*args)

在r3dg-rasterization\ext.cpp中

 在r3dg-rasterization\rasterize_points.cu中

return std::make_tuple(
rendered, n_contrib, out_color, out_opacity, out_depth, out_feature, out_normal, out_surface_xyz, out_weights, radii, geomBuffer, binningBuffer, imgBuffer);

与 下图一一对应

num_rendered, num_contrib, color, opacity, depth, feature, normal, surface_xyz, weights, radii, geomBuffer, binningBuffer, imgBuffer = _C.rasterize_gaussians(*args)

在r3dg-rasterization\cuda_rasterizer\forward.cu中 

rendered_image:是通过球谐函数(Spherical Harmonics, SH)渲染得到的图像,即上图中的out_color

rendered_pbr:是通过物理基础渲染(Physically Based Rendering, PBR)得到的图像,即上图中的out_feature(对应render_feature)中的一部分

pbr = rendered_pbr
rendered_pbr = pbr * rendered_opacity + (1 - rendered_opacity) * bg_color[:, None, None]

out_feature(对应render_feature)由features加权得出,rendered_pbr对应由brdf_color加权

   if is_training:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness, extra_results["diffuse_light"], extra_results["incident_visibility"].mean(-2)], dim=-1)else:features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness,extra_results["diffuse_light"], extra_results["specular"], extra_results["incident_lights"].mean(-2),extra_results["local_incident_lights"].mean(-2),extra_results["global_incident_lights"].mean(-2),extra_results["incident_visibility"].mean(-2)], dim=-1)

重照明relighting.py

 文件路径变量
scene_config_file
路径:{args.config}/transform.json
作用:场景的空间变换配置文件,通常描述每个子场景或物体的变换矩阵(如平移、旋转、缩放)。
traject_config_file
路径:{args.config}/trajectory.json
作用:相机轨迹配置文件,通常描述渲染时相机的运动路径、每一帧的相机参数等。
light_config_file
路径:{args.config}/light_transform.json
作用:光源轨迹或光照变换配置文件,描述光源的位置、方向、变化等(如果有动态光照)。

为什么可以实现

 if iteration % args.save_interval == 0 or iteration == args.iterations:#5000print("\n[ITER {}] Saving Gaussians".format(iteration))scene.save(iteration)

在运行script\run_nerf.sh后 保存高斯各属性在output/NeRF_Syn/hotdog/neilf/point_cloud/iteration_40000/point_cloud.ply类似路径,在configs\nerf_syn_light\transform.json中保存各场景路径和transform矩阵

 在scene_composition中加载ply文件,

relighting.py 的流程:读取高斯体模型(如 .ply 文件);读取环境光照(如 .hdr 文件;读取相机参数;用渲染器(如 render_fn_dict['neilf'])直接渲染图片。

只要有一个已经拟合好的3D场景(高斯体参数),可以随时改变光照条件(比如换环境贴图),然后用渲染器重新渲染出不同光照下的图片。这就是重照明。因为场景的几何和材质参数已经在训练阶段学好了,渲染时只需要前向推理(forward),不需要再优化参数。

 `scene_composition`

功能

scene_composition 的作用是:
将多个场景(或点云)的高斯体模型合成为一个整体高斯体模型,并做必要的初始化。

具体流程如下:

  1. 遍历 scene_dict,为每个子场景加载高斯体点云(.ply 文件),并应用相应的变换(transform),把每个子场景的点云(高斯体)通过指定的 4x4 变换矩阵变换到全局坐标系,。

  2. 把所有加载好的高斯体模型合成为一个大模型(调用 GaussianModel.create_from_gaussians)。

  3. 对合成后的模型做一些初始化(如可见性、入射光参数等)。

  4. 返回合成后的高斯体模型。


输入

  • scene_dict: dict

    • 字典格式,key 是场景名,value 是一个字典,包含:

      • "path":点云文件路径(.ply)

      • "transform":4x4 的变换矩阵(list 或 array)

  • dataset: ModelParams

    • 数据集参数对象,至少包含 sh_degree 等高斯体模型初始化所需参数。


输出

  • gaussians_composite: GaussianModel

    • 合成后的高斯体模型对象,包含所有子场景的点云和参数,已经应用了各自的变换,并做了初始化。


代码流程简述

  1. 加载每个子场景的高斯体模型并变换

    for scene in scene_dict:gaussians = GaussianModel(dataset.sh_degree, render_type="neilf")gaussians.load_ply(scene_dict[scene]["path"])torch_transform = torch.tensor(scene_dict[scene]["transform"], device="cuda").reshape(4, 4)gaussians.set_transform(transform=torch_transform)gaussians_list.append(gaussians)
    
  2. 合成所有高斯体模型

    gaussians_composite = GaussianModel.create_from_gaussians(gaussians_list, dataset)
    
  3. 初始化可见性和入射光参数

    n = gaussians_composite.get_xyz.shape[0]
    gaussians_composite._visibility_rest = (torch.nn.Parameter(torch.cat([gaussians_composite._visibility_rest.data,torch.zeros(n, 5 ** 2 - 4 ** 2, 1, device="cuda", dtype=torch.float32)],dim=1).requires_grad_(True)))
    gaussians_composite._incidents_dc.data[:] = 0
    gaussians_composite._incidents_rest.data[:] = 0
    
  4. 返回合成后的模型

    return gaussians_composite
    

总结

  • 功能:合成多个高斯体点云为一个整体,并初始化相关参数。

  • 输入:场景字典(含路径和变换)、数据集参数。

  • 输出:合成后的高斯体模型对象(GaussianModel)。

render(is_training=false)

render_kwargs = {"pc": gaussians_composite,"pipe": pipe,"bg_color": background,"is_training": False,"dict_params": {"env_light": light,"sample_num": args.sample_num,#384},"bake": args.bake}
with torch.no_grad():render_pkg = render_fn(viewpoint_camera=custom_cam, **render_kwargs)

在 render_view 函数中,is_training 参数为 True 或 False 时,渲染流程和输出内容有明显区别is_training 为 True 时,流程更高效、特征更精简、用于训练和损失计算;为 False 时,流程更全面、特征更丰富、用于推理、评估和可视化。

主要体现在以下几个方面:


1. BRDF 计算方式不同

  • is_training=True
    • 直接对所有点一次性调用 rendering_equation,效率高,适合训练时的批量处理。
    • 代码片段:
      if is_training:brdf_color, extra_results = rendering_equation(base_color, roughness, normal.detach(), viewdirs, incidents,direct_light_env_light, visibility_precompute=pc._visibility_tracing, incident_dirs_precompute=pc._incident_dirs, incident_areas_precompute=pc._incident_areas)
      
  • is_training=False
    • 为了节省显存,采用分块(chunk)处理,每次只处理一部分点,适合测试/推理时大规模渲染。
    • 代码片段:
      else:chunk_size = 100000brdf_color = []extra_results = []for i in range(0, means3D.shape[0], chunk_size):_brdf_color, _extra_results = rendering_equation(...)brdf_color.append(_brdf_color)extra_results.append(_extra_results)brdf_color = torch.cat(brdf_color, dim=0)extra_results = {k: torch.cat([_extra_results[k] for _extra_results in extra_results], dim=0) for k in extra_results[0]}torch.cuda.empty_cache()
      

2. 特征拼接内容不同

  • is_training=True

    • 拼接的特征较少,只包含训练所需的内容。

    • 代码片段:
      features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness, extra_results["diffuse_light"], extra_results["incident_visibility"].mean(-2)], dim=-1)
      
  • is_training=False

    • 拼接的特征更丰富,包含更多渲染细节,便于评估和可视化。

    • 代码片段:
      features = torch.cat([depths, depths2, brdf_color, normal, base_color, roughness,extra_results["diffuse_light"], extra_results["specular"], extra_results["incident_lights"].mean(-2),extra_results["local_incident_lights"].mean(-2),extra_results["global_incident_lights"].mean(-2),extra_results["incident_visibility"].mean(-2)], dim=-1)
      

3. 输出的特征拆分不同

  • is_training=True

    • rendered_feature 只拆分出训练所需的特征(如 base_color、roughness、diffuse、visibility)。

  • is_training=False

    • rendered_feature 拆分出更多特征(如 specular、lights、local_lights、global_lights 等),便于评估和可视化。


4. 环境光相关输出不同

  • is_training=False

    • 还会输出 render_envpbr_envenv_only 等环境光相关的渲染结果,便于评估不同光照下的表现。

  • is_training=True

    • 这些环境光相关的输出不会被计算,节省计算资源。


5. 损失计算

  • is_training=True

    • 会进一步调用 calculate_loss 计算损失和训练日志。

  • is_training=False

    • 不计算损失,只输出渲染结果。


总结表

is_training

主要用途

BRDF计算

特征拼接

输出内容

损失计算

评估/可视化

True

训练

一次性

精简

精简

False

推理/评估

分块

丰富

丰富


render输出results

评估 

  • train.py 的评估是为了训练过程中的监控和调优,通常和训练流程绑定。
  • eval_nvs.py 是专门为独立评测和论文展示设计的,方便单独运行和批量评测。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/912793.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/912793.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka 运维与调优篇:构建高可用生产环境的实战指南

🛠️ Kafka 运维与调优篇:构建高可用生产环境的实战指南 导语:在生产环境中,Kafka集群的稳定运行和高性能表现是业务成功的关键。本篇将深入探讨Kafka运维与调优的核心技术,从监控管理到性能优化,再到故障排…

AR 地产互动沙盘:为地产沙盘带来变革​

在科技飞速发展的今天,AR(增强现实)技术应运而生,为解决传统地产沙盘的困境提供了全新的思路和方法。AR 技术,简单来说,是一种将计算机生成的虚拟信息与真实环境相融合的技术。它通过摄像头、传感器等设备获…

端到端自动驾驶系统关键技术

一、感知决策一体化模型架构 单一神经网络整合全流程 端到端神经网络能够直接将传感器输入映射为控制输出,消除了传统模块化架构中感知、规划、控制等独立模块之间的割裂。传统架构中,感知模块负责识别环境信息,决策模块根据感知结果进行路…

Vue Vue-route (2)

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue-route重定向和声明式导航 目录 Vue-route路由 重定向 首页默认访问 不存在匹配 声明式导航 路由原理 使用示例 自定义class类 Tag设置 版本4路由 改变 示例 总结 Vue-route路由 重定向 首页默认访问 希望访…

Mabl 基于云端的智能化自动化测试平台

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 </

Linux/Dog

Dog Enumeration nmap 第一次扫描发现系统对外开放了22、80端口&#xff0c;端口详细信息如下 ┌──(kali㉿kali)-[~/Desktop/vegetable/HTB] └─$ nmap -sC -sV -p 22,80 -oA nmap 10.10.11.58 Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-26 03:36 EDT Nmap s…

青少年编程与数学 02-022 专业应用软件简介 01 设计与创意类软件:Adobe Creative Cloud

青少年编程与数学 02-022 专业应用软件简介 01 设计与创意类软件&#xff1a;Adobe Creative Cloud **一、Adobe公司介绍**&#xff08;一&#xff09;Adobe的创立与早期发展&#xff08;二&#xff09;Adobe的市场地位与影响力&#xff08;三&#xff09;Adobe的创新文化 **二…

【亚马逊防关联攻略】多店铺运营如何做好环境隔离?

在亚马逊跨境电商中&#xff0c;多店运营的最大风险是账号关联。亚马逊规定&#xff0c;同一卖家在同一站点只能拥有一个店铺。平台会通过多种方式追踪注册信息、设备和网络环境等&#xff0c;如果发现关联因素&#xff0c;所有关联账号可能被批量封禁&#xff0c;这会导致资金…

She‘s Coming !

#好书推荐《一本书讲透汽车功能安全&#xff1a;标准详解与应用实践》 #功能安全应用指南 #功能安全实践参考宝典 Finally, shes coming ! 她来得有点晚&#xff0c;但 “好饭不怕晚”。 她就是刚出炉的新书《一本书讲透汽车功能安全&#xff1a;标准详解与应用实践》 京东…

如何用废弃电脑变成服务器搭建web网站(公网访问零成本)

文章目录 &#x1f4bb; 如何用废弃电脑变成服务器搭建 Web 网站&#xff08;公网访问零成本&#xff09;一、背景与目标✅ 本文目标&#xff1a; 二、准备工作&#xff08;软硬件需求&#xff09;&#x1f9f1; 1. 硬件需求&#x1f9f0; 2. 软件环境准备 三、快速搭建一个 Fl…

〔从零搭建〕指标体系平台部署指南

&#x1f525;&#x1f525; AllData大数据产品是可定义数据中台&#xff0c;以数据平台为底座&#xff0c;以数据中台为桥梁&#xff0c;以机器学习平台为中层框架&#xff0c;以大模型应用为上游产品&#xff0c;提供全链路数字化解决方案。 ✨杭州奥零数据科技官网&#xf…

Vue3 中watch和computed

Vue 3 中 computed 与 watch 深度解析 在 Vue 3 组合中&#xff0c;响应式工具的类型安全使用至关重要。以下是详细说明 一、watch 侦听器 1. 基础类型监听 <template><div>实际参数1{{count}}</div><div><button click"count">点…

.NET测试工具Parasoft dotTEST:全兼容RMS的测试解决方案

随着项目规模扩大&#xff0c;需求管理变得复杂&#xff0c;如何高效追溯需求与测试的关联性成为一大挑战。Parasoft dotTEST 提供了一套强大的需求追溯解决方案&#xff0c;不仅能自动关联单元测试结果与需求&#xff0c;还能兼容几乎所有需求管理系统&#xff08;RMS&#xf…

基于Jeecgboot3.8.1的vue3版本前后端分离的flowable流程管理平台

初步迁移完成了基于jeecgboot3.8.1的vue3版本的前后端流程管理平台,基于flowable6.8.0,同时支持bpmn流程设计器与仿钉钉流程设计器。 功能类似于3.6.3,但增加了一些以下功能: 1、支持多租户 2、支持并行网关的任意跳转、退回与驳回 3、流程表达式 这里流程表达式定义四…

IP 限流 vs. URI 限流

背景&#xff1a; 昨天调程序的时候遇到了一个 BUG&#xff0c;前端无法将文件正确传给后端&#xff0c;后端报错 EOFException&#xff08;EOF 代表 End Of File&#xff09;就是在程序尝试从一个数据流中读取数据时&#xff0c;发现已经到达了数据流的末尾&#xff0c;但它却…

2025年Java常见面试题(持续更新)

数据库事务特性。原子性、一致性、隔离性、持久性如何防止SQL注入&#xff1a;使用#不要使用$符号&#xff1b;对所有的入参做校验&#xff1b;使用存储过程&#xff1b;执行预处理语句和参数化查询&#xff1b;最低权限原则&#xff1b;微服务拆分的原则&#xff1a;微服务的拆…

Spring AI ——在springboot应用中实现基本聊天功能(ChatModel)

文章目录 前言项目版本依赖引入配置key信息编写测试接口注入ChatModel并普通返回注入ChatModel并流式返回自定义模型对象并直接返回总结前言 在Spring AI 中,CchatClient 是一个所有大模型通用性的调用方式,对绝大多数大模型的功能点都具备封装和见解调用性。 但这一点在部…

78、系统工程生命周期阶段及方法

一、系统工程生命周期的七大阶段 系统工程生命周期涵盖从概念萌芽到系统退役的全过程&#xff0c;通常分为以下七个阶段&#xff0c;每个阶段具有明确目标与核心任务&#xff1a; 1.探索性研究阶段 目标&#xff1a;识别利益相关者需求&#xff0c;探索技术可行性。任务&…

二十九、【用户体验篇】个人中心:用户资料展示与密码修改

二十九、【用户体验篇】个人中心:用户资料展示与密码修改 前言准备工作第一部分:后端实现 - 个人中心 API1. 修改 `UserDetailSerializer` 以支持密码修改2. 在 `api/views.py` 中添加 `UserMeView` 和 `PasswordChangeView`3. 注册个人中心相关 API 路由4. 后端初步测试第二…

STEP-BACK PROMPTING:退一步:通过抽象在大型语言模型中唤起推理能力

摘要 我们提出了 STEP-BACK PROMPTING&#xff0c;这是一种简单的提示技术&#xff0c;可以让LLM进行抽象&#xff0c;从包含具体细节的实例中推导出高层次概念和第一性原理。利用这些概念和原理来引导推理过程&#xff0c;LLM在朝向正确解答路径上显著提升了推理能力。我们在…