How to Convert Eigen Matrix to C/C++ Array - c++

In Eigen C/C++ Library, how to converter the operation result (example below) from Eigen Matrix to C/C++ Array?
Example:
const Eigen::MatrixXf mat = Eigen::Map<Eigen::MatrixXf>( array_C_input , 3, 3);
const Eigen::MatrixSquareRootReturnValue<Eigen::MatrixXf> result = m.sqrt();
float* array_C_output = (float*) result; // Error: convert sqrt output to C array

If you want to compute the matrix root of a matrix passed as C-style array and handle the result like a C-style array, you can either store the result into a MatrixXf and use the data() member of that matrix:
Eigen::MatrixXf matrix_root = Eigen::MatrixXf::Map( array_C_input , 3, 3).sqrt();
float* array_C_output = matrix_root.data();
Alternatively, if you already have memory allocated for the result, you can map the output to that:
void foo(float* output_array, float const* input_array) {
Eigen::MatrixXf::Map( output_array , 3, 3) =
Eigen::MatrixXf::Map( input_array , 3, 3).sqrt();
}
Note that Matrix::sqrt computes the matrix-root, i.e., if S = A.sqrt(), then S*S == M. If you want an element-wise root, you need to use
Eigen::ArrayXXf::Map( input_array , 3, 3).sqrt()

Related

2D transformations by normal vector with eigen library

I am looking for a builtin way with the eigen library to perform coordinate transformations by normal vectors in 2D space.
Mathematically, it's not difficult: Let v = (v_x, v_y) be a 2D column vector and n = (n_x, n_y) be a normal vector, then the transformation I am looking for is one by rotational matrix:
v_T = N * v, with v_T being the transformed vector and N being the rotational matrix, which is
| nx, ny |
| -ny, nx |
In my case, the data I need to transform is stored in an Array2Xd and the normal vectors are stored in a Matrix2Xd, with each column holding x- and y-component. I need to transform each column in the array by the corresponding normal vector in the matrix.
Currently, I'm doing it like this:
#include <Eigen/Dense>
#include <iostream>
using namespace Eigen;
/* transform a single vector, just for illustration */
Array2d transform_s( const Ref<const Array2d>& v, const Ref<const Vector2d>& n ){
return {
n.dot( v.matrix() ),
-n.y() * v.x() + n.x() * v.y()
};
}
/* transform multiple columns */
Array2Xd transform_m( const Ref<const Array2Xd>& v, const Ref<const Array2Xd>& n ){
Array2Xd transformed ( 2, v.cols() );
/* colwise dot product for first row */
transformed.row(0) = (n * v).colwise().sum();
/* even less elegant calculation for the second row */
transformed.row(1) = n.row(0) * v.row(1) - n.row(1) * v.row(0);
return transformed;
}
int main(){
Array2Xd vals (2, 3);
vals <<
2, 0,-1,
0, 3, 2;
Matrix2Xd n;
n.resizeLike(vals);
n <<
0, 0, 1,
1,-1, 1;
n.colwise().normalize();
std::cout
<< "single column:\n" << transform_s( vals.col(0), n.col(0) )
<< "\nall columns:\n" << transform_m( vals, n.array() )
<< "\n";
return 0;
}
I'm aware of Eigen::Rotation2D, but it appears to either require an angle or a rotational matrix. I am specifically looking for a way to only provide the normal vectors. Otherwise I need to build the rotational matrices from the normal vectors myself, which doesn't really reduce the complexity on my end.
If there's no way to do this with eigen, I'll accept that as an answer. In that case, I'd be very happy about a more efficient implementation of what I wrote above.
What you are doing is essentially a complex multiplication with conj(n).
There is no elegant way to reinterpret a Vector2d/Array2Xd to a complex<double>/ArrayXcd, but you can hack something together using Maps:
Array2Xd transform_complex( const Ref<const Array2Xd>& v, const Ref<const Array2Xd>& n ){
Array2Xd transformed(2, v.cols());
ArrayXcd::Map(reinterpret_cast<std::complex<double>*>(transformed.data()), v.cols())
= ArrayXcd::Map(reinterpret_cast<std::complex<double> const*>(v.data()), v.cols())
* ArrayXcd::Map(reinterpret_cast<std::complex<double> const*>(n.data()), n.cols()).conjugate();
return transformed;
}
You could write yourself a helper function which takes a const Ref<const Array2Xd>& and returns a Map<ArrayXcd> with the same content.

How to convert an std::vector to a matrix in Eigen?

