3D高斯详解forward.cu

一、3D高斯椭球表示

我们知道高斯分布的范围即G的值为0-1,三维高斯分布的式子如下图第一个公式所示,∑ 表示协方差矩阵,半正定,|Z|是其行列式。然而当指数部分为常数时候就变成了椭圆公式。

 为什么是协方差矩阵?

二、协方差矩阵的表达 

首先结论:任意圆球可以通过仿射变换变为椭球。三维标准高斯是圆球

 协方差矩阵为什么能用旋转R和缩放S矩阵表达?

3DGS计算三维协方差矩阵的代码: 

// Forward method for converting scale and rotation properties of each
// Gaussian to a 3D covariance matrix in world space. Also takes care
// of quaternion normalization.
__device__ void computeCov3D(const glm::vec3 scale, float mod, const glm::vec4 rot, float* cov3D)
{
	// Create scaling matrix
	glm::mat3 S = glm::mat3(1.0f);
	S[0][0] = mod * scale.x;
	S[1][1] = mod * scale.y;
	S[2][2] = mod * scale.z;

	// Normalize quaternion to get valid rotation
	glm::vec4 q = rot;// / glm::length(rot);
	float r = q.x;
	float x = q.y;
	float y = q.z;
	float z = q.w;

	// Compute rotation matrix from quaternion
	glm::mat3 R = glm::mat3(
		1.f - 2.f * (y * y + z * z), 2.f * (x * y - r * z), 2.f * (x * z + r * y),
		2.f * (x * y + r * z), 1.f - 2.f * (x * x + z * z), 2.f * (y * z - r * x),
		2.f * (x * z - r * y), 2.f * (y * z + r * x), 1.f - 2.f * (x * x + y * y)
	);

	glm::mat3 M = S * R;

	// Compute 3D world covariance matrix Sigma
	glm::mat3 Sigma = glm::transpose(M) * M;

	// Covariance is symmetric, only store upper right
	cov3D[0] = Sigma[0][0];
	cov3D[1] = Sigma[0][1];
	cov3D[2] = Sigma[0][2];
	cov3D[3] = Sigma[1][1];
	cov3D[4] = Sigma[1][2];
	cov3D[5] = Sigma[2][2];
}

三、 3D椭球投影到2D

1)首先是物体坐标系中给出位置数据。(在slam中我认为是世界坐标系)使用仿射变换将其映射摄像机坐标系。
2)投影变换,从相机到射线空间的转换,是我们技术的关键元素。由于其目的类似于在OpenGL等渲染流水线中使用的投影变换,它也被称为投影映射。最终会被放在-1到1的正方体内,也就是NDC坐标内。
3)视口变换
4)光栅化

(1)物理坐标到相机坐标系的
其实就是普通法的仿射变换,旋转和平移

 (2)投影变换

投影变换将像机坐标转换为射线坐标,如图  所示。摄像机空间的定义是,摄像机坐标系的原点位于投影中心,投影平面为 u=1的平面。相机空间和射线空间通过映射相关联。

投影变换

然而高斯球的点三维位置可以直接变换,但它的协方差矩阵的变换我们希望是线性的。我们不能直接应用方程将重建核从相机空间转换到射线空间。为了解决个问这题,我们引入了投影变换的局部仿射近似 。即在高斯球中心点很小的范围内我们近似是线性的。

该图被夸大以显示精确映射中的非线性效应。仿射映射基本上近似于透视投影与斜投影。因此,平行线被保留,并且近似误差随着射线发散而增大。然而,一般来说,误差不会导致视觉伪影,因为与重建核的局部支持相交的射线扇形具有小的开口角度。

(3)视口变换 

此时3D高斯在NDC坐标内,也就是大小为1的方格中,我们要根据图片的H*W进行放大,此时协方差是不变的。

__device__ float3 computeCov2D(const float3& mean, float focal_x, float focal_y, float tan_fovx, float tan_fovy, const float* cov3D, const float* viewmatrix)
{
	// The following models the steps outlined by equations 29
	// and 31 in "EWA Splatting" (Zwicker et al., 2002). 
	// Additionally considers aspect / scaling of viewport.
	// Transposes used to account for row-/column-major conventions.
	//世界坐标系到相机坐标系的投影,mean是三维高斯球的均值
	float3 t = transformPoint4x3(mean, viewmatrix);

    //限制x和y不超过1.3倍,小于1.3倍取原来的小的,大于1.3倍取1.3倍
	const float limx = 1.3f * tan_fovx;
	const float limy = 1.3f * tan_fovy;
	const float txtz = t.x / t.z;
	const float tytz = t.y / t.z;
	t.x = min(limx, max(-limx, txtz)) * t.z;
	t.y = min(limy, max(-limy, tytz)) * t.z;

	//根据公式计算雅可比矩阵,focal_x为x方向上的焦距,一个是x维,一个是y维
	glm::mat3 J = glm::mat3(
		focal_x / t.z, 0.0f, -(focal_x * t.x) / (t.z * t.z),
		0.0f, focal_y / t.z, -(focal_y * t.y) / (t.z * t.z),
		0, 0, 0);

	glm::mat3 W = glm::mat3(
		viewmatrix[0], viewmatrix[4], viewmatrix[8],
		viewmatrix[1], viewmatrix[5], viewmatrix[9],
		viewmatrix[2], viewmatrix[6], viewmatrix[10]);

	glm::mat3 T = W * J;

	glm::mat3 Vrk = glm::mat3(
		cov3D[0], cov3D[1], cov3D[2],
		cov3D[1], cov3D[3], cov3D[4],
		cov3D[2], cov3D[4], cov3D[5]);

	//论文公式二维协方差矩阵 V=JWVWJ
	glm::mat3 cov = glm::transpose(T) * glm::transpose(Vrk) * T;

	// Apply low-pass filter: every Gaussian should be at least
	// one pixel wide/high. Discard 3rd row and column.
	cov[0][0] += 0.3f;
	cov[1][1] += 0.3f;
	return { float(cov[0][0]), float(cov[0][1]), float(cov[1][1]) };
}

四、 3D高斯的颜色

五 CUDA编程

首先cuda函数和c语言编成差不多,但是cuda函数不能单独调用,只能用c++调用cuda核函数。cuda核函数必须以__global__ void开头这样就很好找。如下:

__global__ void __launch_bounds__(BLOCK_X * BLOCK_Y)

以下是c调用和函数,第一个是块block的数量,第二个是block中线程的数量。

preprocessCUDA<NUM_CHANNELS> << <(P + 255) / 256, 256 >> >

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值