学习笔记之——2D Gaussian Splatting(2DGS)

3DGS在辐射场重建中取得了巨大的成就,实现高质量的新视图合成和快速渲染。最近新出了3DGS的升级版本,2DGS。写下本博文记录本人学习及测试2DGS的过程,本博文仅为本人学习记录用~

  • Project Website
  • Github Code
  • Original paper

目录

原理解读

什么是surfels?

2DGS与3DGS的区别

2DGS的理解

2DGS 的Modeling

2DGS的Splatting

2DGS的Rasterization

2DGS的训练及loss

Depth Distortion

Normal Consistency

Final Loss

代码测试

代码解读

参考材料


原理解读

由于3D 高斯在多视角下的不一致性,使得它在surface reconstruction中效果不佳。为此,作者提出用2D平面高斯圆盘(2D oriented planar Gaussian disks)来表征三维单元。2DGS通过采用surfels的表达方式,并使用针对surfels的投影方法较好地保证了多视角一致性。通过ray-splat intersection和 rasterization实现2D高斯的渲染。进一步的,通过在loss中引入depth distortion and normal consistency提高了重建几何的质量,而不能单单只靠RGB的loss。

从motivation来看,应该就是3D高斯难以处理复杂的几何形状下的重建,特别是平面会有比较多的noise(这点之前大量的实验也可观察到,也确实3D高斯球叠加一起的平面肯定有些棱角之类的noise)。对于3D高斯而言,对于相邻高斯球交汇处,不同的视角会有不同的渲染值/深度值(3DGS evaluates a Gaussian’s value at the intersection between a pixel ray and a 3D Gaussian, which leads to inconsistency depth when rendered from different viewpoints.)

而采用2D 高斯,也就是类似于Mesh或者surfels差不多的平面来构建的话,可以交换的拟合复杂的平面。

什么是surfels?

Surfels approximate the object surface locally with shape and shade attributes, and can be derived from known geometry.

Surfels(surface elements)是体积渲染文献中的“表面元素”或“表面体素”。其他人将其描述为零维n元组,其形状和阴影属性局部近似于对象表面。对象可以由一组密集的点(表面)表示,这些点(表面)保存照明信息。

A surfel, that is, a point structure representing Euclidean xyz coordinates, together with normal coordinates, a RGBA color, a radius, a confidence value and the surface curvature estimate.

其表达如下:

基于surfels的方法基本上都需要几何的GT、深度信息或者在光照已知的场景下才能运行。而2DGS将其结合起来。2DGS采用了扁平的基元(2D高斯,oriented elliptical disk)对3D场景进行表示,2DGS的基元辐射场垂直于其法线,使其可以更好地贴合场景表面。

2DGS与3DGS的区别

关于3DGS的原理,此处就不再阐述了,请见博客:学习笔记之——3D Gaussian Splatting及其在SLAM与自动驾驶上的应用调研_3d gaussian splatting slam-CSDN博客

虽然3DGS取得巨大的成就,但是由于3D 高斯在多视角下的不一致性,使得它在surface reconstruction中效果不佳。而2D高斯则是多视觉一致性强。而2DGS使用2D的圆盘来表示场景,这使得2DGS与3DGS相比能够表达精确的表面几何。3DGS通过像素发出的光线束和3D Gaussian之间的交平面来计算投影到像平面的高斯值,这在不同视点进行渲染时会导致得到不同的depth(因此depth sort的结果也会不连续)。2DGS使用ray-splat来得到准确连续的投影结果,大大提高了几何的质量。如下图所示。对于3DGS而言,不同的视角,其对应的是不同的交互平面(Intersection Plane),但是对于2DGS,都是相同的平面,因此多视角一致性较强~

此外,2D高斯中固有的表面法线使得能够通过法线约束进行直接的重构表面进行正则化,因此相比于传统的surfel-based的方法,2DGS可以从未知几何体中恢复。(2DGS天生具有normal使其可以很自然地使用normal进行监督,并且2DGS可以通过基于梯度的优化方法从未知的几何中进行重建。)

如下图所示,2DGS所构建的平面光滑一些~

下图放大一些细节就更明显了~

虽然效果比较不错,但是2DGS是通过不透明度来判断场景的表面,对于诸如玻璃一类半透明的物体会遇到较大困难。其次,2DGS的densification策略使其主要集中在纹理较丰富区域,对于弱纹理区域表示较差。

2DGS的理解

