web-dev-qa-db-fra.com

Convertir la matrice propre en tableau C

La bibliothèque Eigen peut mapper la mémoire existante en matrices propres.

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);

Ma question est, comment pouvons-nous obtenir un tableau c (par exemple float [] a) à partir d'une matrice propre (par exemple Matrix3f m)? Quelle est la véritable disposition de la matrice propre? Les données réelles sont-elles stockées comme dans un tableau c normal?

49
lil

Vous pouvez utiliser la fonction membre data () de la classe Eigen Matrix. La disposition par défaut est la colonne principale, pas la ligne principale comme un tableau C multidimensionnel (la disposition peut être choisie lors de la création d'un objet Matrix). Pour les matrices clairsemées, la phrase précédente ne s'applique évidemment pas.

Exemple:

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.
51
janneb

Pour convertir un type de données normal en type de matrice propre

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

Vous pouvez créer une matrice double de taille nRows x nCols en utilisant la fonctionnalité Carte comme ceci:

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

Pour convertir un type de matrice propre en type de données normal

  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;

De cette façon, vous pouvez entrer et sortir de la matrice propre. Les crédits complets vont à http://dovgalecs.com/blog/eigen-how-to-get-in-and-out-data-from-eigen-matrix/

15
GPrathap

Vous devez réutiliser la fonction Carte. Veuillez voir l'exemple ici: http://forum.kde.org/viewtopic.php?f=74&t=95457

3
Prashanth

Si le tableau est bidimensionnel, il faut faire attention à l'ordre de stockage. Par défaut, Eigen stocke les matrices dans l'ordre des colonnes principales. Cependant, un ordre de ligne majeure est nécessaire pour la conversion directe d'un tableau en une matrice propre. Si de telles conversions sont effectuées fréquemment dans le code, il peut être utile d'utiliser un typedef correspondant.

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

Avec une telle définition, on peut obtenir une matrice propre à partir d'un tableau de manière simple et compacte, tout en préservant l'ordre du tableau d'origine.

Du tableau 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

Dans le sens opposé, les éléments d'une matrice propre peuvent être transférés directement vers un tableau de style C en utilisant Map.

De Eigen :: Matrix à C array

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 

Notez que dans ce cas, la matrice d'origine eig n'a pas besoin d'être stockée dans la disposition des lignes principales. Il suffit de spécifier l'ordre des lignes principales dans Map.

3
RHertel

La solution avec Map ci-dessus segfaults quand je l'essaye (voir le commentaire ci-dessus).

Au lieu de cela, voici une solution qui fonctionne pour moi, en copiant les données dans un vecteur std :: à partir d'une matrice Eigen ::. Je pré-alloue de l'espace dans le vecteur pour stocker le résultat de la carte/copie.

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
1
eraoul