#c #opencv #linear-algebra
Вопрос:
Я пытаюсь получить разложение матрицы по Холески и не могу понять, почему результат не работает. Я пробовал использовать только матрицу идентичности 3×3 и использовать матрицу 2×2, для которой я могу получить разложение в matlab.
Я ссылаюсь на документы здесь
https://docs.opencv.org/master/d8/d0e/group__core__hal__interface__decomp__cholesky.html
Хотя в моей версии bool является возвращаемым значением (не передается по ссылке).
Есть какие-нибудь идеи, почему это не сработает? Я ожидал, что это будет тривиально, так как я решаю Ax=B, где A и B-идентификационная матрица (или пример 2×2), и что данные в mat
after будут либо идентификационной матрицей, либо [0.4538, 0; 0.0004, 0.4834]
для 2×2.
Код-это
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/core/operations.hpp"
int main()
{
// int rows = 2;
// float data[4] = {0.2059, 0.0002, 0.0002, 0.2336};
// cv::Mat mat = cv::Mat(rows, rows, CV_32F, data);
int rows = 3;
cv::Mat mat = cv::Mat::eye(rows, rows, CV_32F);
std::cout << "Have matn" << mat << std::endl;
std::size_t bytes_per_row = sizeof(float)*rows;
cv::Mat mat2 = mat.clone();
bool result = cv::Cholesky(reinterpret_cast<float *>(amp;mat), bytes_per_row, rows, reinterpret_cast<float *>(amp;mat2), bytes_per_row, rows);
std::cout << "Did we succeed?n" << result << std::endl;
std::cout << "Aftern" << mat << std::endl;
}
скомпилирован на моей машине с использованием
« g -std=c 11 test.cpp -o основной `pkg-конфигурация opencv —cflags —библиотеки«
Редактировать
После комментария Фрэнка я изменил способ передачи матриц. Теперь функция возвращает значение true, но не возвращает ожидаемый результат. Основываясь на документации, первая переданная матрица теперь должна указывать на разложение, и, хотя она изменилась, она не является более низкой треугольной, и умножение ее на транспонирование не возвращает исходную матрицу. Я могу изолировать это, передав a в nullptr
качестве второй матрицы (согласно документации). Итак, следующий код
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/core/operations.hpp"
int main()
{
int rows = 2;
float data[4] = {9, 2, 2, 8};
cv::Mat mat = cv::Mat(rows, rows, CV_32F, data);
std::size_t bytes_per_row = sizeof(float)*rows;
std::cout << "Before 1n" << mat << std::endl;
bool result = cv::Cholesky(mat.ptr<float>(), bytes_per_row, rows, nullptr, bytes_per_row, rows);
std::cout << "Did we succeed?n" << result << std::endl;
std::cout << "After 1n" << mat << std::endl;
std::cout << "Does it match?n" << mat*mat.t() << std::endl;
}
Теперь уступает…
Before 1
[9, 2;
2, 8]
Did we succeed?
1
After 1
[0.33333334, 2;
0.66666669, 0.36380345]
Does it match?
[4.1111112, 0.9498291;
0.9498291, 0.57679743]
Ожидаемым решением было бы
3.0000 0
0.6667 2.7487
Который имеет нижнюю треугольную форму и отвечает требованиям к декомпозиции.
В соответствии с другим комментарием я также отправлю запрос на github с открытым резюме.
Комментарии:
1.
reinterpret_cast<float *>(amp;mat)
это абсолютно незаконно. Я не могу сказать на 100% уверен, что это сделает что-то для вас, но вы «вероятно» хотитеmat.ptr<float>()
вместо этого.2. возможно, вам захочется отправить проблему на github opencv и запросить соответствующий API Cholesky, который использует Мат вместо указателей. этот API очень уродлив.