mapping c++ array to Eigen Matrix - c++

What I am currently trying to do is get the data from my variable input, convert it into and Eigen matrix, do some computation and then map the result back to an c++ array.
void RBM::reconstruct(double *input, double *w)
{
double *data = input;
mexPrintf("\n");
for (int j = 0; j < 6; j++){
mexPrintf("%f", data[j]);
}
mexPrintf("\n");
Map<MatrixXd> XX(data,6,6);
MatrixXd resultEigen;
double *result;
Map<MatrixXd>( result, 6, 6 ) = XX;
resultEigen = XX.transpose();
Map<MatrixXd>( result, resultEigen.rows(), resultEigen.cols() ) = resultEigen;
}
The above code compiles but i get (run Time error) probably link to an access violation and i can't really figure out where the problem is. Thanks for any hint.

You misunderstand what a Eigen::Map is. The map wraps an existing memory block and allows you to use Eigens functionality on that block. With a Eigen::Map Eigen does handle any of the memory allocations. This allow you to manipulate the data in objects from other libraries without copying back and forth. As mentioned in the comments, if you allocate the result array as double result[36]; the program should run fine.

#include <Eigen/Dense>
#include <kdl/jntarray.hpp>
Eigen::MatrixXd mat_1, mat_2;
KDL::JntArray arr;
mat_1 = arr.data.matrix() - mat_2 ;
Here, array is converted to matrix

Related

C++ Avoiding Triple Pointers

