Как сделать инверсию на сложной матрице в 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 || type == CV_64F) в инвертированном виде

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

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

5

Решение

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;
}
5

Другие решения

Других решений пока нет …