代码
1. 在 diff-gaussian-rasterization/cuda_rasterizer/forward.cu 的 preprocessCUDA函数,line235,不需要再求特征向量和旋转角度了,可以都注释掉
// 计算中间值
float mid = 0.5f * (cov.x + cov.z);
// 计算特征值
float lambda1 = mid + sqrt(fmax(0.1f, mid * mid - det));
float lambda2 = mid - sqrt(fmax(0.1f, mid * mid - det));
// 计算长轴半径
float long_radius = ceil(3.f * sqrt(fmax(lambda1, lambda2)));
// 计算短轴半径
float short_radius = ceil(3.f * sqrt(fmin(lambda1, lambda2)));
//求特征向量
float eigenvectors[2][2];
eigenvectors.x = cov.y / (lambda1 - cov.x);
eigenvectors.y = cov.y / (lambda2 - cov.x);
// 取第一个特征向量
float v1[2] = {eigenvectors.x, eigenvectors.y};
// 计算旋转角度
float rotation_angle = atan2(v1.y, v1.x);
2. 在 diff-gaussian-rasterization/cuda_rasterizer/auxiliary.h,对getRect函数进行修改,比起V1求的是能够覆盖整个椭圆的矩形,V2更直接求出与椭圆面积最为匹配的矩形坐标,不再需要angle
__forceinline__ __device__ void getRect(const float2 p, float long_radius, float short_radius, float angle, uint2& rect_min, uint2& rect_max, dim3 grid)
{
// 计算矩形的左上角坐标
if (angle >= 45 and angle < 135) or (angle >= 225 and angle < 315):
float rect_top_left_x = p.x - short_radius;
float rect_top_left_y = p.y - long_radius;
else:
float rect_top_left_x = p.x - long_radius;
float rect_top_left_y = p.y - short_radius;
// 将矩形左上角坐标转换为索引
rect_min = {
min(grid.x, max((int)0, (int)(rect_top_left_x / BLOCK_X))),
min(grid.y, max((int)0, (int)(rect_top_left_y / BLOCK_Y)))
};
// 计算矩形的右下角坐标
float rect_bottom_right_x = p.x + long_radius;
float rect_bottom_right_y = p.y + short_radius;
// 将矩形右下角坐标转换为索引
rect_max = {
min(grid.x, max((int)0, (int)((rect_bottom_right_x + BLOCK_X - 1) / BLOCK_X))),
min(grid.y, max((int)0, (int)((rect_bottom_right_y + BLOCK_Y - 1) / BLOCK_Y)))
};
}
这是whismer修正过的版本
__forceinline__ __device__ void getRect(const float2 p, float long_radius, float short_radius, float angle, uint2& rect_min, uint2& rect_max, dim3 grid)
{
// 计算矩形的左上角坐标
float rect_top_left_x, rect_top_left_y;
if ((angle >= 45 and angle < 135) or (angle >= 225 and angle < 315)) {
rect_top_left_x = p.x - short_radius;
rect_top_left_y = p.y - long_radius;
} else {
rect_top_left_x = p.x - long_radius;
rect_top_left_y = p.y - short_radius;
}
// 将矩形左上角坐标转换为索引
rect_min = {
min(grid.x, max((int)0, (int)(rect_top_left_x / BLOCK_X))),
min(grid.y, max((int)0, (int)(rect_top_left_y / BLOCK_Y)))
};
// 计算矩形的右下角坐标
float rect_bottom_right_x = p.x + long_radius;
float rect_bottom_right_y = p.y + short_radius;
// 将矩形右下角坐标转换为索引
rect_max = {
min(grid.x, max((int)0, (int)((rect_bottom_right_x + BLOCK_X - 1) / BLOCK_X))),
min(grid.y, max((int)0, (int)((rect_bottom_right_y + BLOCK_Y - 1) / BLOCK_Y)))
};
}
3. 再改一下getRect的调用方式,加上angle,在 diff-gaussian-rasterization/cuda_rasterizer/forward.cu的line235
getRect(point_image, long_radius, short_radius, angle, rect_min, rect_max, grid);
原理
角度angle在45-135度之间和225-315度之间的时候,长轴更接近y轴。
()实验结果
2. 训练对比
V0训练时长 | V0-PSNR | V3训练时长 | V3-PSNR | 备注 | |
db-drjohnson | 30m39s | 36.81 | ❌ | ||
db-playroom | 24m40s | 35.83 | ❌ | ||
m-bicycle | 43m33s | 27.14 | 50m34s | 27.00 | |
m-bonsai | 21m53s | 33.72 | 22m54s | 33.76 | |
m-counter | 24m28s | 30.41 | 25m28s | 30.40 | |
m-garden | ❌ | ||||
m-kitchen | ❌ | ||||
m-room | ❌ | ||||
m-stump | ❌ | ||||
tt-train | 13m34s | 24.64 | ❌ | ||
tt-trunk | ❌ |
- V3还没V2效果好诶,而且也不是全部能跑通。好奇怪。更慢是可以理解的,可是为什么更不好呢?
3. 渲染对比
V0渲染速度 | V0-PSNR | V3渲染速度 | V3-PSNR | 备注 | |
db-drjhonson | |||||
db-playroom | 1.09it/s | ||||
m-bicycle | 1.37s/it | 1.43s/it | |||
m-bonsai | 1.48s/it | 1.55s/it | |||
m-counter | 1.54s/it | 1.61s/it | |||
m-garden | |||||
m-kitchen | |||||
m-room | |||||
m-stump | |||||
tt-train | 2.06it/s 1.53it/s | ||||
tt-trunk |
- 对于