Как сделать инверсию сложной матрицы в OpenCV?

У меня проблемы с инверсией сложной матрицы. Насколько мне известно, комплексная матрица - это просто двухканальная матрица (CV_32FC2 / CV_64FC2).

Скажем, у меня есть матрица C:

Mat C(2, 2, CV_64FC2);

C.at<Vec2d>(0,0)[0] = 1;
C.at<Vec2d>(0,0)[1] = 1;
C.at<Vec2d>(0,1)[0] = 3;
C.at<Vec2d>(0,1)[1] = 4;
C.at<Vec2d>(1,0)[0] = 2;
C.at<Vec2d>(1,0)[1] = -1;
C.at<Vec2d>(1,1)[0] = 5;
C.at<Vec2d>(1,1)[1] = 2;

Mat InverseMat;
invert(C, InverseMat, DECOMP_SVD);

После выполнения функции инвертирования я продолжаю получать эту ошибку:

Ошибка OpenCV: утверждение не удалось (тип == CV_32F || тип == CV_64F) в инверте

Функция инвертирования хорошо работает с загруженным изображением в градациях серого (1 канал), но мне трудно сделать инверсию для сложной матрицы, которая содержит действительную и мнимую части.

Подскажите, пожалуйста, как решить обратную задачу сложной матрицы? Предпочтительно использовать метод DECOMP_SVD, поскольку я не могу получить желаемый результат с помощью метода DECOMP_LU или DECOMP_CHOLESKY, когда я пытался с одноканальным изображением, вероятно, из-за вопроса сингулярной матрицы. Спасибо.


person user2223228    schedule 29.03.2013    source источник


Ответы (1)


OpenCV не поддерживает инверсию сложных матриц. Вы должны манипулировать сложной матрицей таким образом, чтобы сформировать реальную матрицу, содержащую действительную и мнимую части комплексной матрицы. На этой странице объясняется процесс.

Вот код для выполнения инверсии сложной матрицы с использованием вышеупомянутого процесса:

//Perform inverse of complex matrix.
cv::Mat invComplex(const cv::Mat& m)
{
    //Create matrix with twice the dimensions of original
    cv::Mat twiceM(m.rows * 2, m.cols * 2, CV_MAKE_TYPE(m.type(), 1));

    //Separate real & imaginary parts
    std::vector<cv::Mat> components;
    cv::split(m, components);

    cv::Mat real = components[0], imag = components[1];

    //Copy values in quadrants of large matrix
    real.copyTo(twiceM({ 0, 0, m.cols, m.rows })); //top-left
    real.copyTo(twiceM({ m.cols, m.rows, m.cols, m.rows })); //bottom-right
    imag.copyTo(twiceM({ m.cols, 0, m.cols, m.rows })); //top-right
    cv::Mat(-imag).copyTo(twiceM({ 0, m.rows, m.cols, m.rows })); //bottom-left

    //Invert the large matrix
    cv::Mat twiceInverse = twiceM.inv();

    cv::Mat inverse(m.cols, m.rows, m.type());

    //Copy back real & imaginary parts
    twiceInverse({ 0, 0, inverse.cols, inverse.rows }).copyTo(real);
    twiceInverse({ inverse.cols, 0, inverse.cols, inverse.rows }).copyTo(imag);

    //Merge real & imaginary parts into complex inverse matrix
    cv::merge(components, inverse);
    return inverse;
}
person sgarizvi    schedule 29.03.2013
comment
Спасибо, дружище, ты сделал мой день. Это работает для матрицы выше. Я попробовал программу с изображением, и она тоже успешно работает. Мне нужно будет дополнительно проанализировать изображение, и теперь я могу перейти к следующему этапу обработки. Спасибо еще раз! - person user2223228; 29.03.2013