opencv3之SVD

本文详细介绍了OpenCV中SVD奇异值分解的功能与使用方法,包括cv::SVD::compute和cv::SVDecomp两个函数的参数说明及计算原理。通过实例展示了如何进行矩阵分解,并解释了SVD在矩阵运算中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

cv::SVD::compute

static void cv::SVD::compute(InputArraysrc,
OutputArrayw,
OutputArrayu,
OutputArrayvt,
intflags = 0
)

参数:

//A=u*w*vt
src	decomposed matrix
w	calculated singular values
u	calculated left singular vectors
vt	transposed matrix of right singular values
flags	operation flags

flags可以选的参数:

Enumeratorflag
SVD::MODIFY_A1allow the algorithm to modify the decomposed matrix; it can save space and speed up processing. currently ignored.
SVD::NO_UV2indicates that only a vector of singular values w is to be processed, while u and vt will be set to empty matrices
SVD::FULL_UV4when the matrix is not square, by default the algorithm produces u and vt matrices of sufficiently large size for the further A reconstruction; if, however, FULL_UV flag is specified, u and vt will be full-size square orthogonal matrices.
//使用方法
Mat A, w, u, vt;
cv::SVD::compute(A, w, u, vt,SVD::FULL_UV);
cv::SVDecomp(A,w,u,vt,cv::SVD::MODIFY_A | cv::SVD::FULL_UV);

cv::SVDecomp

也是调用的上面函数

void cv::SVDecomp(InputArray src, OutputArray w, OutputArray u, OutputArray vt, int flags)
{
    CV_INSTRUMENT_REGION()

    SVD::compute(src, w, u, vt, flags);
}

SVD计算方法

奇异值分解定义:

有一个m×n的实数矩阵A,我们想要把它分解成如下的形式:
A = U Σ V T A=U\Sigma V^T A=UΣVT
其中UV均为单位正交阵

具体计算可以参考:https://byjiang.com/2017/11/18/SVD/

或者:奇异值分解与应用

主要利用如下性质:
A A T = U Σ V T V Σ T U T = U Σ Σ T U T A T A = V Σ T U T U Σ V T = V Σ T Σ V T AA^T=U\Sigma V^TV\Sigma^TU^T=U\Sigma\Sigma^TU^T\\ A^TA=V\Sigma^T U^TU\Sigma V^T=V\Sigma^T\Sigma V^T\\ AAT=UΣVTVΣTUT=UΣΣTUTATA=VΣTUTUΣVT=VΣTΣVT

Σ Σ T = [ σ 1 2 0 ⋯ 0 0 σ 2 2 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 ⋯ σ m 2 ] , Σ T Σ = [ σ 1 2 0 ⋯ 0 0 σ 2 2 ⋯ 0 ⋮ ⋮ ⋱ ⋮ 0 0 ⋯ σ n 2 ] \Sigma\Sigma^T= \left[ \begin{matrix} \sigma_1^2 & 0 & \cdots & 0 \\ 0 & \sigma_2^2 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \sigma_m^2 \\ \end{matrix} \right], \Sigma^T\Sigma= \left[ \begin{matrix} \sigma_1^2 & 0 & \cdots & 0 \\ 0 & \sigma_2^2 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & \sigma_n^2 \\ \end{matrix} \right] ΣΣT=σ12000σ22000σm2,ΣTΣ=σ12000σ22000σn2

参考

https://docs.opencv.org/3.1.0/d2/de8/group__core__array.html#gab477b5b7b39b370bb03e75b19d2d5109

SVD(奇异值分解)算法及其评估

https://wenku.baidu.com/view/38693ef2e109581b6bd97f19227916888486b916.html?rec_flag=default&sxts=1563780499924