I am somewhat new to Stack Overflow and C++ so feel free to correct any errors in my code and the formatting of this question.
I am trying to make a linear regression calculator using the normal equation which involved the transposing of matrices and multiplication of vectors (and their inverses). The program is supposed to read from a csv file and pass the information from that file into a matrix and calculate the regression line. To make the job easier, I decided to use a library called Eigen for matrix-matrix multiplication.
The problem that I have run into is that the Map function can only take in an array as opposed to a std::vector.
This is what I have so far:
float feature_data[] = { 1, 1, 1, 1, 1, 1,
2, 4.5, 3, 1,4, 5};
float labels[] = { 1, 4, 3, 2, 5, 7 };
//maps the array to a matrix called "feature_data"
MatrixXf mFeatures = Map< Matrix<float, 6, 2> >(feature_data);
MatrixXf mLabels = Map< Matrix<float, 6, 1> >(labels);
//use the toArray function
std::vector<float> test_vector = { 2,1,3 };
float* test_array = toArray(test_vector);
calcLinReg(mFeatures, mLabels);
const int n = 2;
int arr[n];
system("pause");
For context, the toArray function is my unsuccessful attempt to make an array from a vector (in all honesty, it works but it returns a pointer which you can't pass into the Map function in Eigen.) calcLinReg does exactly what it sounds like: calculates the linear regression line parameters.
Is there anyway I can convert a vector to an array or convert a vector to a matrix in Eigen?
How about trying to use the vectors data() method, which gives you access to the memory array used internally by the vector, like this:
std::vector<float> test_vector = { 2,1,3 };
float* test_array = test_vector.data();
Eigen::MatrixXf test = Eigen::Map<Eigen::Matrix<float, 3, 1> >(test_array);
Or shorter:
std::vector<float> test_vector = { 2,1,3 };
Eigen::MatrixXf test = Eigen::Map<Eigen::Matrix<float, 3, 1> >(test_vector.data());
Beware The asignment actually copies the data, therefore this is safe. However, you can also directly use the data of the vector like this
std::vector<float> test_vector(3,2);
Eigen::Map<Eigen::Matrix<float, 3, 1> > dangerousVec (test_vector.data());
If vector goes out of scope the memory is deallocated and dangerousVec's data is dangeling.
Someone in a comment is asking for the case of dynamic numbers of rows and columns. This is possible, as follows:
typedef Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> MyMatrix;
size_t nrow = ...;
size_t ncol = ...;
MyMatrix M = Eigen::Map<MyMatrix>(test_vector.data(), nrow, ncol);

Abstract class on top of Eigen's Matrix and Vector

I would like to implement a neural network framework consisting of layers which can then be composed into a computational graph (see for example caffe). I am using the eigen library for matrices. Eigen distinguishes between vectors and matrices so that for some operations (adding a bias to a matrix) only a vector can be used (and not a matrix with the same dimensions as the vector). For example:
MatrixXf A = MatrixXf(3, 2); // Variables not initialized for brevity
VectorXf v = VectorXf(2);
MatrixXf R1 = A.array().rowwise() + v.transpose().array(); // Broadcasts v correctly
MatrixXf vMat = MatrixXf(1, 2);
MatrixXf R2 = A.array().rowwise() + vMat.array(); // YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX Error
If I want the layers to look something like this:
void AffineForward(std::vector<Tensor> in, std::vector<Tensor> out)
{
MatrixXf &X = in[0];
MatrixXf &W = in[1];
VectorXf &b = in[2];
out[0] = X * W;
out[0] += b;
}
how would I design the abstract Tensor class so that I can just send in a std::vector of Tensors? I thought about something like this:
class Tensor
{
public:
virtual Tensor operator*(const Tensor &t) const = 0;
};
class TensorMatrix : Tensor
{
public:
TensorMatrix operator*(const TensorMatrix &t) const;
TensorMatrix operator*(const TensorVector &t) const;
MatrixXf _data;
};
class TensorVector : Tensor
{
public:
VectorXf _data;
};
but the virtual Tensor operator* throws a compile time error (function returning abstract class Tensor is not allowed) which makes sense.
What is the easiest way of doing what I want? Creating some class that could be put into a container and I could get both MatrixXf and VectorXf out of it (depending on what the user put in?). Caffe uses something called 'Blob'.
Eigen distinguishes between vectors and matrices so that for some operations (adding a bias to a matrix) only a vector can be used (and not a matrix with the same dimensions as the vector).
this is not true, a vector is a matrix in Eigen; it's just that some operations require dimensions to be known at compile time; in your example
MatrixXf R1 = A.rowwise() + v.transpose();
MatrixXf R2 = A.rowwise() + vMat;
the second line does not compile because that broadcasting needs a matrix with a compile time row-dimensions == 1;
the solution is to tell Eigen you want a row vector explictly:
MatrixXf R2 = A.rowwise() + vMat.row(0);
a code working with both row and column vectors stored as MatrixXf being something like ( whether this advisable or not depending on your ultimate requirements )
if( vMat.rows() == 1 )
MatrixXf R1 = A.rowwise() + vMat.rows(0); ...
else if( vMat.cols() == 1 )
MatrixXf R2 = A.rowwise() + vMat.transpose().rows(0); ...
else
whatever...
so, you can always store vectors as matrices with Eigen, you just need some care in telling Eigen what to do with them ...

convert T* array (Jet* or float*) to cv::Mat<CV_32f>

I am using ceres-solver with AutoDiffCostFunction. My cost function takes as parameter 1x3 vector and outputs 1x1 residual.
How can I create opencv Mat out of my T* parameter vector? It may be either Jet or float.
I tried following code, but get error "cannot conver from Jet to float"
struct ErrorFunc
{
template <typename T>
bool operator()(const T * const Kparams, T * residual) const // Kparams - [f, u, v]
{
cv::Mat K = cv::Mat::eye(3, 3, CV_32F);
K.at<float>(0, 0) = float(Kparams[0]); // error
K.at<float>(0, 2) = float(Kparams[1]); // error
K.at<float>(1, 1) = float(Kparams[0]); // error
K.at<float>(1, 2) = float(Kparams[2]); // error
Mat Hdot = K.inv() * H * K;
cv::decomposeHomographyMat(Hdot, K, rot, tr, norm); //want to call this opencv function
residual[0] = calcResidual(norm);
return true;
}
Mat H;
}
There is a way to get Eigen matrix out of T* matrix:
const Eigen::Matrix< T, 3, 3, Eigen::RowMajor> hom = Eigen::Map< const Eigen::Matrix< T, 3, 3, Eigen::RowMajor> >(Matrix)
but I want to call cv::decomposeHomographyMat . How can I do this?
You cannot use an OpenCV method in a ceres::AutoDiffCostFunction in this way. The OpenCV method is not templated with type T as required by ceres to do the automatic differentiation. The float cast cannot be done because the ceres jet of Jacobians is a vector and not a scalar.
You have two options:
1) Use numerical differentiation: see http://ceres-solver.org/nnls_tutorial.html#numeric-derivatives
2) Use a templated library (e.g. Eigen http://eigen.tuxfamily.org/index.php?title=Main_Page) to rewrite the required homography decomposition

Convert Eigen Matrix to C array

The Eigen library can map existing memory into Eigen matrices.
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);
My question is, how can we get c array (e.g. float[] a) from eigen matrix (e.g. Matrix3f m)? What it the real layout of eigen matrix? Is the real data stored as in normal c array?
You can use the data() member function of the Eigen Matrix class. The layout by default is column-major, not row-major as a multidimensional C array (the layout can be chosen when creating a Matrix object). For sparse matrices the preceding sentence obviously doesn't apply.
Example:
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.
To convert normal data type to eigen matrix type
double *X; // non-NULL pointer to some data
You can create an nRows x nCols size double matrix using the Map functionality like this:
MatrixXd eigenX = Map<MatrixXd>( X, nRows, nCols );
To convert eigen matrix type into normal data type
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;
In this way you can get in and out from eigen matrix. Full credits goes to http://dovgalecs.com/blog/eigen-how-to-get-in-and-out-data-from-eigen-matrix/
If the array is two-dimensional, one needs to pay attention to the storage order. By default, Eigen stores matrices in column-major order. However, a row-major order is needed for the direct conversion of an array into an Eigen matrix. If such conversions are performed frequently in the code, it might be helpful to use a corresponding typedef.
using namespace Eigen;
typedef Matrix<int, Dynamic, Dynamic, RowMajor> RowMatrixXi;
With such a definition one can obtain an Eigen matrix from an array in a simple and compact way, while preserving the order of the original array.
From C array to 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
In the opposite direction, the elements of an Eigen matrix can be transferred directly to a C-style array by using Map.
From Eigen::Matrix to 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
Note that in this case the original matrix eig does not need to be stored in row-major layout. It is sufficient to specify the row-major order in Map.
You need to use the Map function again. Please see the example here:
http://forum.kde.org/viewtopic.php?f=74&t=95457
The solution with Map above segfaults when I try it (see comment above).
Instead, here's a solution that works for me, copying the data into a std::vector from an Eigen::Matrix. I pre-allocate space in the vector to store the result of the Map/copy.
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
I tried this : passing the address of the element at (0,0) and iterating forward.
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];
}
This is the output : 001011111101000010110100
The data is stored row-major it seems
ComplexEigenSolver < MyMatrix > es;
complex<double> *eseig;
es.compute(H);
es.eigenvalues().transpose();
eseig=(complex<double> *)es.eigenvalues().data();