2DGS 的Modeling

2DGS采用了扁平的基元(planar disk)对场景进行表示,2DGS的基元辐射场垂直于其法线(the normal as the direction of steepest change of density),使其可以更好地贴合场景表面。也有其他类似的工作采用2D 高斯来做几何重建,但是需要稠密的点云以及真值法向量作为输入,但是本文只需要colmap或sfm得到的稀疏点以及作为supervision的图片。

如所图所示。2D高斯的定义为:其中心点 p_{k},两个切向量 t_{u}t_{v}一个控制2D Gaussians 方差的scaling向量(scalling vector)S=\left (s_{u}, s_{v} \right)。2D Gaussians的法线由两个互相正交的切向量来定义t_{w}=t_{u}\times t_{v} 。因此2D高斯的方位参数可以组织成旋转矩阵R=\left [ t_{u}, t_{v}, t_{w} \right ],缩放参数(scalling factors)可以组织为最后一列为0的对角矩阵 𝑆 。

一个2D Gaussian被定义在3D空间中局部的切平面(local tangent plane)坐标系如下:

其中H ∈ 4 × 4 是一个齐次变换矩阵,可以表示2D Gaussian的几何形状。这里的点u = (𝑢, 𝑣)是在2D Gaussian的局部的切平面(local tangent plane)中取得的,可以理解为此时高斯函数的均值为0,方差为1,因此可以通过一个简单的公式高效地计算点 𝑢 的函数值:

随后可以通过矩阵 𝐻 将局部点 𝑢 变换到全局坐标系中。中心点 p_{k} 、尺度S=\left (s_{u}, s_{v} \right)、rotation \left ( t_{u}, t_{v} \right )都是可学习的参数,并且与3DGS一样,2D Gaussian基元也有opacity 𝛼 和通过球谐函数计算的视角依赖的外观c。

2DGS的Splatting

渲染2D Gaussians的常用策略是利用透视投影的仿射近似将2D Gaussian基元投影到image space。但这个方法只有在接近基元中心是准确的,离中心越远误差越大。为了解决这个问题,采用基于齐次坐标的计算公式,将2D splat的投影过程描述为齐次表示下一个统一的2D-to-2D的映射。让W ∈ 4 × 4 为world space到camera space到变换矩阵(transformation matrix from world space to screen space),则screen space到点可以通过下式进行计算:

其中 𝑥 表示从像素 (𝑥,𝑦) 发射点一条齐次坐标表示的光线,其与2D splat在深度 𝑧 处相交。因此,给定一个屏幕坐标 (𝑥,𝑦) ,可以计算得到Gaussian space的坐标 。但这个逆变换矩阵带来了数值的不稳定性,特别是从侧面观察splat退化为线段时。以前的一些方法会设定一个阈值,当splat退化到一定程度时就不再使用这个变换,但这又会使得可微渲染的优化过程不稳定。为了解决这个问题,2DGS使用了一个显式的ray-splat intersection。

Ray-splat Intersection: 2DGS中采用了计算三个非平行平面的交点来得到ray和splat的交点。首先从图像坐标系下任意点 𝑥=(𝑥,𝑦) 出发,根据其两个坐标轴方向的normal (−1,0,0),(0,−1,0) 和任意位移量 𝑥,𝑦 确定两个以齐次坐标表示的平面h_{x} = \left (-1, 0, 0, x \right ) ; h_{y}=\left (0,-1,0,y \right ),这两个平面的交线确定从对应像素发出的ray。接下来将这两个平面变换到2D Gaussian的局部坐标系下(将平面内的点进行变换时使用变换矩阵 𝑀 ,等价于使用其逆转置矩阵M^{-T}):

由前面得到的2D Gaussian局部坐标系下点坐标为 (𝑢,𝑣,1,1) ,以及ray-splat intersection位于两个平面内,可以得到:

通过这个式子可以导出ray-splat intersection的计算公式:

其中h_{u}^{i} ; h_{v}^{i}分别代表齐次坐标平面的第i个参数。

Degenerate Solutions: 从一些很斜的角度看,2D Gaussian会退化成一条线,在rasterization过程中会突然消失。为了解决这个问题,2DGS中使用一个object-space的低通滤波:

其中 𝑢(𝑥) 为ray-splat intersection, 𝑐 是投影后的2D Gaussian的中心。

2DGS的Rasterization

