Converting Eigen matrix to unsigned char *

Viewed 770

I'm trying to use Eigen to interface with unsigned char * types. I can convert to Eigen and then to float, but when I convert back to unsigned char , the result is wrong. I need the Eigen matrix to be in float type so I can perform arithmetic operations on it. Then I need to bring it back to unsigned char so I can save it.

#include <Eigen/Dense>
#include <iostream>
int main(){
unsigned char* data;
for (int i=0;i<9;++i){ 
    data[i]= i;
}
//Map data to Eigen
Map<Matrix<unsigned char,3,3> ,RowMajor> img(data,3,3);
//Convert to float
MatrixXf gray = img.cast<float>();
//Convert back to unsigned char*
float *gray_array = gray.data();
unsigned char *gray_UC = (unsigned char*)gray_array;

std::cout<<"Eigen matrix converted to unsigned char:"<<(float)*(gray_UC+1)<<std::endl;
std::cout<<"Eigen matrix as float: "<<*(gray_array+i)<<std::endl;
std::cout<<"Original data converted to float: "<<(float)*(data+1)<<std::endl;
}

Data being an unsigned char* type.

I expect gray_UC and data to be the same, but it is not the case. Even more, gray_array prints the right float value, so it might be the conversion to unsigned char that is wrong.

2 Answers

When you do:

(float)*(gray_UC+1)

You are taking the pointer gray_UC and adding one to it according to pointer arithmetic. If an unsigned char is one byte that means just one byte after gray_UC. Then you dereference that, getting that next byte as unsigned char, and then cast that value to float. The result, I presume, should be a float number between 0 and 255.

Here:

(float)*(data+1)

You take the pointer data and increase it by one, but in this case is a pointer to float which, being 4 bytes, would take the pointer four bytes forward. Next you dereference that and cast it to float (which shouldn't have any effect anyway), so you get the second float value in the floats buffer pointed by data.

In order to get the same from gray_UC, you would do something like:

*(((float*) gray_UC) + 1)

Here is a solution that works for me, inspired by @Nico Schertler 's comment. I do the cast within a for loop. However I had to use an array first and then give the adress of the first element to my unsigned char *.

In the future I should consider trying std::transformas is advised in the link from @Nico Schertler .

Note that I did not cast the Eigen array to unsigned char directly, because my real application is using a big array. When I tried it, I got an error linked to memory issues.

Here is my solution:

unsigned char gray_UC_tmp[size];
for (int i=0; i<9;++i){
      gray_UC_tmp[i] = static_cast<unsigned char> (gray_array[i]);
}
gray_UC = gray_UC_tmp;
Related