Search code examples
c++opencveigen3

Read/write Eigen::Matrix with cv::Filestorage


According to the OpenCV Docs, we can use cv::FileStorage to read/write custom data structure from/to config files (XML, YAML, JSON):

#include <opencv2/opencv.hpp>
#include <Eigen/Core>

class MyData { };

static void read(const cv::FileNode& node, MyData& value,
    const MyData& default_value = MyData()) { }

int main()
{
    cv::FileStorage fs;
    MyData md;
    fs["MyData"] >> md;
}

The code above can compile. But if the line class MyData { }; is replaced with using MyData = Eigen::Vector2d;, an error occurs:

/usr/include/opencv4/opencv2/core/persistence.hpp:1281: error: no matching function for call to 'read(const cv::FileNode&, Eigen::Matrix<double, 2, 1>&, Eigen::Matrix<double, 2, 1>)'
In file included from /usr/include/opencv4/opencv2/core.hpp:59,
                 from /usr/include/opencv4/opencv2/opencv.hpp:52,
                 from ../main.cpp:1:
/usr/include/opencv4/opencv2/core/persistence.hpp: In instantiation of 'void cv::operator>>(const cv::FileNode&, _Tp&) [with _Tp = Eigen::Matrix<double, 2, 1>]':
../main.cpp:21:21:   required from here
/usr/include/opencv4/opencv2/core/persistence.hpp:1281:9: error: no matching function for call to 'read(const cv::FileNode&, Eigen::Matrix<double, 2, 1>&, Eigen::Matrix<double, 2, 1>)'
 1281 |     read( n, value, _Tp());
      |     ~~~~^~~~~~~~~~~~~~~~~~

This confuses me a lot. Why Eigen::Matrix doesn't work while a normal custom structure works? Thanks ahead for any help.


Solution

  • The issue is due to the intruduction of namespace, indeed you can get a similar issue with this code:

    #include <opencv2/opencv.hpp>
    
    namespace X 
    {
      struct MyData {};
    }
    
    static void read(const cv::FileNode& node, X::MyData& value,
      const X::MyData& default_value = X::MyData()) { }
    
    int main()
    {
      cv::FileStorage fs;
      X::MyData md;
      fs["MyData"] >> md;
    }
    

    To fix the your compilation error, you need to add the read function inside the same namespace (or cv one):

    #include <opencv2/opencv.hpp>
    #include <Eigen/Core>
    
    using MyData = Eigen::Vector2d;
    
    namespace Eigen //or cv
    {
      static void read(const cv::FileNode& node, MyData& value,
        const MyData& default_value = MyData()) { }
    }
    
    int main()
    {
       cv::FileStorage fs;
       MyData md;
       fs["MyData"] >> md;
    }
    

    The Argument Dependent Lookup (ADL) is looking inside the cv namespace and the namespace where the type is declared in your case the function is in neither of those.