I am trying to create an array of X pointers referencing matrices of dimensions Y by 16. Is there any way to accomplish this in C++ without the use of triple pointers?
Edit: Adding some context for the problem.
There are a number of geometries on the screen, each with a transform that has been flattened to a 1x16 array. Each snapshot represents the transforms for each of number of components. So the matrix dimensions are 16 by num_components by num_snapshots , where the latter two dimensions are known at run-time. In the end, we have many geometries with motion applied.
I'm creating a function that takes a triple pointer argument, though I cannot use triple pointers in my situation. What other ways can I pass this data (possibly via multiple arguments)? Worst case, I thought about flattening this entire 3D matrix to an array, though it seems like a sloppy thing to do. Any better suggestions?
What I have now:
function(..., double ***snapshot_transforms, ...)
What I want to accomplish:
function (..., <1+ non-triple pointer parameters>, ...)
Below isn't the function I'm creating that takes the triple pointer, but shows what the data is all about.
static double ***snapshot_transforms_function (int num_snapshots, int num_geometries)
{
double component_transform[16];
double ***snapshot_transforms = new double**[num_snapshots];
for (int i = 0; i < num_snapshots; i++)
{
snapshot_transforms[i] = new double*[num_geometries];
for (int j = 0; j < num_geometries; j++)
{
snapshot_transforms[i][j] = new double[16];
// 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
for (int k = 0; k < 16; k++)
snapshot_transforms[i][j][k] = k;
}
}
return snapshot_transforms;
}
Edit2: I cannot create new classes, nor use C++ features like std, as the exposed function prototype in the header file is getting put into a wrapper (that doesn't know how to interpret triple pointers) for translation to other languages.
Edit3: After everyone's input in the comments, I think going with a flattened array is probably the best solution. I was hoping there would be some way to split this triple pointer and organize this complex data across multiple data pieces neatly using simple data types including single pointers. Though I don't think there is a pretty way of doing this given my caveats here. I appreciate everyone's help =)
It is easier, better, and less error prone to use an std::vector. You are using C++ and not C after all. I replaced all of the C-style array pointers with vectors. The typedef doublecube makes it so that you don't have to type vector<vector<vector<double>>> over and over again. Other than that the code basically stays the same as what you had.
If you don't actually need dummy values I would remove that innermost k loop completely. reserve will reserve the memory space that you need for the real data.
#include <vector>
using std::vector; // so we can just call it "vector"
typedef vector<vector<vector<double>>> doublecube;
static doublecube snapshot_transforms_function (int num_snapshots, int num_geometries)
{
// I deleted component_transform. It was never used
doublecube snapshot_transforms;
snapshot_transforms.reserve(num_snapshots);
for (int i = 0; i < num_snapshots; i++)
{
snapshot_transforms.at(i).reserve(num_geometries);
for (int j = 0; j < num_geometries; j++)
{
snapshot_transforms.at(i).at(j).reserve(16);
// 4x4 transform put into a 1x16 array with dummy values for each component for each snapshot
for (int k = 0; k < 16; k++)
snapshot_transforms.at(i).at(j).at(k) = k;
}
}
return snapshot_transforms;
}
Adding a little bit of object-orientation usually makes the code easier to manage -- for example, here's some code that creates an array of 100 Matrix objects with varying numbers of rows per Matrix. (You could vary the number of columns in each Matrix too if you wanted to, but I left them at 16):
#include <vector>
#include <memory> // for shared_ptr (not strictly necessary, but used in main() to avoid unnecessarily copying of Matrix objects)
/** Represents a (numRows x numCols) 2D matrix of doubles */
class Matrix
{
public:
// constructor
Matrix(int numRows = 0, int numCols = 0)
: _numRows(numRows)
, _numCols(numCols)
{
_values.resize(_numRows*_numCols);
std::fill(_values.begin(), _values.end(), 0.0f);
}
// copy constructor
Matrix(const Matrix & rhs)
: _numRows(rhs._numRows)
, _numCols(rhs._numCols)
{
_values.resize(_numRows*_numCols);
std::fill(_values.begin(), _values.end(), 0.0f);
}
/** Returns the value at (row/col) */
double get(int row, int col) const {return _values[(row*_numCols)+col];}
/** Sets the value at (row/col) to the specified value */
double set(int row, int col, double val) {return _values[(row*_numCols)+col] = val;}
/** Assignment operator */
Matrix & operator = (const Matrix & rhs)
{
_numRows = rhs._numRows;
_numCols = rhs._numCols;
_values = rhs._values;
return *this;
}
private:
int _numRows;
int _numCols;
std::vector<double> _values;
};
int main(int, char **)
{
const int numCols = 16;
std::vector< std::shared_ptr<Matrix> > matrixList;
for (int i=0; i<100; i++) matrixList.push_back(std::make_shared<Matrix>(i, numCols));
return 0;
}

How to use memset or fill_n to initialize a dynamic two dimensional array in C++

I have a 2D array created dynamically.
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
}
I want to fill the array with some value (say 1). I can loop over each item and do it.
But is there a simpler way. I am trying to use memset and std::fill_n as mentioned in this post.
std::fill_n(abc, rows * cols, 1);
memset(abc, 1, rows * cols * sizeof(int));
Using memset crashes my program. Using fill_n gives a compile error.
invalid conversion from 'int' to 'int*' [-fpermissive]
What am I doing wrong here ?
You could just use vector:
std::vector<std::vector<int>> abc(rows, std::vector<int>(cols, 1));
You cannot use std::fill_n or memset on abc directly, it simply will not work. You can only use either on the sub-arrays:
int **abc = new int*[rows];
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(abc[i], cols, 1);
}
Or make the whole thing single-dimensional:
int *abc = new int[rows * cols];
std::fill_n(abc, rows*cols, 1);
Or I guess you could use std::generate_n in combination with std::fill_n, but this just seems confusing:
int **abc = new int*[rows];
std::generate_n(abc, rows, [cols]{
int* row = new int[cols];
std::fill_n(row, cols, 1);
return row;
});
I think that your main problem here is that you don't have an array of int values. You have an array of pointers to ints.
You probably should start with int* abc = new int[rows * cols]; and work from there, if I understand what you are trying to achieve here.
Just use with * inside the loop you already have:
for (uint32_t i = 0; i < rows; i++)
{
abc[i] = new int[cols];
std::fill_n(*(abc+i), cols, sizeof(int));
}
fill_n don't know where the memory maps the new int array, so you must be carefully coding that way.
I recommend to read:
A proper way to create a matrix in c++
Since you've already got good, workable answers to solve your problem, I want to add just two pointers left and right from the standard path ;-)
a) is just a link to the documentation of Boost.MultiArray
and b) is something I don't recommend you use, but it might help you to understand what you've initially tried. And since your profile shows visual studio tags, you might come in contact with something like this in the win32 api. If that is the case the documentation usually tells you not to use free()/LocalFree()/... on the elements and the "outer" pointer-pointer but to use a specialized function.
(note: I'm not trying to make this code look pretty or clever; it's a mishmash of c and a little c++-ish junk ;-))
const std::size_t rows = 3, cols =4;
int main()
{
std::size_t x,y;
// allocate memory for 0...rows-1 int* pointers _and_ cols*rows ints
int **abc = (int**)malloc( (rows*sizeof(int*)) + cols*rows*sizeof(int) );
// the memory behind abc is large enough to hold the pointers for abc[0...rows-1]
// + the actual data when accessing abc[0...rows-1][0....cols-1]
int* data = (int*)((abc+rows));
// data now points to the memory right after the int*-pointer array
// i.e. &(abc[0][0]) and data should point to the same location when we're done:
// make abc[0] point to the first row (<-> data+(cols*0)), abc[1] point the second row (<-> data+(cols*1)....
for(y=0;y<rows; y++) {
abc[y] = &(data[y*cols]);
}
// now you can use abc almost like a stack 2d array
for(y=0; y<rows; y++) {
for (x=0; x<cols; x++) {
abc[y][x] = 127;
}
}
// and -since the memory block is continuos- you can also (with care) use memset
memset(&abc[0][0], 1, sizeof(int)*rows*cols);
// and with equal care ....
std::fill_n( &(abc[0][0]), rows*cols, 127);
// and get rid of the whole thing with just one call to free
free(abc);
return 0;
}

