Fabiobreo
Fabiobreo

Reputation: 278

How to read vector<vector<Point3f> > from xml file with filestorage

I was wondering if it was possible to load a vector of vector of Point2f from an xml file, using the cv::FileStorage class.

This is what I tried for saving:

filestorage  << "ObjPoints" << "{";
for (int i = 0; i < objPoints.size(); ++i)
{
    Mat outMat(objPoints[i]);
    filestorage << "ObjPoints_" + IntToString(i) << outMat;
}
filestorage << "}";

And this is for loading:

FileNode k = n["ObjPoints"];
int i = 0;
for (FileNodeIterator it = k.begin(); it!=k.end(); ++it)
{
    Mat inMat;
    k["ObjPoints_" + IntToString(i)] >> inMat;
    vector<Point3f> tmp = Mat_<Point3f>(inMat);
    ++i;
    objPoints.push_back(tmp);
}

Where objPoints is a vector< vector< Point3f > > and IntToString is defined as follow:

string IntToString(int number)
{
  stringstream ss;
  ss << number;
  return ss.str();
}

Can anyone point me in the right direction? Thanks.

Upvotes: 3

Views: 2420

Answers (1)

Miki
Miki

Reputation: 41775

You can use FileNodes to iterate over each vector, and over each point. It's easier to show than to explain:

#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;

int main(){

    {
        // Write

        vector<vector<Point3f>> v{
            { { 1, 0, 0 }, { 1, 0, 1 }, { 1, 0, 2 } },
            { { 2, 0, 0 } },
            { { 3, 0, 0 }, { 3, 0, 1 } },
        };


        FileStorage fs("test.xml", FileStorage::WRITE);
        fs << "data" << "[";
        for (int i = 0; i < v.size(); ++i)
        {
            // Write each vector
            fs << "[:";
            for (int j = 0; j < v[i].size(); ++j)
            {
                // Write each point
                fs << "[:" << v[i][j].x << v[i][j].y << v[i][j].z << "]";  // Or use: fs << v[i][j];
            }
            fs << "]"; // close vector
        }
        fs << "]"; // close data
    }


    // Read

    vector<vector<Point3f>> v;

    FileStorage fs("test.xml", FileStorage::READ);

    FileNode data = fs["data"];
    for (FileNodeIterator itData = data.begin(); itData != data.end(); ++itData)
    {
        // Read each vector
        vector<Point3f> vv;

        FileNode pts = *itData;
        for (FileNodeIterator itPts = pts.begin(); itPts != pts.end(); ++itPts)
        {
            // Read each point
            FileNode pt = *itPts;

            Point3f point;
            FileNodeIterator itPt = pt.begin();
            point.x = *itPt; ++itPt;
            point.y = *itPt; ++itPt;
            point.z = *itPt;

            vv.push_back(point);
        }
        v.push_back(vv);
    }

    return 0;
}

Your XML will look like:

<?xml version="1.0"?>
<opencv_storage>
<data>
  <_><_>
      1. 0. 0.</_>
    <_>
      1. 0. 1.</_>
    <_>
      1. 0. 2.</_></_>
  <_><_>
      2. 0. 0.</_></_>
  <_><_>
      3. 0. 0.</_>
    <_>
      3. 0. 1.</_></_></data>
</opencv_storage>

Or in YAML like:

%YAML:1.0
data:
   - [ [ 1., 0., 0. ], [ 1., 0., 1. ], [ 1., 0., 2. ] ]
   - [ [ 2., 0., 0. ] ]
   - [ [ 3., 0., 0. ], [ 3., 0., 1. ] ]

Upvotes: 1

Related Questions