How can I imwrite a double in Matlab? - matlab

I am producing 3500x7500 size double matrices in a loop that I want to export as tif files.
A section of the code
for k = 1:length(basinlist{1})
#some operation that produces GRID
imwrite(GRID,filename);
end
But, when I do this, the TIF file produced contains only 255 and output is in uint8. I read about it in the documentation, but I am not able to fix it. All I want is to retain the original values with no scaling or anything.
If this helps:
>> max(max(GRID))
ans =
1.5646e+04
>> min(min(GRID))
ans =
1.1119e+03

Suppose we want to create image with such colour depth that will fit to given data.
Data exported to image format are converted to uint8 by default (data range 0-2^8-1).
But Matlab (2011b) can operate with more uintX formats where X stands for X bits per value.
uint8 with span 0-255 (2^8)
uint16 with span 0-65 535 (2^16)
uint32 with span 0-4.29 e 9 (2^32)
uint64 with span 0-1.84 e 19 (2^64)
Code to export data without any loss:
for k = 1:length(basinlist{1})
#some operation that produces GRID
%% Convert GRID to roughest acceptable uint format
GRID=uint16(GRID);
%% Export
imwrite(GRID,filename);
end

Related

The format type of reading a matrix from a file?

I saved a matrix in a file.txt; the type of matrix is as follow:
file: 0.010993,0.21973,0.012142,0.49897,0.24634,0.01183
When I open the matrix by using
Matrix= dlmread( 'File.txt') ) ;
The matlab take only 4 number after the point, where Matrix:
Matrix: 0.0110 0.2197 0.0121 0.4990 0.2463 0.0118
I don't want to change the numbers after the matrix.
Checking the Workspace:
Without any change and simply checking variable Matrix in the workspace window reveals that the full values are stored and that MATLAB is simply choosing to only display a specific amount of digits:
Matrix = dlmread('File.txt')
Changing the Display Format:
If you configure the display format to long you will see that MATLAB does extract all the decimals within the text file and can display them in the command window. Also opening up array Matrix in the workspace panel and clicking the cells also verifies that all the decimal numbers are taken into account. For more details on display options: Matlab Documentation: Set Command Window Output Display Format.
Note: "Numeric formats affect only how numbers appear in Command Window output, not how MATLABĀ® computes or saves them".
format long
Matrix = dlmread('File.txt')
Extension: Checking Sum
format long
Matrix = dlmread( 'File.txt') ;
sum(Matrix)
sum([0.010993,0.21973,0.012142,0.49897,0.24634,0.01183])
Google Calculator Check
Taking VPA Sum:
format long
Matrix = dlmread('File.txt') ;
sum(vpa(Matrix))
sum(vpa([0.010993,0.21973,0.012142,0.49897,0.24634,0.01183]))
Playground Script:
Testing different display methods and approaches to taking the sum().
x = [0.010097,0.19957,0.011086,0.49413,0.27437,0.010745];
sum(vpa(x))
x = [0.010097000000000 0.199570000000000 0.011086000000000 0.494130000000000 0.274370000000000 0.010745000000000];
sum(vpa(x))
%%
format short
x = [0.010097,0.19957,0.011086,0.49413,0.27437,0.010745];
sum(x)
x = [0.010097000000000 0.199570000000000 0.011086000000000 0.494130000000000 0.274370000000000 0.010745000000000];
sum(x)
%%
format long
x = [0.010097,0.19957,0.011086,0.49413,0.27437,0.010745];
sum(x)
x = [0.010097000000000 0.199570000000000 0.011086000000000 0.494130000000000 0.274370000000000 0.010745000000000];
sum(x)
Ran using MATLAB R2019b

collapse cell array to text matlab

