在说明前,我也是查了大量文档,弄清楚各个名词的意思,才写下这篇博客。。。

特征值和特征向量:

根据公式:

A是n*n的方阵(必须是方阵),x是特征向量,λ是特征值。

一般情况下,会有n个特征值,和n个特征向量。(这里的一般是指方阵是满秩,各行各列都是线性无关)。

引出问题:如果不是n*n维的矩阵,怎么求?

假设矩阵X是m*n,则可以求矩阵的特征分解。

一般的非方阵的特征分解称为奇异值分解。

奇异值分解(Singular Value Decomposition)是线性代数中一种重要的矩阵分解,奇异值分解则是特征分解在任意矩阵上的推广。在信号处理、统计学等领域有重要应用。

奇异值分解SVD:

A是m*n大小的矩阵

根据公式:

U是左奇异矩阵

同理V是右奇异矩阵

剩下一个S:奇异值矩阵,理论上S的大小应该是m*n才能满足矩阵乘法运算。

=》 =》

理解:, V是单位正交基,不知道的可百度。

理解:,S是奇异值,一般的是n行一列的矩阵,为了方便计算,我们设计S变成对角矩阵,即n*1 =》n*n。

右奇异矩阵举例:

其中V是矩阵的特征向量,   n*n大小

得到奇异值,且S是n列矩阵,V是n*n维,反求左奇异值

  =》 最后得到U是m*n维

左奇异矩阵举例:

其中U是矩阵的特征向量 m*m大小

得到奇异值,且S是m列矩阵,U是m*m维,反求右奇异值

  =》 得到V是n*m维(这里是U的转置)

opencv求SVD:

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;
void main()
{Mat src = imread("1.jpg", IMREAD_GRAYSCALE);Mat src_ = src.clone();src.convertTo(src, CV_64FC1);Mat U, W, V;SVD::compute(src, W, U, V);int set_dim = min(src.rows, src.cols);//cout << "W >> <" << W.rows << "," << W.cols << ">" << endl;//cout << "U >> <" << U.rows << "," << U.cols << ">" << endl;//cout << "V >> <" << V.rows << "," << V.cols << ">" << endl;cout << "W value >> " << W << endl;Mat W_ = Mat(set_dim, set_dim, CV_64FC1, Scalar(0));double ratio = 0.01;int set_rows = set_dim * ratio;for (int i = 0; i < set_rows; i++){W_.at<double>(i, i) = W.at<double>(i, 0);}Mat dst = U * W_ * V;system("pause");
}

opencv里的W,U,V分别对应前文的 S,U,V^T 且维数计算是左奇异矩阵举例的模式。

利用eigen自己实现svd:

详细看注释

void main()
{Mat m = imread("1.jpg", IMREAD_GRAYSCALE);Mat src = m.clone();Mat S, U;m.convertTo(m, CV_64FC1);double t1 = getTickCount();eigen(m * m.t(), S, U); //求出奇异值矩阵 和 左奇异矩阵U = U.t();  //根据公式 U变成转置后的int set_dim = min(src.rows, src.cols);for (int i = 0; i < S.rows; i++){double val = S.at<double>(i, 0);double sq_val = sqrt(val);S.at<double>(i, 0) = sq_val; //λ = sqrt(S)}Mat V;V = m.t() * U; //根据公式for (int i = 0; i < V.cols; i++){for (int j = 0; j < V.rows; j++){V.at<double>(j, i) = V.at<double>(j, i) / S.at<double>(i, 0);}}Mat Vt = V.t();Mat S_ = Mat(S.rows, S.rows, CV_64FC1, Scalar(0));for (int i = 0; i < S.rows; i++)//列向量 变成 对角矩阵{S_.at<double>(i, i) = S.at<double>(i, 0);}dst = U * S_ * Vt;imshow("src", src);imshow("dst", dst);waitKey();}

降维分析:

一直S是对角矩阵,且按降序排列,根据实际测试前10%甚至1%的奇异值就能涵盖99%以上的特征。

可以设置r = ratio * n (ratio:比率)

公式:  (公式1)=》 (公式2)

如果取r = 0.01,降维后公式2维度是公式1 的 亿分之一。

#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;Mat getForeMatrix(int rows, int cols, Mat & img, int type)
{Mat tmp = Mat(rows, cols, type, Scalar(0));for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){if (type == CV_8UC1)tmp.at<uchar>(i, j) = img.at<uchar>(i, j);else if (type == CV_32FC1)tmp.at<float>(i, j) = img.at<float>(i, j);elsetmp.at<double>(i, j) = img.at<double>(i, j);}}return tmp;
}
void main()
{Mat src = imread(filename, IMREAD_GRAYSCALE);Mat src_ = src.clone();src.convertTo(src, CV_64FC1);Mat U, W, V;SVD::compute(src, W, U, V, SVD::Flags::MODIFY_A);double t2 = (getTickCount() - t1) / getTickFrequency();cout << "cost time >> " << t2 << endl;int set_dim = min(src.rows, src.cols);//cout << "W >> <" << W.rows << "," << W.cols << ">" << endl;//cout << "U >> <" << U.rows << "," << U.cols << ">" << endl;//cout << "V >> <" << V.rows << "," << V.cols << ">" << endl;//cout << "W value >> " << W << endl;double ratio = 0.01;int set_rows = set_dim * ratio;Mat W_ = Mat(set_rows , set_rows , CV_64FC1, Scalar(0));for (int i = 0; i < set_rows ; i++){W_.at<double>(i, i) = W.at<double>(i, 0);}Mat U_ = getForeMatrix(set_dim, set_rows , U, CV_64FC1);Mat V_ = getForeMatrix(set_rows , V.cols, V, CV_64FC1);Mat dst = U_ * W_ * V_;system("pause")
}