Add a matrix of 2x2 into a vector in c++

I am trying to fill a vector with a matrix of values in c++. I'm not very self confident with this procedure (I don't know well about pointers and I don't know if I need it here) however I am trying this
int auxMat[gray.rows][gray.cols];
vector<int> collectionSum;
collectionSum.push_back(auxMat);
When I try to compile I receive an error which says
invalid arguments 'Candidates are: void push_back(const int &)
Can anyone tell me wether it's possible to do, how can I solve it?
I read something about erasing cache memory, changing my eclipse compiler, my c++ version, however I don't think the problem is so big.
You cannot push back a matrix into a vector. What you can do is preallocate memory for your vector (for speeding things up) then use the std::vector<>::assign member function to "copy" from the matrix into the vector:
vector<int> collectionSum(gray.rows * gray.cols); // reserve memory, faster
collectionSum.assign(*auxMat, *auxMat + gray.rows * gray.cols);
This should be pretty fast. Otherwise, you can push back each individual element in a loop.
EDIT
See May I treat a 2D array as a contiguous 1D array? for some technicalities regarding possible undefined behaviour (thanks #juanchopanza for the comment). I believe the code is safe, due to the fact that the storage of the matrix is contiguous.
Because the array auxMat is continuous in memory, you can just copy it directly from memory into your vector. Here, you are telling the vector constructor to copy from the start of auxMat until its end in memory using pointer arithmetic:
std::vector<int> collectionSum(auxMat, auxMat + (gray.rows * gray.cols));
EDIT:
Sorry, I read your question as being a 1D array (int*) rather than a 2D (int**) array. I honestly recommend switching over to a 1D array because often it is faster and easier to work with. Depending on whether your using row-first order or column-first order, you can access the element you want by:
elem = y * width + x; // for row-first order
elem = x * height + y; // for column-first order
For instance:
// Create a 3x3 matrix but represent it continuously as a 1D array
const int A[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
const unsigned width = 3;
const unsigned height = 3;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
printf("%d ", A[y * width + x]);
}
printf("\n");
}

What is wrong in my mex file? input/output definition?