<think>我们使用OpenCV中的SVD类来计算矩阵的奇异值分解。SVD将矩阵分解为三个矩阵:U,S,Vt(其中Vt是V的转置)。具体步骤:1.准备输入矩阵(可以是任意大小,实数或浮点数类型)。2.创建cv::SVD对象,并调用compute方法。3.获取分解后的U、奇异值向量(以1D向量形式存储)和Vt矩阵。4.如果需要,可以将奇异值向量转换为对角矩阵。注意:OpenCVSVD::compute函数有两种调用方式:-方式1:使用SVD对象,调用compute方法,然后通过该对象获取结果。-方式2:直接使用静态函数SVD::compute,将结果存储在提供的矩阵中。以下代码示例将展示两种方法。</think>### OpenCV 中求矩阵 SVD 的实现 奇异值分解(SVD)是线性代数中一种重要的矩阵分解方法,在计算机视觉、机器学习和图像处理中有广泛应用。OpenCV 提供了高效的 SVD 实现,支持各种矩阵类型。 #### SVD 数学原理 对于任意 m×n 矩阵 A,其 SVD 分解为: ``` A = U * Σ * V^T ``` 其中: - U 是 m×m 正交矩阵(左奇异向量) - Σ 是 m×n 对角矩阵(奇异值,按降序排列) - V^T 是 n×n 正交矩阵的转置(右奇异向量) #### OpenCV C++ 实现代码 ```cpp #include <opencv2/core.hpp> #include <opencv2/core/utils/logger.hpp> #include <iostream> int main() { // 禁用OpenCV的日志输出 cv::utils::logging::setLogLevel(cv::utils::logging::LOG_LEVEL_ERROR); // 创建示例矩阵 cv::Mat A = (cv::Mat_<float>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9); std::cout << "原始矩阵 A:\n" << A << std::endl; // 创建SVD对象 cv::SVD svd; // 方法1:使用SVD对象计算 svd(A); // 等价于 svd.compute(A); // 获取分解结果 cv::Mat U = svd.u; // 左奇异向量 cv::Mat S = svd.w; // 奇异值向量 (1xN 或 Nx1) cv::Mat Vt = svd.vt; // 右奇异向量 (已转置) // 将奇异值向量转换为对角矩阵 cv::Mat Sigma = cv::Mat::zeros(A.rows, A.cols, A.type()); for (int i = 0; i < S.rows; i++) { Sigma.at<float>(i, i) = S.at<float>(i); } // 方法2:直接使用静态函数计算 cv::Mat U2, S2, Vt2; cv::SVD::compute(A, S2, U2, Vt2); // 重建原始矩阵验证结果 cv::Mat reconstructed = U * Sigma * Vt; std::cout << "\n左奇异向量 U:\n" << U << std::endl; std::cout << "\n奇异值对角矩阵 Σ:\n" << Sigma << std::endl; std::cout << "\n右奇异向量 Vt:\n" << Vt << std::endl; std::cout << "\n重建矩阵 U*Σ*Vt:\n" << reconstructed << std::endl; // 计算矩阵的秩(非零奇异值数量) int rank = cv::countNonZero(S > 1e-5); std::cout << "\n矩阵的秩: " << rank << std::endl; return 0; } ``` #### 代码解释: 1. **矩阵准备**: - 创建任意大小的输入矩阵(支持 float/double 类型) - 示例使用 3×3 浮点矩阵 2. **SVD 计算方式**: - **对象方式**:创建 `cv::SVD` 对象,调用 `compute()` 方法 - **静态方法**:直接使用 `cv::SVD::compute()` - 两种方法结果等价,对象方式可复用 SVD 对象 3. **结果获取**: - `U`:左奇异向量矩阵 (m×m) - `w`:奇异值向量 (min(m,n)×1) - `vt`:右奇异向量矩阵的转置 (n×n) 4. **奇异值矩阵转换**: - 将向量形式的奇异值转换为对角矩阵 Σ - 使用循环填充对角元素 5. **结果验证**: - 重建矩阵:U * Σ * Vt - 应与原始矩阵近似(考虑浮点误差) 6. **应用示例**: - 计算矩阵秩(非零奇异值数量) - 使用阈值 1e-5 处理浮点误差 #### 高级用法:自定义计算选项 ```cpp // 使用计算前预处理选项 int flags = cv::SVD::FULL_UV; // 计算完整的U和V矩阵 // 方法1:对象方式 cv::SVD svd_full(A, flags); // 方法2:静态方法 cv::Mat U_full, S_full, Vt_full; cv::SVD::compute(A, S_full, U_full, Vt_full, flags); ``` #### 重要参数说明: - **计算标志 (flags)**: - `cv::SVD::MODIFY_A`:允许修改输入矩阵 - `cv::SVD::NO_UV`:不计算 U 和 V 矩阵 - `cv::SVD::FULL_UV`:计算完整的 U 和 V 矩阵 - **浮点精度**: - 对于 double 类型矩阵,使用 `cv::Mat_<double>` - 奇异值阈值应考虑数据类型精度 #### 应用场景: 1. 图像压缩(保留主要奇异值) 2. 主成分分析(PCA) 3. 矩阵秩估计 4. 求解最小二乘问题 5. 图像对齐和配准
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值