ofCvFloatImage float pixels values

I want to get the float value of each pixel to do my own operations. getPixels for the ofCvFloatImage class currently returns the IPL_DEPTH_8U image data, not the floats.

  1. For some reason, if I do this:

IplImage * cvImage = floatImage.getCvImage();

I get
error C2275: ‘IplImage’ : illegal use of this type as an expression
\libs\opencv\cxcore\include\cxtypes.h(393) : see declaration of ‘IplImage’

  1. I modified ofCvFloatImage to return the float pixels

char * pix = floatImage.getFloatPixels();

// like so
char * getFloatPixels(){ return cvImage->imageData; };

however, any value eg pix[100] isn’t a number between 0.0-1.0

Any ideas?

Thanks

some thoughts:

a) you will need to make the memory continuous (ie use the memcopy to align memory). opencv images are *not* continuous, so we go through the steps of making them continuous. that’s what happening with the memcpys.

b) because of (a), you will need an internal float “pixels” array, such as:
float * floatPixels; // not width stepped

c) you will want to return a float *, not a char * (otherwise asking for pix[100] is like asking for the 100th unsigned char, not the 100th float).

let me know if that helps - if not we can take a look later at it…

  • zach

It would definitely be great to have get and set methods for float pixels for this class, makes sense.

Here is a first attempt at using your getPixels function

  
  
float * ofCvFloatImage::getFloatPixels(){  
	for (int i = 0; i < height; i++){  
		memcpy(floatPixels + (i * width), cvImage->imageData + (i * cvImage->widthStep), width);  
	}	  
	return floatPixels;  
}  
  

of course, this crashes. imageData is char, but how can it be converted to a float?

In theory you could also do this

  
  
float * ofCvFloatImage::getFloatPixels(){  
  
	unsigned char * tempPixels = getPixels();  
	for(int i=0; i<(width*height); i++){  
		floatPixels[i] = (float)tempPixels[i];  
	}  
	return floatPixels;  
}  
  

But that crashes as well :slight_smile:

can I see where you allocate “floatPixels” ?

(float *) cvImage->imageData helps ?

thanks
zach

sorry, something else i did after this crashed it. Here is the code

  
  
// ofCvFloatImage.h  
  
public:  
 float * getFloatPixels();  
  
private:  
unsigned char * pixels;  
  
// ofCvFloatImage.cpp  
void ofCvFloatImage::allocate(int _w, int _h){  
	if (!bAllocated)  
	{  
	 ....  
		floatPixels			= new float[_w*_h];  
	 ....  
	}  
}  
  

It actually returns values from 0.0 to 255.0

I forgot, doing it using getPixels first won’t work as they return unsigned chars (loosing decimal data when converted to 8u). Let me try the memcpy way

Ok, using the memcpy method (as above), all of the values are 0.0, so memcpy from unsigned char to float isnt working.

I thought this might work but it crashes

  
  
float * ofCvFloatImage::getFloatPixels(){  
	unsigned char * temppixels = new unsigned char[width*height];  
	for (int i = 0; i < height; i++){  
		memcpy(temppixels + (i * width), cvImage->imageData + (i * cvImage->widthStep), width);  
	}  
	floatPixels = (float *)temppixels;  
	delete temppixels;  
	return floatPixels;  
}  
  

  
  
memcpy(floatPixels + (i * width), (float *)cvImage->imageData + (i * cvImage->widthStep), width);  

All pixels are 0.0 :frowning:

  
  
floatPixels = (float *)temppixels;  
   delete temppixels;  
   return floatPixels;   
  

this will cause a crash for sure, since floatPixels is pointing to “freed” memory.

I’ll take a look at this later today - I’m pretty sure the memcpy will work…

take care,
zach

my friend andreas solved it…

sizeof(float)*width

Here is a working function:

  
  
float * ofCvFloatImage::getFloatPixels(){  
	for (int i = 0; i < height; i++){  
		memcpy(floatPixels + (i * width), cvImage->imageData + (i * cvImage->widthStep), sizeof(float)*width);  
	}  
	return floatPixels;  
}  
  

great ! yeah the memcpy stuff always is tricky when it’s not 8bit things being copied.

good call andreas, and thanks for working it out ! I’ll add that code to float image for the next release.

take care,
zach

It might also be good to add setFromFloatPixels()

  
  
void ofCvFloatImage::setFromFloatPixels(float * _pixels, int w, int h){  
	for (int i = 0; i < h; i++){  
		memcpy(cvImage->imageData + (i * cvImage->widthStep), _pixels + (i * w), sizeof(float)*w);  
	}  
	for (int i = 0; i < h; i++){  
	  memcpy(pixels + (i * w), cvImage->imageData + (i * cvImage->widthStep), sizeof(float)*w);  
	}  
}  
  

sure- that’s helpful !

it’d be good there to check allocation and if w/h are equal to what’s passed in. for example, someone might pass in something wrong. or before you have allocated, in which you could reallocate the cvImage (free and reallocate) or do some error reporting, etc. we can try to add those functions to the cv image classes.

thanks!!
zach

I think there may be a bug in the code I posted above…

  
  
void ofCvFloatImage::setFromFloatPixels(float * _pixels, int w, int h){  
	for (int i = 0; i < h; i++){  
		memcpy(cvImage->imageData + (i * cvImage->widthStep), _pixels + (i * w), sizeof(float)*w);  
	}  
	for (int i = 0; i < h; i++){  
	  memcpy(pixels + (i * w), cvImage->imageData + (i * cvImage->widthStep), sizeof(float)*w);  
	}  
}  
  

should be…

  
  
void ofCvFloatImage::setFromFloatPixels(float * _pixels, int w, int h){  
	for (int i = 0; i < h; i++){  
		memcpy(cvImage->imageData + (i * cvImage->widthStep), _pixels + (i * w), sizeof(float)*w);  
	}  
	for (int i = 0; i < h; i++){  
	  memcpy(floatPixels + (i * w), cvImage->imageData + (i * cvImage->widthStep), sizeof(float)*w);  
	}  
}  
  

only difference is memcpy(pixels needs to be memcpy(floatPixels