I am trying to run my mex function which I've written in c++ in VS. It compiles successfully in MATLAB but returns the wrong values. I'm pretty much sure, I'm not reading the 16-by-21 input matrix gammas. Can anybody see what is wrong here?
void fun(double gammas[], int num1, int num2, int length, double a[])
{
...
}
void mexFunction(int nlhs, mxArray *plhs, int nrhs, const mxArray *prhs)
{
double *gammas, *a;
int num1, num2, length;
size_t mrows, mcols;
mrows = 4; mcols = 21;
length = 21;
plhs[0] = mxCreateDoubleMatrix((mSize)mrows, (mwSize)ncols, mxREAL);
gammas = mxGetPr(prhs[0]);
num1 = (int)*mxGetPr(prhs[1]);
num2 = (int)*mxGetPr(prhs[2]);
a = mxGetPr(plhs[0]);
fun(gammas, num1, num2, length, a);
}
I get correct "a" when I call "fun" within a "main" instead of "mex" function in VS and manually provide the input gammas. I receive wrong "a" when I call the resulted mex file in my MATLAB code.
As suspected in comments to your question issue is due to how matlab and c/c++ order array elements for linear storage as 1D array in memory. Matlab uses column-major order while C/C++ uses row-major.
I would not advice you to do permutation prior to call mex-function but rather do the permutation inside the mex function. Either as suggested by #chappjc by call to permute with mexCallMatlab or by call to mxCalcSingleSubscript which returns matlab's linear index from coordinates (whatever the number of dimensions).
Side note: Need confirmation and find back great article I read about that, but matlab uses column-major ordering because it's more appropriate for matrix multiplication (creates less page-defaults when accessing memory cache, and is thus faster). Again need confirmation ... but at least this organisation is better suited for access by columns rather than by rows ...
Edit
Btw, some simple code (C#) to obtain coordinates from maltab's zero based linear index (reverse of mxCalcSingleSubscript):
private static int[] getCoordinatesFromMatlabLinearIndex(int index, int[] arrayDims)
{
var ret = new int[count];
var count = arrayDims.Length;
for (var k = 0; k < count; k++)
{
index = Math.DivRem(index, arrayDims[k], out ret[k]);
}
return ret;
}
As an alternative to inputting a transposed matrix to address the row/column-major discrepancy that CitizenInsane pointed out, you can have the transpose handled inside the MEX file. Use a helper C++ function. You can either write a loop to copy elements, or simply call permute via mexCallMATLAB. Something like the following:
int permute2DMATtoC(mxArray*& matPermuted, const mxArray* mat)
{
mxAssert(mxGetNumberOfDimensions(mat)<=3, "Requires 2D or 3D matrix.");
mxArray *permuteRHSArgs[2];
permuteRHSArgs[0] = const_cast<mxArray*>(mat);
permuteRHSArgs[1] = mxCreateDoubleMatrix(1,3,mxREAL);
mxGetPr(permuteRHSArgs[1])[0] = 2;
mxGetPr(permuteRHSArgs[1])[1] = 1;
mxGetPr(permuteRHSArgs[1])[2] = 3; // supports 2D and 3D
return mexCallMATLAB(1, &matPermuted, 2, permuteRHSArgs, "permute");
}
Use:
mxArray *matPermuted;
permute2DMATtoC(matPermuted, prhs[0]); // matPermuted is MATLAB-managed
double *gammas = (double*)mxGetData(matPermuted);
NOTE: Since matPermuted is manage by MATLAB, you don't need to explicitly destroy it to reclaim resources, but when you are done you can do this if you want:
mxDestroyArray(matPermuted);
For RGB, it may be necessary to convert pixel order (RGB-RGB-RGB-...) to planar order (RRRR...-GGGG...-BBBB...).

How to improve sorting pixels in cvMat?

I am trying to sort pixel values of an image (example 80x20) from lowest to highest.
Below is the some code:
bool sortPixel(int first, int second)
{
return (first < second);
}
vector<int>vect_sortPixel;
for(int y=0; y<height; y++)
{
for(int x=0; x<width; x++)
{
vect_sortPixel.push_back(cvGetReal2D(srcImg, y, x));
sort(vect_sortPixel.begin(), vect_sortPixel.end(), sortPixel);
}
}
But it takes quite long time to compute. Any suggestion to reduce the processing time?
Thank you.
Don't use getReal2D. It's quite slow.
Convert image to cv::Mat or Mat. Use its data pointer to get the pixel values. Mat.data() will give you pointer to the original matrix. Use that.
And as far as sorting is concerned, I would advise you to first make an array of all the pixels, then sort it using Merge sort (time complexity O(n log n))
#include<opencv2/highgui/highgui.hpp>
#include<stdio.h>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
unsigned char *input = (unsigned char*)(img.data);
int i,j,r,g,b;
for(int i = 0;i < img.cols;i++){
for(int j = 0;j < img.rows;j++){
b = input[img.cols * j + i] ;
g = input[img.cols * j+ i + 1];
r = input[img.cols *j + i +2];
}
}
return 0;
}
Using this you can access pixel values from the main matrix.
Warning: This is not how you compare it. I'm suggesting that by using something like this, you can access pixel values.
Mat.data() gives you pointer to the original matrix. This matrix is a 1 D matrix with all the given pixel values.
Image => (x,y,z),(x1,y1,z1), etc..
Mat(original matrix) => x,y,z,x1,y1,z1,...
If you still have some doubts regarding how to extract data from Mat, visit this link OpenCV get pixel channel value from Mat image
and here's a link regarding Merge Sort http://www.cplusplus.happycodings.com/Algorithms/code17.html
There are few problems in your code:
As Froyo already said you use cvGetReal2D which is actually not very fast. You have to convert your cvMat to cv::Mat. To do this there's cv::Mat constructor:
// converts old-style CvMat to the new matrix; the data is not copied by default
Mat(const CvMat* m, bool copyData=false);
And after this use direct pixels acces as mentioned in this SO question.
Another problem is that you use push_back which actually also not very fast. You know the size of array, so why don't you allocate needed memory at the beginning? Like this:
vector<int> vect_sortPixel(mat.cols*mat.rows);
And than just use vect_sortPixel[i] to get needed pixel.
Why do you call sort in the loop? You have to call it after loop, when array is already created! Default STL's sort should work fast:
Complexity
Approximately N*logN comparisons on average (where N is
last-first). In the worst case, up to N^2, depending on specific
sorting algorithm used by library implementation.