Ask Your Question
0

Singular Value Decomposition (SVD) with opencv

asked 2018-09-10 05:05:28 -0600

Digital Design gravatar image

updated 2018-09-10 05:27:36 -0600

berak gravatar image

Hi, I am using SVD for my algorithm and the decomposition is done by this instruction:

const int N= 16;
Mat x= (Mat_<double>(N, N)<< 23, 24, 24, 23, 22.5, 21.5, 20, 20, 19, 20, 22, 23,    23, 23.5, 24, 25.5,
        23.5, 24, 23, 21, 21, 22, 21, 20, 18.5, 18, 19, 20, 20.5, 23, 24, 24,
        24, 24, 22, 21, 21.5, 21.5, 21, 20, 19.5, 20, 21, 21, 22, 23, 24, 24,
        24.5, 24, 23, 23, 23, 21, 20, 20, 20, 22, 22, 22, 23, 23, 24, 24,
        24, 24, 24, 24, 24, 22, 20, 20, 20, 21, 21, 21, 21, 22, 24, 24,
        24, 24.5, 25, 24.5, 24, 22, 20, 21, 21, 21, 22, 22, 22, 23, 24, 24,
        24, 24.5, 25, 24.5, 24, 22, 20, 22, 23, 23, 24, 24, 23, 22, 22.5, 23,
        24.5, 24.5, 24, 24, 23, 22, 22, 23, 24.5, 24.5, 23, 21.5, 21, 21, 22.5, 22.5,
        23.5, 24.5, 25.5, 25, 23.5, 24.5, 26, 25.5, 24, 25, 22.5, 20.5, 20.5, 21, 21, 20.5,
        24.5, 25.5, 26, 25.5, 24.5, 25, 25.5, 25, 24, 24, 22, 20.5, 20.5, 19.5, 18.5, 19.5,
        25.5, 25.5, 26, 26, 25, 25, 25, 25, 23.5, 24, 22, 20, 20, 19.5, 18.5, 21,
        24, 24, 24, 24, 24, 24.5,   23, 22.5, 24, 24.5, 23, 20.5, 20, 20, 20.5, 22.5,
        24, 24, 24, 24, 24, 24, 23, 22.5, 24, 23.5, 23, 21.5, 20, 19.5, 22, 24,
        22.5, 23, 22.5, 22, 23, 23, 22, 21.5, 23, 22, 22, 22, 20, 20.5, 23, 24,
        22.5, 21.5, 21.5, 22, 23, 24, 22.5, 20, 21, 20.5, 20.5, 22, 22, 23, 23.5, 23.5,
        22.5, 21, 21, 21, 21, 23, 21.5, 20, 20, 20.5, 20.5, 22, 24, 24, 23.5, 23.5);
Mat Sigma= Mat::zeros(N, N, CV_64FC1);
Mat S, U, VT, x_hat, err;  
int minLoc[2], maxLoc[2];
double minVal, maxVal;
SVDecomp(x, S, U, VT, cv::SVD::FULL_UV);
/*Please note that S is a column vector and S should be a square diagonal matrix, Assigning the components of the S    to the diagonal components of Sigma*/
x_hat= U * Sigma* VT;
cout<< "U * Sigma* VT= "<< endl<< x_hat<< endl;
absdiff(x, x_hat, err);

And the error is really huge!!! (Terminal output)

Reconstruction err: MIN= 0.00135955, MAX= 2.99473, sum= [176.076, 0, 0, 0]

Which is shit! The whole process is done very straight forward with matlab. What's wrong with opencv SVD? Why does the operation loon irreversible?!!!! Your advices are highly appreciated.

minMaxIdx(err, &minVal, &maxVal, minLoc, maxLoc);
cout<< "Reconstruction err: MIN= "<< minVal<< ", MAX= "<< maxVal<< ", sum= "<< ...
(more)
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
0

answered 2018-09-10 08:14:09 -0600

LBerger gravatar image

updated 2018-09-10 08:14:40 -0600

Try this :

     SVDecomp(x, S, U, VT, cv::SVD::FULL_UV);
     /*Please note that S is a column vector and S should be a square diagonal matrix, Assigning the components of the S    to the diagonal components of Sigma*/
     for (int i = 0; i < VT.rows; i++)
         VT.row(i) = VT.row(i) * S.at<double>(i, 0);
     x_hat = U * VT;
     cout << "U * Sigma* VT= " << endl << x_hat << endl;
     absdiff(x, x_hat, err);
     minMaxIdx(err, &minVal, &maxVal, minLoc, maxLoc);
     cout << "Reconstruction err: MIN= " << minVal << ", MAX= " << maxVal << ", sum= " << sum(err) << endl;

