can't access pixel intensities in image using cimg (returns 0) - c++

I'm tries to access Cimg pixel values to print out the pixel intensity that my mouse is at, as well as calculating a histogram. However, I got all zeros from Cimg object.
The cimg image is initiated from memory buffer and it is 12 bit gray scale image, but padded to 16 bit to save in memory.
The code below is defined in a function that is called multiple times. I want to refresh the images in the current display and not to produce a new one every time the function is called. So the Cimgdisp is defined outside the function.
#include "include\CImg.h"
int main(){
CImg <unsigned short> image(width,height,1,1);
CImgDisplay disp(image);
//showImg() get called multiple times here
}
void showImg(){
unsigned short* imgPtr = (unsigned short*) (getImagePtr());
CImg <unsigned short> img(imgPtr,width,height);
img*=(65535/4095);//Renormalise from 12 bit input to 16bit for better display
//Display
disp->render(img);
disp->paint();
img*=(4095/65535);//Normalise back to get corect intensities
CImg <float> hist(img.histogram(100));
hist.display_graph(0,3);
//find mouse position and disp intensity
mouseX = disp->mouse_x()*width/disp->width();//Rescale the position of the mouse to true position of the image
mouseY = disp->mouse_y()*height/disp->height();
if (mouseX>0&mouseY>0){
PxIntensity = img(mouseX,mouseY,0,0);}
else {
PxIntensity = -1;}
}
All the intensities I retrieve are zero and the histogram is also zero.

img*=(4095/65535);//Normalise back to get corect intensities is incorrect, as (4095/65535)=0 in C/C++ (division of an integer by a larger one).
Maybe img*=(4095/65535.); ?

If you just want to scale between 12-bit and 16-bit and back then just using bit-shifts might be better.
img<<=4;//Renormalise from 12 bit input to 16bit for better display
//Display
disp->render(img);
disp->paint();
img>>=4;//Normalise back to get corect intensities

Related

OpenCV image analysis on 32x32 image sections?

Im trying to divide a passed in, 1920x1080, gray scaled image and divide it into 32x32 "blocks" or "sections". Sort of like an imaginary, overlay grid.
Once this is done, I need to loop through each pixel in each individual section to perform analysis on the single channel, gray scale value that is returned by each pixel.
For example:
//For block (x,y):
if (pixelVal >= 120 && pixelVal <= 130) {
bitStream += "1";
} else if (pixelVal >= 135 && pixelVal <= 140) {
bitstream += "0";
} else {
bitStream += "X";
}
Does this make sense? I'm very new to OpenCV and C++ and basically I know how to show, loop through, and return the pixel value at a given point, just not within a certain, predetermined area. I asked a similar question the other day but it was for thresholding, not the single channel value. Im thinking about creating some sort of window that loops through and with each window, the pixel values within are compared using the conditionals I have above.
Since the value of gray scale pixels is already defined from 0-255, so you may create an array of size 256 and pre-fill that array with "0", "1" and "x" as per your conditions. This lookup table would later help you to substitute values very efficiently. This technique is used internally by OpenCV methods such as cv::threshold.
Then you may crop the image using cv::Mat cropped = bigger_mat(rect), where bigger_mat is 1920x1080 dimension matrix and rect is cv::Rect(x, y, w, h) object which defined the position and size for cropping.
Then you can loop each of the cropped mats' using two nested for loops for rows and columns and access each pixel using img.at<uchar>(j,i). For each value retrieved you can use the above created look-up array to get the substitution and append to your bitstream.

How to convert an image with 16 bit integers into a QPixmap

