【问题标题】:How to read and write parameters of algorithms from xml/yml files in OpenCV3如何在 OpenCV3 中从 xml/yml 文件中读取和写入算法参数
【发布时间】:2016-07-09 10:59:36
【问题描述】:

我正在尝试从 OpenCV3 中的 YAML 文件中读取特征检测器的参数(例如:SIFT)。

我正在尝试使用Documentation 中的提议代码。但它根本不编译。所以,我让它编译,稍微改变一下

#include "opencv2/opencv.hpp"
#include <opencv2/core/persistence.hpp>
#include "opencv2/xfeatures2d.hpp"
using namespace cv::xfeatures2d;


int main () {

  cv::Ptr<cv::Feature2D> surf = SURF::create();
  cv::FileStorage fs("../surf_params.yaml", cv::FileStorage::WRITE);

  if( fs.isOpened() ) // if we have file with parameters, read them
  {
      std::cout << "reading parameters" << std::endl;

      surf->read(fs["surf_params"]);
  }
  else // else modify the parameters and store them; user can later edit the file to use different parameters
  {
      std::cout << "writing parameters" << std::endl;
      cv::Ptr<cv::xfeatures2d::SURF> aux_ptr;
      aux_ptr = surf.dynamicCast<cv::xfeatures2d::SURF>();
      aux_ptr->setNOctaves(3); // lower the contrast threshold, compared to the default value
      {
          cv::internal::WriteStructContext ws(fs, "surf_params", CV_NODE_MAP);
          aux_ptr->write(fs);
      }
  }
  fs.release();

//  cv::Mat image = cv::imread("myimage.png", 0), descriptors;
//  std::vector<cv::KeyPoint> keypoints;
//  sift->detectAndCompute(image, cv::noArray(), keypoints, descriptors);

return 0;

} 

但是参数根本不被读取或写入。

我还检查了这个Transition Guide,并在“算法接口”部分说:

一般算法的使用模式已经改变:现在它必须在堆上创建,包裹在智能指针 cv::Ptr 中。 2.4 版允许直接或通过智能指针进行堆栈和堆分配。

get 和 set 方法已与 CV_INIT_ALGORITHM 宏一起从 cv::Algorithm 类中删除。在 3.0 中,所有属性都已转换为 getProperty/setProperty 纯虚方法对。因此无法按名称创建和使用 cv::Algorithm 实例(使用通用 Algorithm::create(String) 方法),应显式调用相应的工厂方法。

这可能意味着无法使用 read() 和 write() 函数从 XML/YAML 文件中读取和写入参数。

你能告诉我如何从 OpenCV3 中的 XML/YAML 文件中读取特征检测器算法的参数吗?

提前致谢!

【问题讨论】:

  • 检查this
  • 感谢重播。我尝试了答案,但没有奏效。我在找到的原始问题中添加了更多信息。
  • 尝试以 READ 模式读取文件
  • 我尝试了 READ,但都没有用:S 我很确定这是一个不再可用的功能。

标签: c++ xml opencv yaml opencv3.0


【解决方案1】:

如果特定算法覆盖了 cv::Algorithm::readcv::Algorithm::write 方法,那么您可以按照说明使用 then,例如 here

但是,cv::xfeatures2d::SURF 不会覆盖这些方法,因此您不能使用这种方法。

但是,您可以将需要修改的属性存储在 FileStorage 中,像往常一样读写它们,然后修改 SURF 对象:

#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
#include <iostream>

int main() 
{
    cv::Ptr<cv::Feature2D> surf = cv::xfeatures2d::SURF::create();

    {
        // Try to read from file
        cv::FileStorage fs("surf_params.yaml", cv::FileStorage::READ);
        if (fs.isOpened()) 
        {
            std::cout << "reading parameters" << std::endl;

            // Read the parameters
            int nOctaves = fs["nOctaves"];
            surf.dynamicCast<cv::xfeatures2d::SURF>()->setNOctaves(nOctaves);
        }
        else 
        {
            // Close the file in READ mode
            fs.release();

            // Open the file in WRITE mode
            cv::FileStorage fs("surf_params.yaml", cv::FileStorage::WRITE);

            std::cout << "writing parameters" << std::endl;

            fs << "nOctaves" << 3;

            // fs in WRITE mode automatically released
        }
        // fs in READ mode automatically released
    }
}

您可以将 surf 对象设为指向 cv::xfeatures2d::SURF 的指针以避免强制转换:

cv::Ptr<cv::xfeatures2d::SURF> surf = ...

如果你需要支持不同的Features2D,你可以在FileStorage中也存储一个特定功能的标识符,例如:

 fs << "Type" << "SURF";

然后有条件地读取选项来恢复其属性:

 string type;
 FileNode fn_type = fs.root();
 type = fn_type["Type"];

 if(type == "SURF") {
     // Read SURF properties...
 } else if(type == "SIFT") {
     // Read SIFT properties...
 }

【讨论】:

  • 谢谢三木!你证实了我的想法。因此,不可能以一般方式从 XML/YML 文件中读取参数。我会使用你提出的答案。
  • 其实我并没有调查这是一个缺失的功能,还是一个设计选择。无论如何,解决方法很容易。很高兴它有帮助;D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-04
  • 2015-06-12
相关资源
最近更新 更多