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;
}
运行结果

image

在公式 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;
}

运行结果

image

posted @ 2026-04-09 11:01  阳光天气  阅读(2)  评论(0)    收藏  举报