and it is not Sigma.at<double>(i1, i1) but S.at<double>(i1,0); results are

U * Sigma* VT=
[23, 24.00000000000001, 23.99999999999999, 23.00000000000001, 22.5, 21.49999999999999, 20.00000000000002, 19.99999999999999, 19, 20, 21.99999999999999, 23, 23, 23.5, 24, 25.5;
 23.50000000000001, 24.00000000000003, 22.99999999999999, 21.00000000000001, 21, 21.99999999999999, 21.00000000000001, 20, 18.5, 18, 18.99999999999999, 20, 20.50000000000001, 23, 24, 24;
 24.00000000000002, 24.00000000000002, 22, 21.00000000000003, 21.5, 21.5, 21.00000000000001, 20, 19.5, 20.00000000000001, 21.00000000000001, 21, 22.00000000000001, 23.00000000000001, 24, 24;
 24.49999999999999, 24, 22.99999999999998, 23.00000000000001, 22.99999999999998, 20.99999999999999, 20.00000000000001, 19.99999999999998, 20, 22, 21.99999999999999, 21.99999999999999, 23, 23, 23.99999999999999, 24;
 24.00000000000001, 24.00000000000002, 24, 24.00000000000001, 24, 22, 20.00000000000002, 20, 20.00000000000001, 21.00000000000001, 21.00000000000001, 21, 21.00000000000001, 22.00000000000001, 24.00000000000001, 24.00000000000001;
 23.99999999999999, 24.5, 24.99999999999998, 24.50000000000001, 23.99999999999998, 21.99999999999999, 20, 20.99999999999999, 21, 21, 21.99999999999999, 22, 22.00000000000001, 22.99999999999999, 24, 24;
 23.99999999999999, 24.5, 24.99999999999998, 24.50000000000001, 23.99999999999999, 21.99999999999999, 20.00000000000002, 21.99999999999999, 23.00000000000001, 23, 24, 23.99999999999999, 23.00000000000001, 22, 22.5, 23;
 24.5, 24.5, 24, 24.00000000000001, 22.99999999999999, 22, 22.00000000000002, 22.99999999999999, 24.5, 24.50000000000001, 23, 21.49999999999999, 21.00000000000001, 21.00000000000001, 22.5, 22.5;
 23.5, 24.5, 25.49999999999998, 25, 23.49999999999999, 24.49999999999999, 26.00000000000001, 25.49999999999999, 24, 25, 22.5, 20.5, 20.5, 21, 21, 20.50000000000001;
 24.5, 25.50000000000002, 25.99999999999999, 25.5, 24.5, 24.99999999999998, 25.5, 24.99999999999999, 24, 24, 21.99999999999998, 20.49999999999999, 20.49999999999999, 19.5, 18.49999999999999, 19.5;
 25.49999999999999, 25.49999999999999, 25.99999999999998, 25.99999999999999, 24.99999999999998, 24.99999999999998, 25, 24.99999999999998, 23.49999999999999, 24, 22, 20, 20.00000000000001, 19.50000000000001, 18.5, 21;
 24, 24, 23.99999999999998, 24.00000000000001, 23.99999999999998, 24.49999999999999, 23, 22.49999999999999, 24, 24.50000000000001, 23, 20.49999999999999, 20.00000000000001, 20.00000000000001, 20.5, 22.5;
 24.00000000000002, 24.00000000000003, 24.00000000000001, 24.00000000000003, 24, 24, 23.00000000000003, 22.5, 24.00000000000002, 23.50000000000001, 23.00000000000001, 21.50000000000002, 20.00000000000003, 19.50000000000003, 22.00000000000002, 24.00000000000002;
 22.5, 23.00000000000001, 22.49999999999998, 22, 22.99999999999999, 22.99999999999999, 22.00000000000001, 21.49999999999999, 23.00000000000001, 22.00000000000001, 22.00000000000001, 22, 20.00000000000001, 20.50000000000001, 23.00000000000001 ...
(more)
edit flag offensive delete link more

Comments

Many thanks for your answer. It works!! Just out of curiosity, why do you multiply each line of VT by corresponding singular value: for (int i = 0; i < VT.rows; i++) VT.row(i) = VT.row(i) * S.at<double>(i, 0); The second question is that I am processing a very huge matrix and I use pointers to access the elements efficiently. Is there a faster way to modify the whole row of VT? Thanks a lot

Digital Design gravatar imageDigital Design ( 2018-09-10 08:28:14 -0600 )edit

because image description

"a very huge matrix "? iteraive method are better. About pointer it's here=efficient way you should use opencv with lapack support

LBerger gravatar imageLBerger ( 2018-09-10 13:50:47 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-09-10 05:05:28 -0600

Seen: 4,049 times

Last updated: Sep 10 '18