I am discovering the Armadillo
package to perform a SVD
on an image. I first try with OpenCV
which is very very slow. So now I am writing an example which perform the SVD
using this new library, and I don't get the same result as OpenCV
. After some researches, it seems to be linked to Lapack which is no longer used by OpenCV
but still by Armadillo
. So I am reconstructing the image after the SVD
computation to verify if I get back the original image. With OpenCV
it is okay, the difference is near to 0, but I don't know why for Armadillo I have NaN
number as singular values so I can't get back an image.
Thank you in advance for any help/advice you can bring.
My C++ code:
int main()
{
// Load the image
cv::Mat img = cv::imread("path/to/the/image.png", 0);
img.convertTo(img, CV_32FC1);
// Convert cv::Mat to arma::fmat
arma::fmat arma_img(reinterpret_cast<float*>(img.data), img.cols, img.rows);
// Check if the image back from armadillo is okay
cv::Mat opencv_img(arma_img.n_cols, arma_img.n_rows, CV_32FC1, arma_img.memptr());
// ------ Perform SVD with OpenCV (2.5s)
cv::SVD svvd;
cv::Mat w1, U1, V1t;
svvd.compute(opencv_img, w1, U1, V1t);
cv::Mat W1 = cv::Mat::zeros(w1.rows, w1.rows, CV_32FC1);
for (int i = 0; i<w1.rows; i++)
{
W1.at<float>(i, i) = w1.at<float>(i);
}
cv::Mat opencv_img_result = U1 * W1 * V1t;
// ------ Perform SVD with Armadillo (0.05s)
arma::fmat U2, V2;
arma::fvec w2;
arma::svd(U2, w2, V2, arma_img);
arma::fmat W2 = arma::zeros<arma::fmat>(arma_img.n_rows, arma_img.n_cols);
for (int i = 0; i < arma_img.n_cols; i++)
{
*(W2.memptr() + i * (1 + arma_img.n_rows)) = *(w2.memptr() + i);
}
arma::fmat arma_img_result = U2 * W2* V2.t();
return 0;
}
The problem is because of the mode of computation:
The method argument is optional; method is either "dc" or "std"
"dc" indicates divide-and-conquer method (default setting) "std" indicates standard method the divide-and-conquer method provides slightly different results than the standard method, but is considerably faster for large
matrices
The dc
mode is not working properly, but the std
one is. Maybe something is wrong on the Lapack library abotu the dc
mode.