I am working with software that has a proprietary image format. I need to be able to display a modified version of these images in a QT GUI. There is a method (Image->getpixel(x,y)) that returns a 16 bit integer (16 bits per pixel). To be clear, the 16 bit number does not represent an RGB color format. It literally represents a measurement or dimension to that particular point (height map) on the part that is being photographed. I need to take the range of dimensions (integers) in the image and apply a scale to be represented in colors. Then, I need to use that information to build an image for a QPixmap that can be displayed in a Qlabel. Here is the general gist...
QByteArray Arr;
unsigned int Temp;
for (int N = 0; N < Image->GetWidth(); N++) {
for (int M = 0; M < Image->GetHeight(); M++) {
Temp = Image.GetPixel(N,M);
bytes[0] = (Temp >> 8) & 0xFF;
bytes[1] = Temp & 0xFF;
Arr.push_back(bytes[0]);
Arr.push_back(bytes[1]);
}
}
// Take the range of 16 bit integers. Example (14,982 to 16,010)
// Apply a color scheme to the values
// Display the image
QPixmap Image2;
Image2.loadFromData(Arr);
ui->LabelPic->setPixmap(Image2);
Thoughts?
This screenshot is an example of what I am trying to replicate. It is important to note that the coloration of the image is not inherent to the underlying data in the image. It is the result of an application scaling the height values and applying a color scheme to the range of integers.
The information on proprietary image format is limited so the below is guess or thought (as requested) according to explanation above:
QImage img(/*raw image data*/ (const uchar*) qbyteArr.data(),
/*columns*/ width, /*height*/ rows,
/*bytes per line*/ width * sizeof(uint16),
/*format*/ QImage::Format_RGB16); // the format is likely matching the request
QPixpam pixmap(img); // if the pixmap is needed
I found pieces of the answer here.
Algorithm to convert any positive integer to an RGB value
As for the actual format, I chose to convert the 16 bit integer into a QImage::Format_RGB888 to create a heat map. This was accomplished by applying a scale to the range of integers and using the scale to plot different color equations.

Converting float to unsigned char causes wrong values

I've created a function that creates a BMP image using RGB values.
The RGB values are stored as floats that range from 0.0 to 1.0.
When writing the values to the BMP file they need to range from 0 to 255.0 so I multiply the floats by 255.0
They also need to be unsigned chars.
EDIT: Unless one of you can think of a better type.
So basically what I do is this
unsigned char pixel[3]
//BMP Expects BGR
pixel[0] = image.b*255.0;
pixel[1] = image.g*255.0;
pixel[2] = image.r*255.0;
fwrite(&pixel, 1, 3, file);
Where image.r is a float.
There seems to be some kind of loss of data in the conversion because some parts of the image are black when they shouldn't be.
The BMP image is set to 24 bits per pixel
I was going to post images but I don't have enough reputation.
edit:
BMP image
http://tinypic.com/r/2qw3cdv/8
Printscreen
http://tinypic.com/r/2q3rm07/8
Basically light blue parts become black.
If I multiply by 128 instead the image is darker but otherwise accurate. It starts getting weird around 180 ish

how to acces colour of individual pixels using SOIL in cpp

I would like to access the RGB valuas from individual pixels. I know I can get an unsigned char array by calling
unsigned char* pixels = SOIL_load_image(picturename.c_str(), &_w, &_h, 0, SOIL_LOAD_RGB);
However I dont understand what these chars mean. The documentation says:
// The return value from an image loader is an 'unsigned char *' which points
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
// with each pixel consisting of N interleaved 8-bit components; the first
// pixel pointed to is top-left-most in the image. There is no padding between
// image scanlines or between pixels, regardless of format. The number of
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
// If req_comp is non-zero, *comp has the number of components that _would_
// have been output otherwise. E.g. if you set req_comp to 4, you will always
// get RGBA output, but you can check *comp to easily see if it's opaque.
However when I load an 10 by 10 pixels image to test it i get an huge ammound of chars in the array (almost 54000) this seems way too much. How do i get the individual pixel colour that I can do something like this:
int colourvalue = pixel[y*width+x];
i cant seem to find this

getting Y value[Ycbcr] of one Pixel in opencv

I'm trying to get the Y value of pixel from a frame that's in Ycbcr color mode.
here what I' wrote:
cv::Mat frame, Ycbcrframe, helpframe;
........
cvtColor(frame,yCbCrFrame,CV_RGB2YCrCb); // converting to Ycbcr
Vec3b intensity =yCbCrFrame.at<uchar>(YPoint);
uchar yv = intensity.val[0]; // I thought it's my Y value but its not, coz he gives me I think the Blue channel of RGB color space
any Idea how what the correct way to do that
what about the following code?
Vec3f Y_pix = YCbCrframe.at<Vec3f>(rows, cols);
int pixelval = Y_pix[0];
(P.S. I havent tried it yet)
You need to know both the depth (numerical format and precision of channel sample) as well as the channel count (typically 3, but can also be 1 (monochrome) or 4 (alpha-containing)), ahead of time.
For 3-channel, 8-bit unsigned integer (a.k.a. byte or uchar) pixel format, each pixel can be accessed with
mat8UC3.at<cv::Vec3b>(pt);