c++opencvlinear-algebra

OpenCV 4.5 produces wrong eigen vectors


So I rejoiced in the easy installation of opencv under WSL2 (Windows Subsystem for Linux), Ubuntu:

apt-get install libopencv-dev

Following this up with dpkg -s libopencv-dev | grep Version answered me Version: 4.5.4+dfsg-9Ubuntu4. I am interested in eigen vectors. Nothing evil, real valued eigen values will do nicely (however, complex ones would also be welcome).

I wrote a CMakeLists.txt

cmake_minimum_required(VERSION 3.5)

project(testcv)
find_package( OpenCV REQUIRED )
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(testcv testcv.cpp)
target_link_libraries(testcv ${OpenCV_LIBS})

And the following test program testcv.cpp

#include <iostream>
#include <opencv2/core/mat.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

int main()
{
        float numbers[] =
              { 0, 2,
                1, 0 };
        Mat A = Mat(2,2,CV_32F,numbers);
        Mat eigen_vals, eigen_vecs;
        eigen(A, eigen_vals, eigen_vecs);
        cout << "A: " << A << endl <<
          "eigen_vals: " << eigen_vals << endl <<
          "eigen_vecs: : " << eigen_vecs << endl <<
          "Done." << endl;
        return 0;
}

Finally, saying

cmake .
make
./testcv

got me

A: [0, 2;
 1, 0]
eigen_vals: [0.99999994;
 -0.99999994]
eigen_vecs: : [0.70710677, 0.70710677;
 -0.70710677, 0.70710677]
Done.

Honestly? That is just wrong! For comparison, my octave results:

>> A
A =

   0   2
   1   0

>> lambda
lambda =

Diagonal Matrix

   1.4142        0
        0  -1.4142

>> B
B =

   0.8165  -0.8165
   0.5774   0.5774

>> A*B
ans =

   1.1547   1.1547
   0.8165  -0.8165

What am I doing wrong here, in such a simple call to such a simple interface?


Solution

  • Found my own answer by reading the docs a little closer: https://docs.opencv.org/4.x/d2/de8/group__core__array.html

    bool cv::eigen (InputArray src,
      OutputArray eigenvalues, OutputArray eigenvectors=noArray())
    

    Calculates eigenvalues and eigenvectors of a symmetric matrix.

    Also answering the optional "complex" part of the question (real-valued, symmetric matrices yield real-valued eigenvalues).

    Note: Also be wary that eigenvectors are stored row-wise by cv::eigen(..). So the first row is the first eigenvector.