dhang
November 22, 2023, 1:35pm
1
有两个问题:
1.文档中说根据误差矩阵可以计算得到误差 cost,但是 cost 的类型是 float,如何从一个四乘四的矩阵计算出它对应的误差呢?
2.在对每个面片进行初始化时,计算他的二次误差矩阵需要用到坍缩后的点的坐标 x,但此时还没有计算出对应边的 K,更解不出 x,应该怎么办呢?
同时,这样子去计算最佳坍缩位置是否正确:
Eigen::JacobiSVD<Eigen::Matrix4f> svd(K, Eigen::ComputeFullV); // 解 Kx = 0
Vector4f x_best = svd.matrixV().col(3); // 取最后一列
x_best.normalize(); // 归一化
optimal_pos = x_best.segment(0,3); // 前三位就是所需坐标
同学,虽然你提问的格式很工整,但就你的问题内容而言我认为你是没有认真看实验文档的,以后还请注意。
文档中说根据误差矩阵可以计算得到误差 cost,但是 cost 的类型是 float,如何从一个四乘四的矩阵计算出它对应的误差呢?
如果你看得太快了,那么产生这个问题也不奇怪。在解释 QEM 简化的近似思路时,实验文档中一直强调该算法是根据 坍缩后的点到坍缩前网格的距离 来评判坍缩结果好坏的。
在问题 3.2 的回答中,我们明确提到该算法是用这个距离作为误差的,而给出式 3.2 之前,我们也说明了算法中使用距离的平方比有向距离更好。因此,计算单个面片误差估计值的公式就是式 3.2,即使用最优点 \mathbf{x} 和二次误差矩阵 K 求距离平方:
\text{cost}=(\mathbf{u}\cdot\mathbf{v})^2=\mathbf{u}^T(\mathbf{v}\mathbf{v}^T)\mathbf{u}=\mathbf{u}^TK_f\mathbf{u}
而根据矩阵乘法的分配率,将若干 K_f 累加所得的边误差矩阵 K 代入上式,结果与分别将每个 K_f 代入后求和相同。所以式 3.2 同样适用于计算边坍缩误差估计值,在 3.2.2 节末尾已经说得很明确了。
在对每个面片进行初始化时,计算他的二次误差矩阵需要用到坍缩后的点的坐标 x,但此时还没有计算出对应边的 K,更解不出 x,应该怎么办呢?
这里你应该是完全理解错了计算面片 K_f 的过程。文档中的原话是:“对任意的点 \mathbf{x} ,一个恒定的系数矩阵 K_f 决定了 \mathbf{x} 到这个平面的距离”,因此 K_f 这个矩阵只要知道面片的法向量 \mathbf{N} 就能根据式 3.1 和 3.2 求出来。
你求最佳位置的代码也是不对的。首先这里 K 是一个四维方阵,但你要求解的方程组中并没有四个线性无关的未知数(齐次坐标形式下,点的最后一维应当是 1),因此你应该将系数矩阵 K 改写成一个三阶而非四阶的线性方程组来求解。如果像你这样直接求解四阶方程组,最后又调用 normaliz
将四维解向量归一化,那么最后一维一定不是 1,此时直接取前三维得到的就不是三维空间中的坐标。
另外,因为矩阵 K 必定是对称正定矩阵,你完全没有必要用 SVD 分解来求解方程组,随便用一种能解方程组的方法就够了。