Eigen中SVD的理解
1.SVD = 奇异值分解
你可以把它理解成:
把一个复杂矩阵 A,拆成 3 个简单矩阵:A = U * Σ * Vᵀ
U:左边正交矩阵
Σ:中间只有对角线上有数字(奇异值)
V:右边正交矩阵
2. 我们为什么要做 SVD?
因为我们要解方程:
Ax = 0
而且约束:
x 的长度 = 1(||x||=1)
数学上已经证明:
满足条件的最优解 x = V 矩阵的最后一列!
这就是三角化能算出 3D 点的原因!
代码解释
auto svd = A.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV);
① A.bdcSvd(...)
对矩阵 A 做 SVD 分解
bdcSvd = Eigen 里最快、最常用的 SVD 算法
② Eigen::ComputeThinU
计算 U 矩阵
thin = 只算有用的部分,更快更小
③ Eigen::ComputeThinV
计算 V 矩阵
我们最需要 V!因为解藏在 V 的最后一列
④ |
= 同时要 U 和 V
小例子
点击查看代码
#include <iostream>
#include <Eigen/Core>
#include <Eigen/SVD>
using namespace std;
using namespace Eigen;
int main() {
// 构造一个 4x4 矩阵,让 Ax=0 有解
MatrixXd A(4, 4);
A << 1, 2, 3, 4,
2, 4, 6, 8, // 和第一行线性相关
3, 6, 9, 12, // 线性相关
5,10,15,20; // 线性相关
auto svd = A.bdcSvd(ComputeFullU | ComputeFullV);
// ==============================================
cout << "V 矩阵(4列):\n" << svd.matrixV() << "\n\n";
// 现在可以安全取最后一列!
VectorXd x = svd.matrixV().col(3);
cout << "Ax=0 的解 x = V最后一列:\n" << x << endl;
auto x=svd.matrixV().col(3);
cout<<"x的长度="<<x.norm()<<endl;
return 0;
}

在公式 A = U * Σ * Vᵀ
中:奇异值 只在 Σ 矩阵里
SVD 奇异值的含义:
大奇异值:方程约束很强
接近 0 的奇异值:方程几乎没有约束,解可以随便飘
最小奇异值特别小 → 3D 点位置可以飘来飘去 → 噪声一扰动就完全变了 → 不能用!
点击查看代码
#include <iostream>
#include <Eigen/Core>
#include <Eigen/SVD>
using namespace std;
using namespace Eigen;
int main() {
// 随便一个矩阵
MatrixXd A(4, 4);
A << 1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16;
// SVD
auto svd = A.bdcSvd(ComputeFullV);
// 拿出奇异值(已经从大到小排好序了!)
auto s = svd.singularValues();
cout << "奇异值: " << s.transpose() << endl << endl;
// 核心判断!!!
double ratio = s[3] / s[2];
cout << "最小/次小 = " << ratio << endl;
if (ratio < 1e-2) {
cout << "→ 解质量太差,返回 true,扔掉这个点!" << endl;
} else {
cout << "→ 解很好,返回 false,保留这个点!" << endl;
}
return 0;
}
运行结果


浙公网安备 33010602011771号