【问题标题】:OpenCV storing vectors of vectors of points vector<vector<Point> >OpenCV 存储点向量的向量 vector<vector<Point>>
【发布时间】:2012-07-20 17:52:55
【问题描述】:

我正在使用 OpenCV 2.4.2 FileStorage 并尝试以我可以读回的方式存储点向量的向量。最好的方法是什么?

以下是我尝试过的,但读回来会引发错误: OpenCV Error: Unspecified error (The sequence element is not a numerical scalar) in cvReadRawDataSlice, file /Downloads/OpenCV-2.4.2/modules/core/src/persistence.cpp, line 3367

保存:

bool writeVectorVectorPoint(string fname, vector<vector<Point> > vvP)
{
  FileStorage fs(fname, FileStorage::WRITE);
  fs << "nV" << static_cast<int>(vvP.size());
  for(size_t i = 0; i < vvP.size(); i++)
  {
    ostringstream istr;
    istr << "v" << i;
    fs << istr.str() << "[";
    for(size_t jj = 0; jj < vvP.at(i).size(); jj++)
    {
      ostringstream jjstr;
      fs << vvP.at(i).at(jj);
    }
    fs << "]";
  }
  fs.release();
  return(true);
}

阅读:

FileStorage fs(argv[2], FileStorage::READ);
if(!fs.isOpened())
{
  cout << "Unable to open: " << argv[2] << endl;
  return(-1);
}
int nV = static_cast<int>(fs["nV"]);
cout << "nV: " << nV << endl;
vector<Point> vPts;
for(int ii = 0; ii < nV; ii++)
{
  ostringstream iistr;
  iistr << "v" << ii;
  cout << iistr.str() << ": ";
  fs[iistr.str()] >> vPts;
  cout << endl;
}
fs.release();

xml 文件如下所示:

<?xml version="1.0"?>
<opencv_storage>
<nV>4</nV>
<v0>
  <_>
    269 490</_>
  <_>
    400 522</_>
  <_>
    331 600</_>
  <_>
    294 610</_></v0>
<v1>
  <_>
    537 510</_>
  <_>
    590 458</_>
  <_>
    603 612</_>
  <_>
    508 626</_></v1>
<v2>
  <_>
    594 287</_>
  <_>
    444 240</_></v2>
<v3>
  <_>
    451 330</_>
  <_>
    632 342</_>
  <_>
    652 344</_>
  <_>
    470 381</_></v3>
</opencv_storage>

【问题讨论】:

    标签: opencv vector


    【解决方案1】:

    有点晚了: 一个类似的更简单的例子,带有向量的向量:

    编写函数,每次添加一个不同名称的节点(仅供参考):

    void writeVectorOfVector(FileStorage &fs, string name, vector<vector<Point2f>> &vov)
    {
        fs << name;
        fs << "{";
        for (int i = 0; i < vov.size(); i++)
        {
            fs << name + "_" + to_string(i);
            vector<Point2f> tmp = vov[i];
            fs << tmp;
        }
        fs << "}";
    }
    

    读取函数,使用 FileNodeIterator 读取每个向量 并将其推回向量的向量:

    void readVectorOfVector(FileNode &fns, string name, vector<vector<Point2f>> &vov)
    {
        vov.clear();
        FileNode fn = fns[name];
        if (fn.empty()){
            return;
        }
    
        FileNodeIterator current = fn.begin(), it_end = fn.end(); // Go through the node
        for (; current != it_end; ++current)
        {
            vector<Point2f> tmp;
            FileNode item = *current;
            item >> tmp;
            vov.push_back(tmp);
        }
    }
    

    使用 OpenCV 2.4.8/C++/Vs2013 测试。

    希望这能简化您的代码。

    【讨论】:

    • readVectorOfVector 函数的第一个参数应该是 FileStorage &fs,而不是 FileNode &fns,对吗?然后读取节点将是: FileNode fn = fs[name];
    【解决方案2】:

    目前,我通过不使用 OpenCV 的 FileStorage 解决了这个问题。这是我为存储 Point 向量的向量所做的,因为有很好的打印向量的例程。

    bool writeVectorVectorPoint(string fname, vector<vector<Point> > vvP)
    {
      ofstream fsOut;
      vector<vector<Point> >::iterator p;
    
      fsOut.open(fname.c_str());
      if(fsOut.fail())
      {
        cout << "Failed to open " << fname << endl;
        return(false);
      }
      for(p = vvP.begin(); p != vvP.end(); p++)
      {
        fsOut << (*p) << endl;
      }
      fsOut.close();
      return(true);
    }
    

    重新读取它们有点复杂,但仍然不难。如果有人看到任何优化,请告诉我,因为我怀疑有更好(或至少更优雅)的解决方案。

    bool readVectorVectorPoint(string fname, vector<vector<Point> >& vvP)
    {
      ifstream fsIn;
      fsIn.open(fname.c_str());
      if(fsIn.fail())
      {
        cout << "Failed to open: " << fname << endl;
        return(false);
      }
      Point pt;
      vector<Point> vPt;
      vector<Point>::iterator p;
      string line;
      while(getline(fsIn, line))
      {
        cout << line << endl;
        string ptStr;
        stringstream s(line.substr(1,line.size()-1));
        vPt.clear();
        while(getline(s, ptStr, ';'))
        {
          stringstream s1(ptStr);
          string lastStr;
          getline(s1, lastStr, ',');
          pt.x = atoi(lastStr.c_str());
          getline(s1, lastStr, ',');
          pt.y = atoi(lastStr.c_str());
          vPt.push_back(pt);
        }
        vvP.push_back(vPt);
      }
    
      fsIn.close();
      return(true);
    }
    

    【讨论】:

      【解决方案3】:

      在我的情况下,我使用这个解决方案来读取一个向量 o KeyPoints 和一个基于 bloublo 答案的 Mat
      我正在使用 opencv 2.4.9

         FileNodeIterator current = fn.begin(), it_end = fn.end(); // Go through the node
         for (; current != it_end; ++current)
         {
          vector<KeyPoint> kp;
          Mat desc;
          FileNode item = *current;
          read(item,kp);
      
          ++current;
          item = *current;
          item >> desc;
          ...
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-22
        • 2011-10-24
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-23
        • 2011-06-14
        相关资源
        最近更新 更多