Eigen library --> initialize matrix with data from file or existing std::vector<string> content (c++)

Viewed 27926

My question is how to initialize an eigen Matrix, but NOT this way:

matrix << 1,0,1,0,
          1,0,1,0,
          1,0,1,0,

I have a Matrix that looks like the above one ( commas or no commas doesnt matter) stored in a txt file.

I already wrote a function to read in each line and put it into a vector now I want to create a matrix with this data

But it doesn' work and I cant find any page that explains how to assign data to a matrix without writing just the values.(like the example above)

All I need is the data from my file in an eigen Matrix

What I tried so far: (PS: had the idea with the iterators but i guess it will take too long with really big matrices, I just tried this example with a 1-2 dimensional matrix)

int readFromFile (const char * path, vector <string> & mv)
{
    fstream file;
    string line;
    file.open(path);

    while (getline(file,line))
    {
        mv.push_back(line);
    }
    file.close();
    return 0;
}


typedef Matrix <int, 1, 2> MyMatrix;

int fromVectoEigen (vector<string> & source, MyMatrix & target)
{   //for (int i = source.size(); i<0 ; i--)
    //{

        string valuerow = source.back();
        string::iterator it = valuerow.begin();
        target.row(0)<< *it;
        target.row(0)<<*it+1;
        //source.pop_back();
    //}

    return 0;
}

Unfortunately cant just say Matrix.row(i) = vector.back() that doesnt work.

8 Answers

I used iterators to collect the data in a vector and then initialize the matrix. The conversion to the vector<double> seem to be the time-consuming part of the method, which approximately has the same speed as the solutions above. Ideas on how to improve this would be interesting.

template <class T>
using Tmat = Eigen::Matrix<T,Dynamic,Dynamic>;

Tmat<double> txt_to_mat(std::string path, int rows, int cols)
{
    std::ifstream fstr(path.c_str());
    std::vector<double> data_vec = std::vector<double>{
        std::istream_iterator<double>(fstr),
        std::istream_iterator<double>()
    };

    Tmat<double> mat(rows, cols);
    for(int i=0; i<rows; i++){
        for(int j=0; j<cols; j++){
            mat(i,j) = data_vec[i*cols + j];
        }
    }

    return mat;
}

A templated stream operator can be used for reading all Eigen dense matrix types from a stream:

#include <Eigen/Dense>
#include <fstream>

template <typename Derived>
std::ifstream& operator>>(std::ifstream& in, Eigen::MatrixBase<Derived>& b)
{
  for(int row = 0; row < b.rows(); ++row)
    for(int col = 0; col < b.cols(); ++col)
      in >> b(row, col);

  return in;
}

This will instantiate for any of Eigen's dense matrix types. Here's an example reading camera intrinsics and extrinsics from a file for Eigen::Matrix3d and Eigen::Vector3d using the above templated stream operator:

std::ifstream input(krtPath);

Eigen::Matrix3d K, R;
Eigen::Vector3d t;

input >> K >> R >> t;

Eigen::Vector3d C = -R.transpose() * t;
Related