Pregunta

I have trouble in doing inverse of a complex matrix. As far as I know, complex matrix is simply a two-channel matrix (CV_32FC2 / CV_64FC2).

Let's say I have a matrix 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);

After I perform the invert function, I keep getting this error:

OpenCV Error: Assertion failed (type == CV_32F || type == CV_64F) in invert

The invert function works well with a grayscale loaded image (1 channel), but I have hard time to do inverse on complex matrix which contains real and imaginary part.

Can someone please tell me how to solve the inverse problem of a complex matrix? Preferably using DECOMP_SVD method, as I can't get desired result using DECOMP_LU or DECOMP_CHOLESKY method when I tried with a single channel image, probably because of the matter of singular matrix. Thanks.

¿Fue útil?

Solución

OpenCV does not support inversion of complex matrices. You have to manipulate the complex matrix in a way to form a real matrix containing the real and imaginary parts of the complex matrix. This page explains the process.

Here is the code to perform inverse of a complex matrix using the above mentioned process:

//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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top