it's a basic question I guess (but I'm new to Matlab), but given:
>> class(motifIndexAfterThresholds)
ans =
'double'
with :
16
8037
14340
21091
27903
34082
as the contents of that variable
I hoped to print to the same line on the matlab console the contents of that variable and some other output:
fprintf('With threshold set to %d, %d motifs found at positions %f.\n',threshold,length(motifIndexAfterThresholds), motifIndexAfterThresholds);
When I do this however, I'm getting more than one line of output:
With threshold set to 800, 6 motifs found at positions 16.000000.
With threshold set to 8037, 14340 motifs found at positions 21091.000000.
With threshold set to 27903, 34082 motifs found at positions
Can someone share the method for collapsing this double array to a single line of text that I can display on the Matlab console please?
What you need is the num2str function that is builtin MATLAB. Modify your code as below:
strThresholds = num2str(motifIndexAfterThresholds.', '%f, '); % Transpose used here since you need to make sure that motifIndexAfterThresholds is a row vector
fprintf('With threshold set to %d, %d motifs found at positions %s.\n',threshold,length(motifIndexAfterThresholds), strThresholds);
The num2str function will convert your vector to a string with the specified format. So for your given example,
strThresholds = '16.000000, 8037.000000, 14340.000000, 21091.000000, 27903.000000, 34082.000000,'
You could definitely edit the format string used in the num2str funcion to suit your needs. I would suggest using %d since you have integers in your vector

Convert a Matrix of doubles to a grayscale .tif image

I have an nCol by nRow matrix of doubles that I want to convert into an nCol by nRow grayscale images of pixels. I don't want to cut this down to an image scaled to 256 channels. I'd be happy with using singles instead of doubles. I've looked through the Tiff class documentation from Mathworks but can't find a simple example for this.
I tried to read about Tiff class and yep it is very poor documented. But I found this going through trial and error:
lets say we have matrix
data = rand(100,200);
Lets save it as Tiff:
t = Tiff('new.tif','w') %create object of Tiff class
setTag(t,Tiff.TagID.ImageLength,size(data,1)) %define image dimentions
setTag(t,Tiff.TagID.ImageWidth,size(data,2))
setTag(t,'Photometric', Tiff.Photometric.MinIsBlack) %define the color type of image
%specifies how image data components are stored on disk
setTag(t,'PlanarConfiguration',Tiff.PlanarConfiguration.Chunky);
setTag(t,'BitsPerSample',64); %because 1 double = 8byte = 64bits
%Specify how to interpret each pixel sample (IEEEFP works with input doubles)
setTag(t,'SampleFormat',Tiff.SampleFormat.IEEEFP);
t.write(data)
t.close
Lets test this now:
datac = imread('new.tif')
whos datac
Name Size Bytes Class Attributes
datac 100x200 160000 double
And:
datac(:,1)
ans =
0.4921
0.6908
0.1544
0.4433
...

Matlab is opening a pgm image with different values using imread

I have a pgm image with 1251 different pixel values, ranging from 0 to 1250. I know this because I can open this image file with kate and see the values.
But when I open the same file using Matlab's imread, it also returns me 1251 different pixel values, but these values are not consecutive. The minimum value is 0 and the maximum value is 65483.
I want to iterate through these values in a for loop so I need to read the original and consecutive values as they exist in the file. How to do that in Matlab?
EDIT: That's the image if someone wants to try.
image
The values are scaled so that when you view the image it's not mostly black.
I tested that the scaling works with straight integer truncation by checking that:
[A] = imread( 'myfile.pgm', 'pgm' );
p = sort(unique(A(:));
q = uint16((0:1250) * 65535 / 1251)';
all(p == q) % returns 1
So, you can restore the image like this:
map = arrayfun( #(x) uint16(x * 1251 / 65536), 0:65535 );
B = arrayfun( #(x) map(x+1), A );

Matlab rgb2hsv dimensions

I am reading in the matlab documentation that rgb2hsv will return an m-by-n-by-3 image array, yet when I call it, I get a 1-by-3 vector. Am I misunderstanding something?
Here is an sample code:
image_hsv = rgb2hsv('filepath')
and as output
image_hsv =
0.7108 0.3696 92.0000
You cannot call rgb2hsv on a filepath - it must be called on a MATLAB image matrix. Try:
image_rgb = imread('filepath'); % load the image array to MATLAB workspace
image_hsv = rgb2hsv(image_rgb); % convert this array to hsv
You can see these matrices with:
>> whos image* % display all variables whose name begins with 'image'
Name Size Bytes Class Attributes
image_hsv 480x640x3 7372800 double
image_rgb 480x640x3 921600 uint8
What your original code was doing was converting your filepath string to ascii numbers, taking the first three values of this array as RGB values and converting these to HSV.
NOTE: This example highlights dangers with MATLAB's weak typing system, where data types are silently converted from one type to another. Also maybe a lack of correct input checking to the rgb2hsv function.