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 サイズの double マトリックスを作成できます。

  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

配列が 2 次元の場合、格納順序に注意する必要があります。デフォルトでは、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

Map 機能を再度使用する必要があります。こちらの例をご覧ください: http://forum.kde.org/viewtopic.php?f=74&t=95457

于 2012-06-19T11:52:20.393 に答える
0

私が試してみると、Map above segfaultsを使用したソリューション(上記のコメントを参照)。

代わりに、データを 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 に答える