Svd Armadillo 给出一些 NaN 值
Svd Armadillo give some NaN values
我发现 Armadillo
包可以对图像执行 SVD
。我首先尝试使用 OpenCV
,它非常非常慢。所以现在我正在编写一个使用这个新库执行 SVD
的示例,但我没有得到与 OpenCV
相同的结果。经过一些研究,它似乎与 OpenCV
不再使用但仍被 Armadillo
使用的 Lapack 相关联。所以我在 SVD
计算后重建图像以验证我是否找回了原始图像。使用 OpenCV
没关系,差异接近于 0,但我不知道为什么对于犰狳我有 NaN
数字作为奇异值,所以我无法取回图像。
提前感谢您help/advice可以带来的任何东西。
我的 C++ 代码:
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 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
dc
模式无法正常工作,但 std
模式可以。也许 Lapack 库在 dc
模式下出了点问题。
我发现 Armadillo
包可以对图像执行 SVD
。我首先尝试使用 OpenCV
,它非常非常慢。所以现在我正在编写一个使用这个新库执行 SVD
的示例,但我没有得到与 OpenCV
相同的结果。经过一些研究,它似乎与 OpenCV
不再使用但仍被 Armadillo
使用的 Lapack 相关联。所以我在 SVD
计算后重建图像以验证我是否找回了原始图像。使用 OpenCV
没关系,差异接近于 0,但我不知道为什么对于犰狳我有 NaN
数字作为奇异值,所以我无法取回图像。
提前感谢您help/advice可以带来的任何东西。
我的 C++ 代码:
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 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
dc
模式无法正常工作,但 std
模式可以。也许 Lapack 库在 dc
模式下出了点问题。