【原】特征/SVD分解(圖像壓縮)/PCA降維簡介


說明:實際上EVD(特征分解)是SVD的一種特殊情況;逆是偽逆的特殊情況?,這在最小二乘當中有應用。

在“8點法”求解本質矩陣當中會有SVD分解,在3D到3D空間轉換中,算法icp有SVD解法。SVD作為一種分解矩陣的方法,

有着廣泛應用。

 

 

一、特征分解(手寫word截圖)

 

 

1 %% Matlab驗證代碼
2 a=[1 2 3;2 1 3;3 3 6]
3 [x,y]=eig(a) %% x矩陣每一列代表 lamda123 對應的特征向量
4 diag(y) %% y矩陣的對角元素是對應特征值lamda123

 

二、 SVD分解和圖像壓縮

 

數學概念;參考:  https://www.cnblogs.com/xugenpeng/p/4839336.html?from=singlemessage&isappinstalled=0

 

 

 

 

 

                 

1 A = [1 2; 0 0; 0 0]
2 [U, S, V] = svd(A);

和手動計算結果一致。

 

圖像壓縮實例

  1 #include<iostream>
  2 using namespace std;
  3 
  4 #include<opencv2/opencv.hpp>
  5 using namespace cv;
  6 
  7 void printMat(Mat& matrix)
  8 {
  9     for (int j = 0; j < matrix.rows; j++)
 10     {
 11         for (int i = 0; i < matrix.cols; i++)
 12         {
 13             cout << matrix.ptr<double>(j)[i] << ", ";
 14         }
 15         cout << endl;
 16     }
 17     cout << endl;
 18 }
 19 
 20 // input:  image : ...
 21 //         radio : 壓縮比率
 22 // ouput:  Mat : 壓縮后的灰度圖
 23 Mat compressJPG(Mat image, double radio)
 24 {
 25     SVD svd_1st(image, SVD::MODIFY_A);
 26     Mat W_ = Mat::zeros(svd_1st.w.rows, svd_1st.w.rows, CV_64F);
 27 
 28     // 壓縮比例:radio = m*n/(r*(m+n+1))
 29     // r = m*n / (radio*(m+n+1))
 30     double m = double(image.rows);
 31     double n = double(image.cols);
 32     double r = m * n/(radio*(m + n + 1));
 33     int r_ = int(r);
 34     if (r_  >= svd_1st.w.rows)
 35     {
 36         cout << "errors in setting radio!" << endl;
 37         return Mat();
 38     }
 39     //for (int i = 0; i < svd_1st.w.rows; i++)
 40     for (int i = 0; i < r_; i++)
 41     {
 42         W_.ptr<double>(i)[i] = svd_1st.w.ptr<double>(i)[0];
 43     }
 44 
 45     Mat image_compressed = svd_1st.u * W_ * svd_1st.vt;
 46     image_compressed.convertTo(image_compressed, CV_8U);
 47     return image_compressed;
 48 }
 49 
 50 int main()
 51 {
 52     // <1> test SVD API of opencv 
 53     Mat A = (Mat_<double>(3, 2) << 1, 2, 0, 0, 0, 0);
 54     cout << "原矩陣 A = " << endl;
 55     printMat(A);
 56     Mat W, U, Vt;
 57     SVD::compute(A,W,U,Vt, SVD::MODIFY_A);
 58 
 59     cout << "奇異值矩陣 W =" << endl;
 60     printMat(W);
 61     cout << "左奇異值矩陣 U =" << endl;
 62     printMat(U); //U是 3X2. rank(U) = 2; to save space, U has's 2 cols.
 63     cout << "右奇異值矩陣(自動轉置) Vt =" << endl;
 64     printMat(Vt);
 65 
 66     // <2> recover the matrix 'A'
 67     Mat W_ = Mat::zeros(W.rows, W.rows, CV_64F); // 構建奇異值(方)矩陣,不保留0行 
 68     for (int i = 0; i < W.rows; i++)
 69     {
 70         W_.ptr<double>(i)[i] = W.ptr<double>(i)[0];
 71     }
 72     Mat A_ = U*W_*Vt;
 73     cout << "恢復之后:" << endl;
 74     printMat(A_);
 75 
 76     //*******************************************************************************************************
 77     // 壓縮圖像例子
 78     // 假設原矩陣 A 是 m x n;奇異值個數為r(也就是rank(A) = r)
 79     // 那么壓縮比例:radio = m*n/(r*(m+n+1))
 80     // 分母分別是 r*m : 左奇異矩陣元素個數; r*n : 右奇異矩陣元素個數;  r: 奇異值矩陣元素個數
 81 
 82     Mat image = imread("2.jpg", 0);
 83     imshow("image", image);
 84     image.convertTo(image, CV_64F);
 85 
 86     Mat image_1st = compressJPG(image, 0.6);
 87     if (!image_1st.empty())
 88     {
 89         imshow("radio = 0.6", image_1st);
 90         imwrite("image_1st.jpg", image_1st);
 91     }
 92     
 93     Mat image_2st = compressJPG(image, 1);
 94     if (!image_2st.empty())
 95     {
 96         imshow("radio = 1", image_2st);
 97         imwrite("image_2st.jpg", image_2st);
 98     }
 99 
100     Mat image_3st = compressJPG(image, 3);
101     if (!image_3st.empty())
102     {
103         imshow("radio = 3", image_3st);
104         imwrite("image_3st.jpg", image_3st);
105     }
106     
107     Mat image_4st = compressJPG(image, 5);
108     if (!image_4st.empty())
109     {
110         imshow("radio = 5", image_4st);
111         imwrite("image_4st.jpg", image_4st);
112     }
113 
114     Mat image_5st = compressJPG(image, 7);
115     if (!image_5st.empty())
116     {
117         imshow("radio = 7", image_5st);
118         imwrite("image_5st.jpg", image_5st);
119     }
120 
121     Mat image_6st = compressJPG(image, 9);
122     if (!image_6st.empty())
123     {
124         imshow("radio = 9", image_6st);
125         imwrite("image_6st.jpg", image_6st);
126     }
127 
128     Mat image_7st = compressJPG(image, 20);
129     if (!image_7st.empty())
130     {
131         imshow("radio = 20", image_7st);
132         imwrite("image_7st.jpg", image_7st);
133     }
134 
135     waitKey(0);    
136     return 1;
137 }

 這里比率設置不正確,返回一個提示!

 

