Eigen::MatrixXd to flann::Matrix<double> conversion
Asked Answered
D

2

7

Assume that mat below is of type Eigen::MatrixXd and already contains some data. In an attempt to avoid duplicating memory, I tried to instantiate a flann::Matrix<double> object from the pointer to the raw memory chunk allocated by Eigen3:

flann::Matrix<double> input(const_cast<double *>(mat.data(), mat.rows(), mat.cols())

However, my algorithm outputs garbage, but is just fine with the ugly:

flann::Matrix<double> input(new double[mat.rows()*mat.cols()], mat.rows(),  mat.cols());
for (int i = 0; i  < mat.rows(); i++) {
for (int j = 0; j < mat.cols(); j++) {
  input[i][j] = mat(i, j);
}

}

I investigated the option to subclass the base Matrix_ type from flann to create an adaptor to Eigen3 matrices. The problem though is that Matrix_ relies on the implementation of the [] operator in its interace. It makes me feel that I might encounter the same memory issue than in the simple (but broken) solution shown above.

What do you think could explain such behaviour ?

Dannica answered 20/11, 2012 at 2:49 Comment(0)
D
7

I also got confirmation from Marius Muja, the author of libflann, that flann::Matrix stores in row-major order whereas Eigen uses column-major by default. Here's the answer that he gave me by email:

The problem is most likely the fact that Eigen stores matrices in column-major order > while FLANN requires them in row-major order.

A solution would be to use Matrix<double, Dynamic, Dynamic, RowMajor> instead of MatrixXd, then FLANN and Eigen matrices can share the same memory, otherwise a copy will be needed. Marius Muja

Dannica answered 26/11, 2012 at 19:33 Comment(1)
I had the same problem with nanoFLANN (although it worked in both ways but the default Column-Major was very clumsy for my application), thanks!Rhapsody
L
1

Eigen::Matrix store data continously, so you shouldn't get stride problems. Alignment may be the problem if you are trying to construct an Eigen::Matrix on it (but I can't imagine how this is possible). By default Eigen::Matrix is column-major, this may be your problem. I don't know how flann treat matrices, if they are row-major, then that's it. The following example work with Eigen::Matrix< double, -1, -1, Eigen::RowMajor > for mat and fails with Eigen::MatrixXd.

int k = 0;
for (int i = 0; i<mat.rows(); ++i)
{
    for (int j = 0; j<mat.cols(); ++j, ++k) {
        mat(i, j) = k;
    }
}

double* mptr = mat.data();
for (int i = 0; i<mat.rows() * mat.cols(); ++i) {
    assert(mptr[i] == i);
}

I haven't got your complain about Eigen::Map. It is the nicest way to treat some data as eigen matrix (note that it will still be column-major by default), subclassing from matrix, or implementing custom eigen expression may be painfull.

Livvie answered 22/11, 2012 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.