Weird Values in an IplImage - c++

I do have an IplImage I. and it's supposed to have values from 0 to 255 (pixels).
I'm having in it unfortunately weird special characters like:
ØÕÖÕÓÎËÍÌÈÃÃÁ»¶±«¨¤Ÿ™”‰
I did the following:
uchar* d_I = (uchar*) I->imageData;
How can I convert those characters into values from 0 to 255 ?

Since you have tagged c++, here's how you can print a char as a number using cout.
Keep your previous code.
uchar* d_I = (uchar*) I->imageData;
std::cout <<(int) *d_I;

are you taking image->widthStep into account? the pixels aren't simply the pointer cast to the data type you passed to cvCreateImage (or what got loaded by cvLoadImage) then incremented... the rows are aligned to 4 or 8 bytes, so each row isn't necessarily touching in memory (though it would be close within a few bytes).
Access your pixels with:
(unsigned char)CV_IMAGE_ELEM(myImage, unsigned char, y, x)
or if you started with a 64F depth image:
(double)CV_IMAGE_ELEM(myImage, double, row, col)
see:
How to access the elements of single channel IplImage in Opencv

Instead of casting in uchar, you should cast to int:
int* d_l = (int*)l->imageData

Related

How do you convert a 16 bit unsigned integer to a larger 8 bit unsigned integer?