2DGS的rasterization过程与3DGS一致,首先为2D Gaussian计算一个screen space的bound ing box,然后将2D Gaussians按照其depth进行排序并且根据bounding box将其划分为多个tiles,最后使用volumetric α blending来累加得到最终的color:

2DGS的训练及loss

如果仅仅使用photometric loss,重建得到的几何会比较noisy,于是2DGS引入了两个regularization terms对几何进行约束。

(由于3D重建任务的多解性,2DGS中除了rgb loss外还使用了两个loss,分别是对depth的监督和对normal连续性的约束。通过额外的两个约束,使得2DGS能够重建出精确的mesh)

Depth Distortion

由于3DGS的体渲染没有考虑intersected高斯基元之间的距离,因此分散的高斯会导致相似的颜色和深度渲染,即体渲染过程中没有准确地对表面部分进行渲染。为了解决这个问题,可以通过最小化ray-splat intersections之间的距离,来使体渲染的权重尽量集中在表面:

其中,。2DGS在CUDA中对这一项进行了高效的实现。

Normal Consistency

2DGS这种基于2D Gaussians的surfels表达需要在局部上保证和真实的表面对齐,但体渲染中一条光线上可能会有多个半透明的surfels,于是2DGS将中间的surfels即累积不透明度为0.5的点视为真实表面所在的位置。随后将真实表面位置对应的normal与depth maps的梯度对齐:

其中 𝑖 代表沿着光线排列的intersected splat, 𝜔 代表交点处的blending weight, 𝑛𝑖 ​​代表splat朝向camera的法线, N 代表depth maps的归一化梯度,可以由下式计算:

Final Loss

最终的loss为:

其中第一项为rgb loss, 𝛼=100∼1000,𝛽=0.05。那么就是Normal Consistency的贡献量相对少些?

下面图例将2DGS与3DGS的数学模型放在一起对比,有助于更加直观的感受二者的区别~

至于从论文的实验来看,视觉效果好像是2DGS好不少,但是数值效果跟3DGS差不多~

代码测试

安装

git clone https://github.com/hbb1/2d-gaussian-splatting.git --recursive


# if you have an environment used for 3dgs, use it
# if not, create a new environment
conda env create --file environment.yml
conda activate surfel_splatting

由于之前已经有3DGS的环境了,因此直接用原来的conda环境

conda activate 3DGS

但是运行的时候会报错,大几率是环境名字不一样,所以不能直接用3DGS的环境,重新安装2DGS的环境~

但是还是会报错如下:

看上去像是setuptools版本有问题。应该是由于安装的python包的环境不对?为此先把构建好的conda 环境remove掉。然后更新一下yaml文件如下

name: surfel_splatting
channels:
  - pytorch
  - nvidia
  - conda-forge
  - defaults
dependencies:
  - ffmpeg=4.2.2
  - pillow=10.2.0
  - pip=23.3.1
  - python=3.8.18
  - pytorch=2.0.0
  - torchaudio=2.0.0
  - torchvision=0.15.0
  - typing_extensions=4.9.0
  - setuptools=69.5.1
  - pip:
    - open3d==0.18.0
    - mediapy==1.1.2
    - lpips==0.1.4
    - scikit-image==0.21.0
    - tqdm==4.66.2
    - trimesh==4.3.2
    - submodules/diff-surfel-rasterization
    - submodules/simple-knn
conda remove --name surfel_splatting --all
conda env create --file environment.yml
conda activate surfel_splatting

配置成功

开启训练

conda activate surfel_splatting

python train.py -s <path to COLMAP or NeRF Synthetic dataset>


#测试tandt数据集
python train.py -s /home/gwp/dataset/tandt/train -m output/tandt/train 

#验证
python render.py -s /home/gwp/dataset/tandt/train -m output/tandt/train --unbounded --skip_test --skip_train --mesh_res 1024

但是会报错No module named 'plyfile'

 pip install plyfile,然后再运行

又显示ModuleNotFoundError: No module named 'cv2'

安装

pip install opencv-python

终于可以了~~~~