可以看到壓縮比率越大,圖像失真越明顯。

 

 

可以看到壓縮比率增大,圖像體積變小,別小看一張圖減小十幾kb大小,對於視頻網站來講.......毋庸置疑,開源節流!

樓主不是專門研究圖像壓縮的,就不深究了,據說微信能將一張由iphone拍的照片(10Mb左右)壓縮到幾百kb,圖像依然很清晰!

 

 

 

三、PCA降維

參考:https://zhuanlan.zhihu.com/p/21580949

給出PCA的一般數學步驟:

順便給出一道例題:

 

 

 

依據上述步驟,我們來解一道題

 

 

 

 

投影后如圖;

(順便:如果用 特征值 2/5 對應的特征向量作為矩陣P;

可以看到,如果映射到一維數軸上,是有信息丟失的。你看下圖,是主城成分,二維數據映射到一維空間,)

 


 

  工程上,數據維度太高,其中又有許多冗余成分;這樣處理起來效率不高。這時候,我們可以對數據經行降維。

PCA,即:主成成分分析,回想SVD分解圖像壓縮實例。我們保留最大的幾個奇異值,就可以壓縮數據的同時,還能最大化減少信息的損失。同理,通過多種線性變換,我們可以將原始數據降維,往往原始數據對應的協方差矩陣的多個奇異值/特征值中,將最大的幾個值所對應的特征向量作為線性變換矩陣,可以起到降維作用。如上圖,我們便是將最大特征值 2 對應的特征向量 作為矩陣P(P是什么?看上述PCA計算步驟)。你可以看看參考鏈接,另外為了更好理解PCA,你可以去看看有關PCA的應用,參考:

https://blog.csdn.net/HLBoy_happy/article/details/77146012

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM