65

Eigen库可以将现有内存映射到 Eigen 矩阵。

float array[3];
Map<Vector3f>(array, 3).fill(10);
int data[4] = 1, 2, 3, 4;
Matrix2i mat2x2(data);
MatrixXi mat2x2 = Map<Matrix2i>(data);
MatrixXi mat2x2 = Map<MatrixXi>(data, 2, 2);

我的问题是,我们如何从特征矩阵(例如 Matrix3f m)中获取 c 数组(例如 float[] a)?特征矩阵的真实布局是什么?真实数据是否存储在普通 c 数组中?

4

7 回答 7

67

您可以使用 Eigen Matrix 类的data()成员函数。默认情况下布局是列优先的,而不是多维 C 数组中的行优先(可以在创建 Matrix 对象时选择布局)。对于稀疏矩阵,前面的句子显然不适用。

例子:

ArrayXf v = ArrayXf::LinSpaced(11, 0.f, 10.f);
// vc is the corresponding C array. Here's how you can use it yourself:
float *vc = v.data();
cout << vc[3] << endl;  // 3.0
// Or you can give it to some C api call that takes a C array:
some_c_api_call(vc, v.size());
// Be careful not to use this pointer after v goes out of scope! If
// you still need the data after this point, you must copy vc. This can
// be done using in the usual C manner, or with Eigen's Map<> class.
于 2011-12-09T09:59:19.980 回答
20

将普通数据类型转换为特征矩阵类型

  double *X; // non-NULL pointer to some data

您可以使用 Map 功能创建一个 nRows x nCols 大小的双精度矩阵,如下所示:

  MatrixXd eigenX = Map<MatrixXd>( X, nRows, nCols );

将特征矩阵类型转换为普通数据类型

  MatrixXd resultEigen;   // Eigen matrix with some result (non NULL!)
  double *resultC;        // NULL pointer <-- WRONG INFO from the site. resultC must be preallocated!
  Map<MatrixXd>( resultC, resultEigen.rows(), resultEigen.cols() ) =   resultEigen;

通过这种方式,您可以从特征矩阵中进出。完整的学分转到http://dovgalecs.com/blog/eigen-how-to-get-in-and-out-data-from-eigen-matrix/

于 2015-04-25T12:14:58.613 回答
7

如果数组是二维的,需要注意存储顺序。默认情况下,Eigen 以列优先顺序存储矩阵。但是,将数组直接转换为特征矩阵需要行优先顺序。如果在代码中频繁执行此类转换,则使用相应的typedef.

using namespace Eigen;
typedef Matrix<int, Dynamic, Dynamic, RowMajor> RowMatrixXi;

有了这样的定义,我们可以以一种简单而紧凑的方式从数组中获得特征矩阵,同时保留原始数组的顺序。

从 C 数组到 Eigen::Matrix

int nrow = 2, ncol = 3;
int arr[nrow][ncol] =  { {1 ,2, 3},  {4, 5, 6} }; 
Map<RowMatrixXi> eig(&arr[0][0], nrow, ncol);

std::cout << "Eigen matrix:\n" << eig << std::endl;

// Eigen matrix:
// 1 2 3
// 4 5 6

在相反的方向上,特征矩阵的元素可以通过使用直接转移到 C 风格的数组中Map

从 Eigen::Matrix 到 C 数组

int arr2[nrow][ncol];
Map<RowMatrixXi>(&arr2[0][0], nrow, ncol) = eig;

std::cout << "C array:\n";
for (int i = 0; i < nrow; ++i) {
  for (int j = 0; j < ncol; ++j) {
    std::cout << arr2[i][j] << " ";
  }
  std::cout << "\n";
}

// C array:
// 1 2 3 
// 4 5 6 

请注意,在这种情况下,原始矩阵eig不需要存储在行优先布局中。在 中指定行主要顺序就足够了Map

于 2018-02-07T19:40:41.483 回答
3

您需要再次使用地图功能。请在此处查看示例:http: //forum.kde.org/viewtopic.php?f=74 &t=95457

于 2012-06-19T11:52:20.393 回答
0

当我尝试时,上面的 Map 解决方案会出现段错误(请参阅上面的评论)。

相反,这是一个适合我的解决方案,将数据从 Eigen::Matrix 复制到 std::vector 中。我在向量中预先分配空间来存储映射/复制的结果。

Eigen::MatrixXf m(2, 2);
m(0, 0) = 3;
m(1, 0) = 2.5;
m(0, 1) = -1;
m(1, 1) = 0;

cout << m << "\n";

// Output:
//    3  -1
// 2.5   0

// Segfaults with this code: 
//
// float* p = nullptr;
// Eigen::Map<Eigen::MatrixXf>(p, m.rows(), m.cols()) = m;

// Better code, which also copies into a std::vector:

// Note that I initialize vec with the matrix size to begin with:
std::vector<float> vec(m.size());
Eigen::Map<Eigen::MatrixXf>(vec.data(), m.rows(), m.cols()) = m;

for (const auto& x : vec)
  cout << x << ", ";
cout << "\n";

// Output: 3, 2.5, -1, 0
于 2016-10-26T20:06:16.873 回答
0

我试过这个:在(0,0)处传递元素的地址并向前迭代。

Eigen::Matrix<double, 3, 8> coordinates3d;
coordinates3d <<    0.0,  0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  1.0,
                    0.0,  1.0,  1.0,  0.0,  0.0,  1.0,  1.0,  0.0,
                    1.0,  1.0,  1.0,  1.0,  0.0,  0.0,  0.0,  0.0;
double *p = &coordinates3d(0,0);
std::vector<double> x2y2;
x2y2.assign(p, p + coordinates3d.size());

for(int i=0;i < coordinates3d.size(); i++) {
    std::cout <<x2y2[i];
}

这是输出: 001011111101000010110100 数据似乎以行为主

于 2020-08-27T09:07:25.573 回答
-5
ComplexEigenSolver < MyMatrix > es;
complex<double> *eseig;
es.compute(H);
es.eigenvalues().transpose();
eseig=(complex<double> *)es.eigenvalues().data();
于 2013-12-13T03:50:04.343 回答