为啥用 Eigen 和 OpenCV 计算的 SVD 左奇异向量具有不同的符号

Posted

技术标签:

【中文标题】为啥用 Eigen 和 OpenCV 计算的 SVD 左奇异向量具有不同的符号【英文标题】:Why SVD left singular vectors computed with Eigen and OpenCV have different signs为什么用 Eigen 和 OpenCV 计算的 SVD 左奇异向量具有不同的符号 【发布时间】:2015-02-15 06:04:49 【问题描述】:

我同时使用 OpenCV 和 Eigen 来计算 SVD:

Eigen:
JacobiSVD<Matrix3f> svd(myM, ComputeFullU);

OpenCV:
cvSVD(&myM, &w, &u, 0, CV_SVD_MODIFY_A | CV_SVD_U_T);

我专注于左奇异向量:

Eigen result:
 0.0341698  -0.064916   0.997306
  0.950241  -0.307051 -0.0525437
  0.309635   0.949476   0.051194

OpenCV result:
[0.03417001163639093, -0.06491612525262211, 0.9973055233913801;
  -0.9502414121501213, 0.3070511298822651, 0.05254390804810754;
  -0.3096347347112595, -0.9494764348419663, -0.05119404985032185]

尽管一个是float类型,一个是double类型,但是计算出来的左奇异向量有不同的符号。所以我的问题是:

    这种符号差异真的很重要吗? 如何使它们相同?

【问题讨论】:

【参考方案1】:

    不,没关系,因为对应的符号差也会出现在右奇异向量上,所以基本上

    U * S * V^adjoint
    

    会给你正确的结果。

    更准确地说,来自***:

    非退化奇异值总是具有唯一的左和 右奇异向量,最多乘以单位相位因子 exp(iφ)(真实案例待签)。因此,如果 M 的所有奇异 > 值都是非退化且非零的,那么它的奇异值 分解是唯一的,最多将 U 的列乘以 单位相位因子和相应的同时乘法 V的列由相同的单位相位因子。

    为什么要它们相同?如果你真的想要,你可以通过将第一个分量相除得到相位,然后乘以那个相位使它们相等。

    由于奇异值的排序,还可能出现额外的差异,afaik eigen 以降序对它们进行排序,不确定 opencv。

【讨论】:

【参考方案2】:

奇异值分解不是唯一的,有多种可能的分解。实际的奇异值集合是唯一的,但是向量的左右矩阵可以有不同的符号,没有关系,因为多个组合符号可以抵消。

一个明显的例子,对于M = UΣV*,像M=(-U)Σ(-V*) = UΣV* 一样分解,但一般来说,左右奇异向量可以有不同的符号组合。

这种差异并不重要,所以我认为您不必费心尝试使它们相同。

不仅如此,奇异向量的顺序也可以变化。通常是奇异值的降序排列。

【讨论】:

以上是关于为啥用 Eigen 和 OpenCV 计算的 SVD 左奇异向量具有不同的符号的主要内容,如果未能解决你的问题,请参考以下文章

OPENCV 2.4.9 cv2eigen 语义错误

Eigen学习

为啥我的Eigen的速度特别慢

eigen 笔记1

CMakeList.txt里添加OpenCV, Eigen, Ceres, G2O库

为啥我的 Eigen 代码不能随更多线程扩展