使用 cv::Filestorage 读/写 Eigen::Matrix

问题描述

根据OpenCV Docs,我们可以使用cv::FileStorage从/向配置文件(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;
}

上面的代码可以编译。但是如果将 class MyData { }; 行替换为 using MyData = Eigen::Vector2d;,则会出现错误

/usr/include/opencv4/opencv2/core/persistence.hpp:1281: error: no matching function for call to 'read(const cv::FileNode&,Eigen::Matrix<double,2,1>&,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,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&,1>)'
 1281 |     read( n,value,_Tp());
      |     ~~~~^~~~~~~~~~~~~~~~~~

这让我很困惑。为什么 Eigen::Matrix 不起作用而正常的自定义结构有效?在此先感谢您的帮助。

解决方法

问题是由于引入了命名空间,确实你可以用这段代码得到类似的问题:

#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;
}

要修复您的编译错误,您需要在同一个命名空间(或 cv 之一)中添加 read 函数:

#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;
}

Argument Dependent Lookup (ADL) 正在查找 cv 命名空间和在您的情况下声明类型的命名空间,函数不在这两者中。