不正确的希望指出。。。不胜感激

更新错误日志2019.12.23,看了下左奇异矩阵举例:不需要将U转置。且更改了一些定义问题

最后:若要显示最终图像,需要将CV_64FC1图像转成CV_8UC1格式。

OpenCV——相当通俗易懂的SVD奇异值分解相关推荐

  1. svd奇异值分解_SVD(奇异值分解)到底在干什么

    奇异值分解就是在低维空间中寻找最接近原矩阵 的低维矩阵 ,说白了就是数据降维. 奇异值分解是一种十分重要但又难以理解的矩阵处理技术,据人工智能的大牛吴恩达老师所说,在机器学习中是最重要的分解没有之一的 ...

  2. 【数学和算法】最小二乘法,SVD奇异值分解、LU分解的应用场景

    多项式拟合曲线时使用最小二乘法,把问题化简为A*x=B的线性方程组: 然后使用LU矩阵分解算法求解线性方程组A*x=B,具体做法是: 先对矩阵A进行行初等变换得到上三角矩阵U: 再求出下三角矩阵L,就 ...

  3. svd奇异值分解_Lecture 28 | 奇异值分解

    01 Singular Value Decomposition 奇异值分解 奇异值分解指任一mxn的矩阵A都可以分解为一个mxm酉矩阵U乘一个mxn对角阵Σ再乘一个nxn酉矩阵V共轭转置的形式. 下面 ...

  4. SVD奇异值分解(理论与C++实现)

    SVD奇异值分解 前言 理论推导 部分代码实现 前言   奇异值分解(singular value decomposition,以下简称SVD)是线性代数中一种重要的矩阵分解.SVD将矩阵分解为奇异向 ...

  5. SVD奇异值分解(标题重复率过高)

    本篇为<深度学习>系列博客的第三篇,该系列博客主要记录深度学习相关知识的学习过程和自己的理解,方便以后查阅. 之前在看slam的时候就遇到过SVD但是没有做系统的学习,现在接触到深度学习, ...

  6. 奇异值分解图片压缩_通俗易懂的讲解奇异值分解(SVD)和主成分分析(PCA)

    图片来自Unsplash上的Dave 0.本教程包含以下内容 特征分解 对称矩阵的特征分解 奇异值分解(The Singular Value Decomposition,SVD) 主成分分析(Prin ...

  7. 主成分分析逆变换_通俗易懂的讲解奇异值分解(SVD)和主成分分析(PCA)

    图片来自Unsplash上的Dave 0.本教程包含以下内容 特征分解 对称矩阵的特征分解 奇异值分解(The Singular Value Decomposition,SVD) 主成分分析(Prin ...

  8. Singular Value Decomposition(SVD)--奇异值分解【转】

    奇异值分解是线性代数中一种重要的矩阵分解,在信号处理.统计学等领域有重要应用.奇异值分解在某些方面与对称矩阵或Hermite矩阵基于特征向量的对角化类似.然而这两种矩阵分解尽管有其相关性,但还是有明显 ...

  9. 其他算法-SVD奇异值分解

    目录 SVD原理 特征值分解EVD 奇异值分解SVD SVD的性质 基于Numpy的SVD图像压缩 奇异值分解即 Singular Value Decomposition,简称SVD,SVD广泛应用于 ...

  10. svd奇异值分解_矩阵相乘和奇异值分解(SVD)

    关于矩阵相乘 图1.Trefethen, Lloyd N., and David Bau III. Numerical linear algebra. Vol. 50. Siam, 1997.中关于矩 ...

最新文章

  1. 扁平化职能管理三部曲
  2. 为js和css文件自动添加版本号
  3. #ifdef __cplusplus 的用法(C语言调用c++代码)(extern “C“)
  4. 这款网络排查工具,堪称神器!
  5. 书评:精通Lambda:多核世界中的Java编程
  6. A Star寻路相关资料汇总
  7. 麻省理工学院给研究生的文献阅读方法,简单高效!
  8. pupload 文件分块 php,基于Plupload实现Base64分割的文件上传方案
  9. Docker 遇到swapon failed Operation not permitted
  10. 在哪里编写写php,php扩展编写
  11. 【Linux 4,2021最新Java笔试题及答案
  12. JAVA 基础语法(六)——方法(函数)
  13. 《android开发艺术探索》笔记
  14. 2022年MSI赛程安排时间表 MSI赛事规则
  15. 微信小程序/社区/信息发布小程序/信息类小程序
  16. android涂鸦程序(在图像上绘制)
  17. CCleanner下载安装教程
  18. python:shape和reshape()函数
  19. 屏幕分辨率、屏幕尺寸、屏幕像素、屏幕密度完全解析
  20. 【jsp学籍管理系统——开题报告 分享(仅供参考呀)】

热门文章

  1. latex加下划线_Latex学习系列之粗体、斜体和下划线
  2. 智能插帧,打造丝滑视频体验
  3. w10 桌面计算机垃圾桶,解答win10我的电脑怎么放在桌面
  4. sumif单列求和_excel sumif单条件求和 使用SUMIF函数统计单字段多条件求和的方法...
  5. matlab模板,matlab模板匹配
  6. as常用固定搭配_语法必看:as的几种固定用法
  7. Word中插入分隔线
  8. MySQL 数据归档清理方法
  9. 微信公众号迁移公证书办理流程与条件
  10. 什么是BOM?BOM和DOM的区别