1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

core: cv::eigenNonSymmetric() via EigenvalueDecomposition

This commit is contained in:
Alexander Alekhin
2017-09-30 11:55:13 +00:00
parent a9effeeb35
commit 529632f8d0
3 changed files with 219 additions and 27 deletions
+77 -24
View File
@@ -863,45 +863,49 @@ private:
d = alloc_1d<double> (n);
e = alloc_1d<double> (n);
ort = alloc_1d<double> (n);
// Reduce to Hessenberg form.
orthes();
// Reduce Hessenberg to real Schur form.
hqr2();
// Copy eigenvalues to OpenCV Matrix.
_eigenvalues.create(1, n, CV_64FC1);
for (int i = 0; i < n; i++) {
_eigenvalues.at<double> (0, i) = d[i];
try {
// Reduce to Hessenberg form.
orthes();
// Reduce Hessenberg to real Schur form.
hqr2();
// Copy eigenvalues to OpenCV Matrix.
_eigenvalues.create(1, n, CV_64FC1);
for (int i = 0; i < n; i++) {
_eigenvalues.at<double> (0, i) = d[i];
}
// Copy eigenvectors to OpenCV Matrix.
_eigenvectors.create(n, n, CV_64FC1);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
_eigenvectors.at<double> (i, j) = V[i][j];
// Deallocate the memory by releasing all internal working data.
release();
}
catch (...)
{
release();
throw;
}
// Copy eigenvectors to OpenCV Matrix.
_eigenvectors.create(n, n, CV_64FC1);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
_eigenvectors.at<double> (i, j) = V[i][j];
// Deallocate the memory by releasing all internal working data.
release();
}
public:
EigenvalueDecomposition()
: n(0), cdivr(0), cdivi(0), d(0), e(0), ort(0), V(0), H(0) {}
// Initializes & computes the Eigenvalue Decomposition for a general matrix
// given in src. This function is a port of the EigenvalueSolver in JAMA,
// which has been released to public domain by The MathWorks and the
// National Institute of Standards and Technology (NIST).
EigenvalueDecomposition(InputArray src) {
compute(src);
EigenvalueDecomposition(InputArray src, bool fallbackSymmetric = true) {
compute(src, fallbackSymmetric);
}
// This function computes the Eigenvalue Decomposition for a general matrix
// given in src. This function is a port of the EigenvalueSolver in JAMA,
// which has been released to public domain by The MathWorks and the
// National Institute of Standards and Technology (NIST).
void compute(InputArray src)
void compute(InputArray src, bool fallbackSymmetric)
{
CV_INSTRUMENT_REGION()
if(isSymmetric(src)) {
if(fallbackSymmetric && isSymmetric(src)) {
// Fall back to OpenCV for a symmetric matrix!
cv::eigen(src, _eigenvalues, _eigenvectors);
} else {
@@ -930,11 +934,60 @@ public:
~EigenvalueDecomposition() {}
// Returns the eigenvalues of the Eigenvalue Decomposition.
Mat eigenvalues() { return _eigenvalues; }
Mat eigenvalues() const { return _eigenvalues; }
// Returns the eigenvectors of the Eigenvalue Decomposition.
Mat eigenvectors() { return _eigenvectors; }
Mat eigenvectors() const { return _eigenvectors; }
};
void eigenNonSymmetric(InputArray _src, OutputArray _evals, OutputArray _evects)
{
CV_INSTRUMENT_REGION()
Mat src = _src.getMat();
int type = src.type();
size_t n = (size_t)src.rows;
CV_Assert(src.rows == src.cols);
CV_Assert(type == CV_32F || type == CV_64F);
Mat src64f;
if (type == CV_32F)
src.convertTo(src64f, CV_32FC1);
else
src64f = src;
EigenvalueDecomposition eigensystem(src64f, false);
// EigenvalueDecomposition returns transposed and non-sorted eigenvalues
std::vector<double> eigenvalues64f;
eigensystem.eigenvalues().copyTo(eigenvalues64f);
CV_Assert(eigenvalues64f.size() == n);
std::vector<int> sort_indexes(n);
cv::sortIdx(eigenvalues64f, sort_indexes, SORT_EVERY_ROW | SORT_DESCENDING);
std::vector<double> sorted_eigenvalues64f(n);
for (size_t i = 0; i < n; i++) sorted_eigenvalues64f[i] = eigenvalues64f[sort_indexes[i]];
Mat(sorted_eigenvalues64f).convertTo(_evals, type);
if( _evects.needed() )
{
Mat eigenvectors64f = eigensystem.eigenvectors().t(); // transpose
CV_Assert((size_t)eigenvectors64f.rows == n);
CV_Assert((size_t)eigenvectors64f.cols == n);
Mat_<double> sorted_eigenvectors64f((int)n, (int)n, CV_64FC1);
for (size_t i = 0; i < n; i++)
{
double* pDst = sorted_eigenvectors64f.ptr<double>((int)i);
double* pSrc = eigenvectors64f.ptr<double>(sort_indexes[(int)i]);
CV_Assert(pSrc != NULL);
memcpy(pDst, pSrc, n * sizeof(double));
}
sorted_eigenvectors64f.convertTo(_evects, type);
}
}
//------------------------------------------------------------------------------
// Linear Discriminant Analysis implementation