先试试采用MobaXterm用SIBR_remoteGaussian_app来可视化,但是没有任何输出~(github issue中也提出了online SIBR viewer for 2dgs · Issue #17 · hbb1/2d-gaussian-splatting · GitHub)

因此,需要等待有模型保存后再运行下面命令

训练完后也有对应的模型输出了~

conda activate surfel_splatting


#验证
python render.py -s /home/gwp/dataset/tandt/train -m output/tandt/train --unbounded --skip_test --skip_train --mesh_res 1024

CUDA_VISIBLE_DEVICES=3 python render.py -s /home/gwp/dataset/tandt/train -m output/tandt/train --unbounded --skip_test --skip_train --mesh_res 1024

CUDA_VISIBLE_DEVICES=3 python render.py -s /home/gwp/dataset/tandt/train -m output/tandt/train --skip_test --skip_train --mesh_res 1024

注意模型太大可能会爆掉内存,感觉这个可视化还是有点问题~(加载模型也很慢)

最终把渲染点云生成后再用gaussian-splatting-lightning来查看

python viewer.py TRAINING_OUTPUT_PATH
 
在本次实验中为如下:

conda activate gspl

python viewer.py /home/gwp/2d-gaussian-splatting/output/tandt/train/point_cloud/iteration_30000/point_cloud.ply

出来的不知道是什么鬼。。。

换个数据集再测试看看~

#测试chair数据集
python train.py -s /home/gwp/dataset/chair -m output/chair

然后运行可视化


conda activate gspl

CUDA_VISIBLE_DEVICES=3 python render.py -s /home/gwp/dataset/chair -m output/chair --unbounded --skip_test --skip_train --mesh_res 1024

python viewer.py /home/gwp/2d-gaussian-splatting/output/chair/point_cloud/iteration_30000/point_cloud.ply

出来的还是一坨不知道什么东西,大概是要用作者后续开发的可视化界面吧~

代码解读

类似3DGS系列的博客,关于2DGS的代码解读后续会push到github仓库~

参考材料

2D Gaussian Splatting论文阅读笔记 - 知乎

更多关于3DGS的介绍及解读请见:

http://t.csdnimg.cn/ZwV2ricon-default.png?t=N7T8http://t.csdnimg.cn/ZwV2r

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3项目炫酷实战,检测密码强度值

在前端项目开发中&#xff0c;确保用户密码的强度是保护账户安全的重要措施。本文将演示如何使用Vue 3实现一个简单的密码强度检测功能。通过实时反馈&#xff0c;帮助用户创建更安全的密码&#xff0c;从而提升整体系统的安全性。无论您是前端开发新手还是经验丰富的开发者&am…

实验9 静态路由配置

实验9 静态路由配置 一、 原理描述二、 实验目的三、 实验内容四、 实验配置五、 实验步骤 一、 原理描述 网络中的每个路由器都会维护一张路由表或转发表。路由表的表项记录着目的网络信息以及下一跳I 地址。路由表可以手动配置&#xff0c;也可以通过路由算法动态生成。静态…

.NET最新漏洞 | 某SLMS系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

结合视差补偿与3D数据处理的盲光场图像质量评价

摘要&#xff1a;与传统的2D图像相比&#xff0c;光场图像记录了场景中光线的强度和方向信息&#xff0c;在多媒体技术应用领域中占据着重要的地位。但在光场图像的产生、传输等处理过程中会不可避免地引入失真&#xff0c;影响用户视觉体验&#xff0c;因而需构建有效、准确的…

副业变现:AI技术在多领域创收的七大策略

AI副业变现&#xff1a;开启你的智能创富之路 近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术迅猛发展&#xff0c;从大数据分析到自然语言处理&#xff0c;AI正在深刻地改变我们的生活和工作方式。越来越多的人开始利用AI技术发展副业&#xff0c;实现智能创富。…

数字认证携手华为鸿蒙生态,升级智慧办公新体验

5月29日,“千帆竞发启航 共筑鸿蒙生态”鸿蒙原生应用合作仪式在北京成功举办,近40个应用现场官宣启动鸿蒙原生应用开发。数字认证应邀参加,基于HarmonyOS NEXT鸿蒙星河版,数字认证对“掌上信手书”App进行了鸿蒙原生应用开发,为用户提供更安全、更便捷的使用体验。双方此次战略…

软件3班20240603

经典 报错 404 大概率 就是 这图 的 路径 写错i了 package com.yanyu;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import jav…

基于PCIE X16总线架构的4路QSFP28 100G光纤通道适配器(可实现100%国产化)

板卡概述 PCIE736是一款基于PCIE总线架构的4路QSFP28 100G光纤通道适配器&#xff0c;该板卡具有1个PCIe Gen3x16主机接口、一共4个QSFP28 100G光纤接口&#xff0c;可以实现4路QSFP28 100G光纤的数据实时采集、实时缓存与PCIE高速传输。该板卡采用Xilinx的高性能Virtex Ultra…

Redis-02

redis安装包位置 /opt/redis-7.2.5 redis默认安装路径&#xff1a; 配置文件路径&#xff1a;/usr/local/bin/redisconfig gcc安装位置 /opt/rhredis启动&#xff1a; 在/usr/local/bin目录下输入redis-server redisconfig/redis.confredis-cli -p 6379redis性能测试命令 red…

ES6-02-变量的解构赋值

一、解构赋值的定义 ES6允许按照一定模式从数组和对象中提取值&#xff0c;对变量进行赋值。 二、解构的使用 1、数组解构 2、对象解构 3、方法的解构&#xff08;用的多&#xff09; const zhao {name: 赵本上,age: 不知道,xiaopin: function () {console.log(我能演小品);…

【Python3.11版本利用whl文件安装对应的dlib-19.24.1-cp311-cp311-win_amd64.whl库】

下载Python对应的安装包 找到自己Python版本对应的dlib whl库将网盘下载好的文件放在安装Python的Scripts路径下面接着在该路径输入cmdpip进行安装使用的是国内的源 找到自己Python版本对应的dlib whl库 python 3.11 对应 dlib-19.24.1-cp311-cp311-win_amd64.whl -i 也可以去…

Github上一款开源、简洁、强大的任务管理工具:Condution

Condution 是一款开源任务管理工具&#xff0c;它以简洁易用、功能强大著称。它旨在为用户提供一个简单高效的平台&#xff0c;帮助他们管理日常任务、提高工作效率。 1. Condution 的诞生背景 现如今&#xff0c;市面上存在着许多任务管理软件&#xff0c;但它们往往价格昂贵…

LeetCode 算法:和为 K 的子数组c++

原题链接&#x1f517;&#xff1a;和为 K 的子数组 难度&#xff1a;中等⭐️⭐️ 题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;num…

C语言:学生成绩管理系统(含源代码)

一.功能 二.源代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_NUM 100 typedef struct {char no[30];char name[10];char sex[10];char phone[20];float cyuyan;float computer;float datastruct; } *student, student1;typ…

基于springboot实现人事管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现人事管理系统演示 摘要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;问卷信息因为其管理内容繁杂&#xff0c;管理数…

AWS EC2服务器开启root密码,SSH登录

1) EC2 Instance Connect连接&#xff0c;更改root密码 sudo passwd root 2&#xff09;接着切换到切换到 root 身份&#xff0c;编辑 SSH 配置文件 $ sudo -i$ vi /etc/ssh/sshd_configPasswordAuthentication no&#xff0c;把 no 改成 yes #PermitRootLogin prohibit-passw…

TPM 是什么?如何查看电脑的 TPM?

TPM 是什么&#xff1f; 首先我们来了解一下 TPM 是什么&#xff0c;TPM 由可信计算组织&#xff08;Trusted Computing Group&#xff0c;TCG&#xff09;开发&#xff0c;为了在提高计算机系统的安全性。随着网络安全威胁的不断增加&#xff0c;TPM 技术逐渐成为确保系统安全…

创新指南|提高人才回报率的重要举措和指标

员工是组织最大的投资&#xff0c;也是最深层的价值源泉。人才系统必须同时强调生产力和价值创造。让合适的人才担任合适的职位&#xff0c;并为员工提供成功所需的支持和机会&#xff0c;这是实现回报的关键。本文将介绍组织可以采取的五项行动&#xff0c;以最大化企业的人才…

批量剪辑软件 故事影视解说

故事影视解说1 1.根据导入的文案&#xff08;也可直接导入音视频文件或者字幕文件&#xff0c;软件会自动提取文案或整理字幕文件内容&#xff09;进行配音并结合背景素材&#xff08;支持图与视频&#xff0c;支持可选择是否混剪&#xff09;合并&#xff08;可选择性是否加对…

QT 如何在 QListWidget 的选项中插入自定义组件

有时我们需要 QListWidget 完成更复杂的操作&#xff0c;而不仅限于添加文本或者图标&#xff0c;那么就会使用到 setItemWidget 函数&#xff0c;但是这也会伴生一个问题&#xff0c;插入自定义组件后&#xff0c;QListWidget 对选项点击事件的获取会收到阻塞&#xff0c;因…