UR5
TODO
不再需要测试页面, 但是保留该页面, 用来暂时存储准备写但是还不值得单独创建一个post的内容
3dgs的缩放问题
起源于在使用点云初始化3dgs时, 试图寻找create_from_pcd函数中第二个参数的解释时, 发现了下面的issue
其中提到, 尺度问题对于缩放和位置可能是简单的, 但是对于旋转可能变换很大, 尤其是用来做pose estimation的时候.
From my understanding you’re right that both the scales and positions are easy to scale, however the real problem here is the rotations.
I bet you, that if you took EXACTLY the same scene and just rescaled it, you’d get VASTLY different ‘rotation’ results (whether that matters for the kind of nerf-scenes we’re optimizing is a different question), but I bet you at one end of the scale continuum they all stay at ‘eye’ rotation, and at the other end they all happy rotate around to wherever…
Like I said, maybe it doesn’t matter too much for making volume rendering look good, but for other apps where rotation is important (e.g. estimating camera poses) this matters ALOT…
About 1 year ago I did a lot of investigations into this with @leonidk and the best we came up with at the time was just to make sure to normalize your scene before optimizing (although maybe he has more opinions).
所以会有什么问题?没能理解
spatial_lr_scale根据我的理解,是根据当前场景的尺寸来修改学习率的初值,也就是对初值进行缩放。而且根据其他issue的反馈,学习率其实对于最终的渲染效果有很大的影响。有必要的话甚至需要手动去调整它。(因为对于3dgs的训练, 学习率动态调整是比较重要的一环)
关于这个参数值
在vanilla 3dgs的代码中:
Click to expand!
~~~ """ translate: np.array 均值点取反, 便于之后计算世界坐标系的均值化后的坐标 radius: float 相机中心点到最远的相机中心点的距离 * 1.1 """ def getNerfppNorm(cam_info): def get_center_and_diag(cam_centers): cam_centers = np.hstack(cam_centers) avg_cam_center = np.mean(cam_centers, axis=1, keepdims=True) center = avg_cam_center dist = np.linalg.norm(cam_centers - center, axis=0, keepdims=True) diagonal = np.max(dist) return center.flatten(), diagonal cam_centers = [] for cam in cam_info: W2C = getWorld2View2(cam.R, cam.T) C2W = np.linalg.inv(W2C) cam_centers.append(C2W[:3, 3:4]) center, diagonal = get_center_and_diag(cam_centers) radius = diagonal * 1.1 translate = -center return {"translate": translate, "radius": radius} ~~~该函数get_center_and_diag首先计算所有相机中心点的均值(avg_cam_center),然后计算每个相机中心点到这个均值中心点的距离(dist),最后取最大距离作为对角线长度(diagonal),最后取该值的1.1倍作为场景的半径。该结果最终被传入为spatial_lr_scale, 作为学习率的乘数。
cf3dgs在使用点云初始化3dgs时, 使用的是:
1
radius = np.linalg.norm(input.points,axis=1).max()
计算的是点云中所有点到原点的最大距离,但根据注释来看, 作者也不确定这样是否正确。因为与vanilla 3dgs中使用相机的中心点来计算完全不同。(而且这一方法对于点云要求预先进行均值化)
但实际上, CF3dgs其实也没有使用这个半径
init single image
只要有pose或depth任意一个, 就会得到比现在更好的结果。
深度loss
depth_gt是单目深度估计得到的, 但是在整个流程中, 实际上只在init_two_view中使用了一次. 也就是说,每一个序列的第一帧使用了深度来进行监督(虽然深度是估计出来的, 但是也算是一个缺陷)
C++
###
1
2
3
4
5
6
7
8
9
10
11
12
13
解释:In file included from /home/lab/workspace/cxx/intg/ARTest/AREngine/Basic/asset/cvf/BFC/ssh.cpp:2:
/home/lab/workspace/cxx/intg/ARTest/AREngine/Basic/asset/cvf/BFC/ssh.h:26:117: error: default member initializer for ‘ff::SSHSession::Options::port’ required before the end of its enclosing class
26 | void connect(const std::string &host, const std::string &userName, const std::string &password, Options op=Options());
| ^
/home/lab/workspace/cxx/intg/ARTest/AREngine/Basic/asset/cvf/BFC/ssh.h:21:12: note: defined here
21 | int port = 22;
| ^~~~~
/home/lab/workspace/cxx/intg/ARTest/AREngine/Basic/asset/cvf/BFC/ssh.h:26:117: error: default member initializer for ‘ff::SSHSession::Options::maxChannels’ required before the end of its enclosing class
26 | void connect(const std::string &host, const std::string &userName, const std::string &password, Options op=Options());
| ^
/home/lab/workspace/cxx/intg/ARTest/AREngine/Basic/asset/cvf/BFC/ssh.h:22:19: note: defined here
22 | int maxChannels = 1;
| ^~~~
这个错误信息指出,在 C++ 代码中,某个类成员变量的默认初始化器需要在类的封闭类定义结束之前定义。具体来说,错误发生在 ssh.h 头文件中,类 ff::SSHSession::Options 的成员变量 port 和 maxChannels 需要在类定义结束之前进行默认初始化。
错误原因
在 C++11 及其后续标准中,你可以在类内对成员变量进行默认初始化。但是,如果这些成员变量在类的方法中被默认参数使用,那么默认初始化器必须在该方法的定义之前出现。
解决方法
确保在类 ff::SSHSession::Options 定义中,对成员变量 port 和 maxChannels 进行默认初始化,并且这些初始化器出现在任何使用这些成员变量作为默认参数的方法之前。
1
2
3
4
5
6
7
8
9
10
11
namespace ff {
class SSHSession {
public:
struct Options {
int port = 22;
int maxChannels = 1;
};
void connect(const std::string &host, const std::string &userName, const std::string &password, Options op=Options());
};
}
1
2
3
4
5
6
7
#include "ssh.h"
namespace ff {
void SSHSession::connect(const std::string &host, const std::string &userName, const std::string &password, Options op) {
// Implementation of the connect function
}
}
修改后的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#pragma once
#include <string>
namespace ff {
class SSHSession {
public:
struct Options {
int port;
int maxChannels;
// 构造函数默认参数初始化
Options(int p = 22, int mc = 1) : port(p), maxChannels(mc) {}
};
void connect(const std::string &host, const std::string &userName, const std::string &password, Options op = Options());
};
}
结构体初始化
1
Options(int p = 22, int mc = 1) : port(p), maxChannels(mc) {}
构造函数
1
2
3
• Options(int p = 22, int mc = 1):这是构造函数的声明。它有两个参数:
• int p:用于初始化 port 成员变量,默认值为 22。
• int mc:用于初始化 maxChannels 成员变量,默认值为 1。
成员初始化列表
1
2
3
• : port(p), maxChannels(mc):这是成员初始化列表,它在构造函数体之前执行,用于初始化成员变量。
• port(p):使用参数 p 初始化成员变量 port。
• maxChannels(mc):使用参数 mc 初始化成员变量 maxChannels。
构造函数体
1
• {}:构造函数体是空的,因为所有的初始化工作已经在成员初始化列表中完成了。
行为
当你创建 Options 对象时,可以使用以下几种方式:
1
1. 使用默认参数