I have a function that needs to return a 16 bit unsigned int vector, but for another from which I also call this one, I need the output in 8 bit unsigned int vector format. For example, if I start out with:
std::vector<uint16_t> myVec(640*480);
How might I convert it to the format of:
std::vector<uint8_t> myVec2(640*480*4);
UPDATE (more information):
I am working with libfreenect and its getDepth() method. I have modified it to output a 16 bit unsigned integer vector so that I can retrieve the depth data in millimeters. However, I would also like to display the depth data. I am working with some example code c++ from the freenect installation, which uses glut and requires an 8 bit unsigned int vector to display the depth, however, i need the 16 bit to retrieve the depth in millimeters and log it to a text file. Therefore, i was looking to retrieve the data as a 16 bit unsigned int vector in glut's draw function, and then convert it so that I can display it with the glut function that's already written.
As per your update, assuming the 8-bit unsigned int is going to be displayed as a gray scale image, what you need is akin to a Brightness Transfer Function. Basically, your output function is looking to map the data to the values 0-255, but you don't necessarily want those to correspond directly to millimeters. What if all of your data was from 0-3mm? Then your image would look almost completely black. What if it was all 300-400mm? Then it'd be completely white because it was clipped to 255.
A rudimentary way to do it would be to find the minimum and maximum values, and do this:
double scale = 255.0 / (double)(maxVal - minVal);
for( int i = 0; i < std::min(myVec.size(), myVec2.size()); ++i )
{
myVec2.at(i) = (unsigned int)((double)(myVec.at(i)-minVal) * scale);
}
depending on the distribution of your data, you might need to do something a little more complex to get the most out of your dynamic range.
Edit: This assumes your glut function is creating an image, if it is using the 8-bit value as an input to a graph then you can disregard.
Edit2: An update after your other update. If you want to fill a 640x480x4 vector, you are clearly doing an image. You need to do what I outlined above, but also the 4 dimensions that it is looking for are Red, Green, Blue, and Alpha. The Alpha channel needs to be 255 at all times (this controls how transparent it is, you don't want it to be transparent), as for the other 3... that value you got from the function above (the scaled value) if you set all 3 channels (channels being red, green, and blue) to the same value it will appear as grayscale. For example, if my data ranged from 0-25mm, for a pixel who's value is 10mm, I would set the data to 255/(25-0)* 10 = 102 and therefore the pixel would be (102, 102, 102, 255)
Edit 3: Adding wikipedia link about Brightness Transfer Functions - https://en.wikipedia.org/wiki/Color_mapping
How might I convert it to the format of:
std::vector myVec2; such that myVec2.size() will be twice as
big as myVec.size()?
myVec2.reserve(myVec.size() * 2);
for (auto it = begin(myVec); it!=end(myVec); ++it)
{
uint8_t val = static_cast<uint8_t>(*it); // isolate the low 8 bits
myVec2.push_back(val);
val = static_cast<uint8_t>((*it) >> 8); // isolate the upper 8 bits
myVec2.push_back(val);
}
Or you can change the order of push_back()'s if it matters which byte come first (the upper or the lower).
Straightforward way:
std::vector<std::uint8_t> myVec2(myVec.size() * 2);
std::memcpy(myVec2.data(), myVec.data(), myVec.size());
or with the use of the standard library
std::copy( begin(myVec), end(myVec), begin(myVec2));

OpenGL convert RGBA byte pixels to image integers array

I read pixels from OpenGL texture 2D into byte array (unsigned char) as it is usually done.But now I need to convert it into image array (of Integers I suppose) to have the layout and pixel range of the images loaded from CPU for reverse process.
My question is - is it enough just to to do :
glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_INT,bytes);
instead of :
glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_BYTE,bytes);
and then iterate over each integer and convert it from 0-1 range to 0-255?
I haven't really found any example doing such a conversion without using 3 party image libs.
If I do this :
size_t lenght=_viewWidth * _viewHeight ;
GLubyte *bytes=(GLubyte*)malloc(lenght);
/////////////// read pixels from tex /////////////////////
glBindTexture(GL_TEXTURE_2D,tex);
glGetTexImage(GL_TEXTURE_2D,0,GL_BGR,GL_UNSIGNED_BYTE,bytes);
uint8_t Rc, Gc, Bc;
for(x = 0; x < lenght; x+=3)
{
Bc = *bytes + x;
Gc = *bytes + x + 1;
Rc = *bytes + x + 2;
}
Is Rc , Gc and Bc going to be in the 0-255 range ?
When OpenGL loads a texture, it will convert the incoming pixels into the format provided as the internal format as specified in the glTexImage*() call. This operation may include a mapping step from the pixel format (glTexImage*()'s third parameter) to the internal format, and often includes mapping into one of the ranges [0,1] or [-1,1], and then onto the range for the internal format for each component. For example, a pixel format of GL_FLOAT, and an internal format of GL_RGBA8, will cause the input values to be mapped from the range [0,1] into the range [0,255].
When you retrieve the texels using glGetTexImage(), the process is done in reverse, and so the output pixel values (per component) will be in the range of the specified output type (e.g., GL_UNSIGNED_INT in your case). The range for unsigned ints is [0,232-1], so that will be the range of values returned in your integer image array. If you need those values in a different range (e.g., GL_UNSIGNED_BYTES), then you would need to manually convert values into the range you need.
Personally, if one of the data types OpenGL can return matches the range of values you need, try to use that type.

reinterpret_cast and use with CV_MAT_ELEM

i want to put all the data of an 8 bit input colorimage (Inputfile is a.bmp file)
in a new 16 bit Mat Array.
I do this because i need to sum up several image patches and then build the meanvalue for each pixel.
Mat img = imread(Inputfile); //there now should be values between 0 and 255
Addressing the blue value for example like follows
uchar* ptr = img.data + img.step*row;
cout << ptr[n*col] << endl;
only brings up single Letters and no values.
cout << static_cast<short>(ptr[n*col]) << endl;
Typecasting to short or bigger brings up the correct values. but a cast to unsigned char (which is the correct datatype in my opinion) brings up the same Letters than without any typecast.
Short has 2 Bytes as i know, but a color .bmp should only have 1 Byte color information per channel. As i need to sum up in worst case 81 (smaller 128=7bit) pixel values, i thought the short as a target value would be great.
Any help concerning the right way to get simple access to the 8 bit values and use them in 16bit arrays would be great.
Thank you.
The cast works correct, but if you send an unsigned char into the output stream, it will be interpreted as a character and printed as a character.
Also note that OpenCV already has functionality to convert a matrix to a different datatype. You can even read your image into a matrix of the preferred datatype:
cv::Mat3s img = cv::imread(...);
And it is disregarded to use the data pointer. Read OpenCV documentation on how to access single pixels or rows in a clean fashion (iterators, operator(), operator[]...).

Converting color bmp to grayscale bmp?

I am trying to convert a colored BMP file to gray-scale BMP. The input bmp is 24 bit and I am producing the same 24 bit bmp at the output, only this time in gray-scale.
The code I am using is
for(int x = 0; x < max; x++)
{
int lum;
lum = (r[x]*0.30) + (g[x]*0.59) + (b[x]*0.11);
r[x] = lum;
g[x] = lum;
b[x] = lum;
}
The r, g, b arrays are the RGB color components and I have them in a char *r,*g,*b.
For some reasons I am not getting a clean output. I am attaching the output I am getting with this question, its patchy and contains white and black areas at palces. So what am I doing wrong here?
Is it due to data loss in calculationg of lum or is there something wrong in storing int as a char?
Can gray-scale bmp not be 24 bit? or is it something wrong in the way I am storing rgb values after conversion?
Any help in this will be much appriciated. Thanks.
These should really be unsigned char; if char happens to be signed on your platform, then this code won't do what you expect.
You need to clamp the output of your calculation to be in [0,255]. Your calculation looks ok, but it's always good to be sure.
Also make sure that the r, g, b arrays are unsigned char. You can get away with a lot of signed/unsigned mixing in int (due to 2's complement overflow covering the mistakes) but when you convert to float the signs must be right.

OpenCV: Accessing And Taking The Square Root Of Pixels

I'm using OpenCV for object detection and one of the operations I would like to be able to perform is a per-pixel square root. I imagine the loop would be something like:
IplImage* img_;
...
for (int y = 0; y < img_->height; y++) {
for(int x = 0; x < img_->width; x++) {
// Take pixel square root here
}
}
My question is how can I access the pixel value at coordinates (x, y) in an IplImage object?
Assuming img_ is of type IplImage, and assuming 16 bit unsigned integer data, I would say
unsigned short pixel_value = ((unsigned short *)&(img_->imageData[img_->widthStep * y]))[x];
See also here for IplImage definition.
OpenCV IplImage is a one dimensional array. You must create a single index to get at image data. The position of your pixel will be based on the color depth, and number of channels in your image.
// width step
int ws = img_->withStep;
// the number of channels (colors)
int nc = img_->nChannels;
// the depth in bytes of the color
int d = img_->depth&0x0000ffff) >> 3;
// assuming the depth is the size of a short
unsigned short * pixel_value = (img_->imageData)+((y*ws)+(x*nc*d));
// this gives you a pointer to the first color in a pixel
//if your are rolling grayscale just dereference the pointer.
You can pick a channel (color) by moving over pixel pointer pixel_value++. I would suggest using a look up table for square roots of pixels if this is going to be any sort of real time application.
please use the CV_IMAGE_ELEM macro.
Also, consider using cvPow with power=0.5 instead of working on pixels yourself, which should be avoided anyways
You may find several ways of reaching image elements in Gady Agam's nice OpenCV tutorial here.