When i convert a image to YUV from RGB I cant get a value of Y when I try printing the pixels. I get a value 377 and when I cast it with integer I get 255. WHich I presume is incorrect. Is there a better way or rather correct way to print the values of YUV image pixels.
Actually i am priting the values (int)src.at<Vec3b>(j,i).val[0]= 255
and src.at<Vec3b>(j,i).val[0] = 377
Also on that note, the Y is the combination of RGB calculated with some constants according to note. I am actually confused as how to get the value of Y.
This is a problem of OpenCV. OpenCV does not gracefully handle (scale) YUV or HSV color spaces for uchar format. With Vec3b you have effectively 3-channel uchar, and that ranges [0;255].
The solution is to use another matrix type. With cv::Mat3f you have a 3-channel floating point image. Then the values will be correctly converted by cvtColor function. You can get a Mat3f from a Mat3b by assignment.
Another solution that uses less memory may be Mat3s and Mat3w types, if supported by cvtColor.
Related
I have a 2D CNN model where I perform a classification task. My images are all coming from a sensor data after conversion.
So, normally, my way is to convert them into images using the following approach
newsize = (9, 1000)
pic = acc_normalized[0]
img = Image.fromarray(np.uint8(pic*255), 'L')
img = img.resize(newsize)
image_path = "Images_Accel"
image_name = "D1." + str(2)
img.save(f"{image_path}/{image_name}.jpeg")
This is what I obtain:
However, their precision is sort of important. For instance, some of the numerical values are like:
117.79348187327987 or 117.76568758022673.
As you see in the above line, their difference is the digits, when I use uint8, it only takes 117 to when converting it into image pixels and it looks the same, right? But, I'd like to make them different. In some cases, the difference is even at the 8th or 10th digit.
So, when I try to use mode F and save them .jpeg in Image.fromarray line it gives me error and says that PIL cannot write mode F to jpeg.
Then, I tried to first convert them RGB like following;
img = Image.fromarray(pic, 'RGB')
I am not including np.float32 just before pic or not multiplying it by 255 as it is. Then, I convert this image to grayscale. This is what I got for RGB image;
After converting RGB into grayscale:
As you see, it seems that there is a critical different between the first pic and the last pic. So, what should be the proper way to use them in 2D CNN classification? or, should I convert them into RGB and choose grayscale in CNN implementation and a channel of 1? My image dimensions 1000x9. I can even change this dimension like 250x36 or 100x90. It doesn't matter too much. By the way, in the CNN network, I am able to get more than 90% test accuracy when I use the first-type of image.
The main problem here is using which image conversion method I'll be able to take into account those precision differences across the pixels. Would you give me some idea?
---- EDIT -----
Using .tiff format I made some quick comparisons.
First of all, my data looks like the following;
So, if I convert this first reading into an image using the following code where I use np.float64 and L gives me a grayscale image;
newsize = (9, 1000)
pic = acc_normalized[0]
img = Image.fromarray(np.float64(pic), 'L')
img = img.resize(newsize)
image_path = "Images_Accel"
image_name = "D1." + str(2)
img.save(f"{image_path}/{image_name}.tiff")
It gives me this image;
Then, the first 15x9 matrix seems like following image; The contradiction is that if you take a closer look at the numerical array, for instance (1,4) member, it's a complete black where the numerical array is equal to 0.4326132099074307. For grayscale images, black means that it's close to 0 cause it makes white if it's close to 1. However, if it's making a row operation, there is another value closer to 0 and I was expecting to see it black at (1,5) location. If it does a column operation, there is again something wrong. As I said, this data has been already normalized and varies within 0 and 1. So, what's the logic that it converts the array into an image? What kind of operation it does?
Secondly, if I first get an RGB image of the data and then convert it into a grayscale image, why I am not having exactly the same image as what I obtained first? Should the image coming from direct grayscale conversion (L method, np.float64) and the one coming from RGB-based (first I get RGB then convert it to grayscale) be the same? There is a difference in black-white pixels in those images. I do not know why we have it.
---- EDIT 2 ----
.tiff image with F mode and np.float32 gives the following;
I don't really understand your question, but you seem to want to store image differences that are less than 1, i.e. less than the resolution of integer values.
To do so, you need to use an image format that can store floats. JPEG, PNG, GIF, TGA and BMP cannot store floats. Instead, use TIFF, EXR or PFM formats which can handle floats.
Alternatively, you can create 16-bit PNG images wherein each pixel can store values in range 0..65535. So, say the maximum difference you wanted to store was 60 you could calculate the difference and multiply it by 1000 and round it to make an integer in range 0..60000 and store as 16-bit PNG.
You could record the scale factor as a comment within the image if it is variable.
I want to know the difference between imagesc & image in matlab
I used this example to try to figure out the difference beween the two but i couldn't explain the difference in the output images by myself; could you help me with that ?
I = rand(256,256);
for i=1:256
for j=1:256
I(i,j) = j;
end
end
figure('Name','Comparison between image et imagesc')
subplot(2,1,1);image(I);title('using image(I)');
subplot(2,1,2);imagesc(I);title('using imagesc(I)');
figure('Name','gray level of image');
image(I);colormap('gray');
figure('Name','gray level of imagesc');
imagesc(I);colormap('gray');
image displays the input array as an image. When that input is a matrix, by default image has the CDataMapping property set to 'direct'. This means that each value of the input is interpreted directly as an index to a color in the colormap, and out of range values are clipped:
image(C) [...] When C is a 2-dimensional MxN matrix, the elements of C are used as indices into the current colormap to determine the color. The
value of the image object's CDataMapping property determines the
method used to select a colormap entry. For 'direct' CDataMapping (the default), values in C are treated as colormap indices (1-based if double, 0-based if uint8 or uint16).
Since Matlab colormaps have 64 colors by default, in your case this has the effect that values above 64 are clipped. This is what you see in your image graphs.
Specifically, in the first figure the colormap is the default parula with 64 colors; and in the second figure colormap('gray') applies a gray colormap of 64 gray levels. If you try for example colormap(gray(256)) in this figure the image range will match the number of colors, and you'll get the same result as with imagesc.
imagesc is like image but applying automatic scaling, so that the image range spans the full colormap:
imagesc(...) is the same as image(...) except the data is scaled to use the full colormap.
Specifically, imagesc corresponds to image with the CDataMapping property set to 'scaled':
image(C) [...] For 'scaled' CDataMapping, values in C are first scaled according to the axes CLim and then the result is treated as a colormap index.
That's why you don't see any clipping with imagesc.
I have the following matrix:
A = [0.01 0.02; 1.02 1.80];
I want to compress this using JPEG 2000 and then recover the data. I used imwrite and imread in MATLAB as follows:
imwrite(A,'newA.jpg','jp2','Mode','lossless');
Ahat = imread('newA.jpg');
MATLAB give me the result in uint8. After converting data to double I get:
Ahat_double = im2double(Ahat)
Ahat_double =
0.0118 0.0196
1.0000 1.0000
I know this is because of the quantization, but I don't know how to resolve it and get the exact input data, which is what lossless compression is supposed to do.
Converting data to uint8 at the beginning did not help.
The reason why you are not getting the correct results is because A is a double precision matrix. When you are writing images to file in double precision, it assumes that the values vary between [0,1]. In your matrix, you have 2 values that are > 1. When you write this to file, these values will saturate to 1, and then they are saved to file. Actually, before even writing, the intensities will be scaled so that they are uint8 and vary between [0,255]. When you try re-reading the values, it will be read in as intensity 255, or double intensity of 1.0.
The other two values make sense when you read the values back in, as 0.01 in double form is actually 255*0.01 = 2.55 and thus rounded to 3 and 3 / 255 = 0.0118. For 0.02, this is 255*0.02 = 5.1 and thus rounded to 5 and 5 / 255 - 0.0196.
The only way you can possibly get around this is to renormalize your data before you write the image so that it conforms to [0,1]. To get the original data back, you would have to know the minimum and maximum values you had before you normalized this. Even when you do this, there are only 256 possible double precision values that can be encoded in your image (assuming grayscale), and so you will not be able to capture all possible floating point values this way.
As such, there is basically no way around your problem, so you're SOL!
If you want to encode arbitrary data using the JPEG 2000 standard, perhaps you should download this library from MATLAB's File Exchange. I haven't taken a closer look at it, but it may be able to compress arbitrary data using the JPEG 2000 algorithm.
If I have an image, how can I obtain the values of each pixel in that image using matlab
Thanks.
Images are matrices (2D if grayscale, 3D if colored) in MATLAB.
You can use x(i,j) to access a pixel at location (i,j) in a grayscale image.
If the image is colored, you can use x(i,j,:) to access the r, g, b values in a 3-vector, respectively. If you need individual channels, then, you can use x(i,j,1) for red for example.
You may read this page to learn more.
You can use reshape to extract all the pixel values of the image into a vector with pixel values:
frame = imread('picture.jpg');
frame_size = size(frame);
allpixels = reshape(frame, frame_size(1)*frame_size(2), frame_size(3))
This can be useful when you want to vectorize your Matlab code (to avoid a for loop that goes through every pixel). To get back the original image representation:
frame2 = reshape(allpixels, frame_size);
to get the values at pixel(1,1) we simply write image(1,1).
When using the function: D3DXSaveTextureToFile and passing in D3DXIFF_BMP to create a bmp I've noticed that the values seem to be estimated rather than given specifically.
Correct me if I'm wrong but a floating point texture can store any float in any given texel which would put it outside the range of a BMP which is stuck between rgb(255,255,255,255), so what it seems that the function is doing is simply taking the upper most and lowermost value of the texture and normalizing it between that range.
So my question is: Is it possible to grab the values exactly as they are in memory? including when the colours are outside of the spectruc of the computer monitor?
Don't use BMP. Use a format that supports the data type you want. For DX textures, it seems the D3DXIFF_PFM format is what you need. It's described like so:
Portable float map format. A raw
floating point image format, without
any compression. The file header
specifies image width, height,
monochrome or color, and machine word
order. Pixel data is stored as 32-bit
floating point values, with 3 values
per pixel for color, and one value per
pixel for monochrome.
Note that images will be large, though. A 256x256 texture in this format should weigh in at around 768 KB.
Updates: You should be able to use Image Magick's display command to view images in this format. Also HDRView supports the PFM format. A third choice might be fv.