imwrite a double matrix in MATLAB - matlab

How can I imwrite this value [12 13.5; 15 107.75] without changing in imread?
I want to save my information. But if I uint8 this value when I imread this matrix, I have this [12 13; 15 108].

(Let [12 13.5;15 107.75] be A.)
From imwrite documentation:
imwrite(A,filename) writes image data A to the file specified by filename.
If A is of data type uint16 and the output file format supports 16-bit data (JPEG, PNG, and TIFF), then imwrite outputs 16-bit values.
So you can multiply A by 100 then and then convert it to uint16. You will get [1200 1350;1500 10775]. Write it to a (JPEG, PNG, or TIFF) eg.imwrite(A,'image.jpeg').
Now imread('image.jpeg') will return 16-bit integers. Convert them to double and then divide by 100 to get original data. (eg. out = double(imread('image.jpeg'))/100 )
Note: The highest value representable in 16 bits is 65536. So this means that you input after scaling up must have numbers less than 65536 or else you will lose information. If you are using doubles less that 255 with precision 2 or less (two places after decimal) then the highest value after scaling up would be 25599 which is smaller than 65536 so it is fine. Just take care if your input values have a different range or precision.
Still, I think you should write the data in a file using fprintf as suggested by T. Huang.

This cannot be done by imwrite.you may try the fuction fprintf.
http://cn.mathworks.com/help/matlab/ref/fprintf.html

Related

How do I encode NaN values in xarray / zarr with integer dtype?

I have a large xarray DataArray containing NaNs and want to save it with zarr. I want to minimize the file size and am OK with losing a few bits of precision - 16 bits ought to be OK.
I tried using numcodecs.FixedScaleOffset(astype='u2') filter but this stores all NaNs as zero. Since the data also contains zeros as valid values, this is not very helpful.
NumPy's u2 (a.k.a. uint16) does not support NaN values (please this SO answer). Zarr is merely reflecting NumPy's behavior.
It doesn't work with numcodecs.Quantize, but the xarray encoding parameters can specify _FillValue:
dataset.to_zarr(store, encoding={'<array-name>': {'dtype': 'uint16', '_FillValue': 65535}})
See https://xarray.pydata.org/en/stable/io.html#writing-encoded-data

How to convert uint8 to int in Matlab?

I have converted the image from RGB to grayscale and have the image-matrix in uint8. I'm trying to make some image processing with convolution which means that I want to use the values as int when I'm summing up everything. So, how can I convert from uint8 to int in Matlab?
Matlab support multiple integer formats. The main difference is the required space in memory and if the sign (+ or -) is used.
For example, uint8 means that the integer is unsigned and that it uses 8 bit to store the value. The number of used bits determines the maximal value. The uint8 can store a number between 0 and 2^8-1.
You can find a whole list of all supported integer here
If you would like to convert your uint8 into another format you can just write the desired format as a function and pass the value as parameter:
I2 = uint16(I);
In matlab you can use double type.
for example type cast with:
I2=double(I);
It is easy to understand that you can use
int8(I)
int16(I)
too.

Matlab fwrite saturation

I have an image (matrix) that has values on 16 bits, that is between 0 and 65535 and I want to write it in a binary file, so I am using fwrite, as it says in the documentation I have tried to use different precision to write the data on 2 bytes ('integer*2', 'uint16', etc), but it seems that the data gets saturated on 15 bits, that is the maximum value is 0x7ff, if I use more bytes, let's say 4, the data arrives complete, with values greater than 0x7ff and less than 0xffff. I read in the documentation that fwrite saturate the values so there will be no Inf or NaN, does that mean that I can write on x bytes, just (x*8 - 1) bits ?!?
Is there any other way to write the image to a bin file with the correct values on 2 bytes ?
Can you run this code and verify it works on your system?
%generate and show data
IM = uint16(((2^16)-1) .* rand(512));
imagesc(IM);axis image;colorbar
%write data
fid=fopen('image.dat','w');
fwrite(fid,IM(:),'uint16');
fclose(fid);
%read data
fid=fopen('image.dat','r');
IM2=fread(fid,inf,'*uint16');
fclose(fid);
IM2=reshape(IM2,512,512);
%check if they are equal
all(IM(:)==IM2(:))
>> 1
If this works, can you check where it differs from your code?

Why demosaic introduce pixel value greater than the max pixel in raw image?

I read the raw image and check the max value of the pixel(max(rawImage(:))). The max value is 4095. But, after I convert it to color image and check the max value, I get max values greater than 4095 in all 3 channels . Why after using demosaic I get values greater that 4095?
rawImage = uint16(fread(rawFile,[cols rows],'uint16'));
colorImage = demosaic(rawImage,'rggb');
red = colorImage(:,:,1);
green = colorImage(:,:,2);
blue = colorImage(:,:,3);
The docs of demosaic state that, using this syntax:
RGB = demosaic(I, sensorAlignment)
RGB has the same class
as I.
Since you cast rawImage as uint16, colorImage will be uint16 as well and the maximal possible value will be 2^16-1 = 65535
Since demosaic internally performs so many filters; it's natural for the resultant pixel to be greater than the max input value. For some pixels you can have 5001, for others you can get 5023 etc which is quite normal.
In MATLAB when you have a 8 bit data in 8-bit container, it automatically saturates all values greater than 255 to 255. Similarly for a 16-bit data in a 16 bit container it saturates the values to 65535. So it's the container/data type that determines to clip off value and not your data.
Since you have 12 bit data in a 16 bit container, so MATLAB will only saturate a value if it's greater than 65535 and not 4095. What can do is manually saturate all values greater than 4095 to 4095. It won't effect the result.

Matlab precion when specifying fractions

I wanted to create a vector with three values 1/6, 2/3 and 1/6. Obviously I Matlab has to convert these rational numbers into real numbers but I expected that it would maximize the precision available.
It's storing the values as doubles but it's storing them as -
b =
0.1667 0.6667 0.1667
This is a huge loss of precision. Isn't double supposed to mean 52 bits of accuracy for the fractional part of the number, why are the numbers truncated so severly?
The numbers are only displayed that way. Internally, they use full precision. You can use the format command to change display precision. For example:
format long
will display them as:
0.166666666666667 0.666666666666667 0.166666666666667
So the answer is simple; there is no loss of precision. It's only a display issue.
You can read the documentation on what other formats you can use to display numbers.
you can not store values as 1/2 or 1/4 or 1/6 in to a Double variable... these are stored as decimals behind the system; if you want to store these values , try storing it as string that would work;
Whenever you want to make mathematical calculation using these strings then convert the value into number and continue....