Skip to content

Feature request: eigenNonSymmetric() with complex eigenvalues #16298

@catree

Description

@catree

Current eigenNonSymmetric() function does not seem to support real square matrix with complex eigenvalues.
Checking that a real matrix has complex eigenvalues seems to be not trivial, see.

Example in Numpy/Scipy (from Matlab doc):

from __future__ import print_function
import numpy as np
from scipy.linalg import eig

A = np.matrix([[1, 2, 3],
               [3, 1, 2],
               [2, 3, 1]])
w, v = eig(A)
print('A:\n', A)
print('v:', v)
print('w:', w)

gives:

A:
 [[1 2 3]
 [3 1 2]
 [2 3 1]]
v: [[-0.57735027+0.j   0.28867513-0.5j  0.28867513+0.5j]
 [-0.57735027+0.j  -0.57735027+0.j  -0.57735027-0.j ]
 [-0.57735027+0.j   0.28867513+0.5j  0.28867513-0.5j]]
w: [ 6.0+0.j        -1.5+0.8660254j -1.5-0.8660254j]

In OpenCV:

      Matx33d m(
          1, 2, 3,
          3, 1, 2,
          2, 3, 1);
      Mat eigenvalues, eigenvectors;
      try
      {
          cv::eigenNonSymmetric(m, eigenvalues, eigenvectors);
          std::cout << "m:\n" << m << std::endl;
          std::cout << "eigenvalues:\n" << Mat(eigenvalues.t()) << std::endl;
          std::cout << "eigenvectors:\n" << eigenvectors << std::endl;
      }
      catch (const cv::Exception& e)
      {
          std::cerr << "eigenNonSymmetric no conv: " << e.what() << std::endl;
      }
      catch (...)
      {
          std::cerr << "Unknown exception has been raised" << std::endl;
      }

gives:

m:
[1, 2, 3;
 3, 1, 2;
 2, 3, 1]
eigenvectors:
[0.577350269189626, 0.5773502691896255, 0.577350269189626;
 0.7316804540966678, -0.6796598963166424, -0.05202055778002566;
 0.3623677410581142, 0.4524699901711914, -0.8148377312293055]
eigenvalues:
[6.000000000000004, -1.5, -1.5]

Possible feature implementation would be to use ?GEEV LAPACK routine to compute the eigenvalues and eigenvectors of a general square matrix. So a fallback would be needed when OpenCV is not built with LAPACK support, something like a reference LAPACK implementation?
Output would be something like CV_64FC2 to handle complex values? Or CV_64FC2 only when values are complex to keep the previous behavior?

See DGEEV doc.
See numpy.linalg.eig doc and corresponding source code.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions