Change uint8 grayscale image to a floating point for learning - matlab

My goal is to make a vector of (1,250x250) for learning in a Neural Network. I am converting 250x250 jpg images to grayscale in matlab. The result is <250x250 uint8>. My question is how do I convert the uint8 vector into float32?

To convert a uint8 type array into 32 bit floating point you can simply:
for_learning = single( gray_imag );
for_learning is a single precision 250x250 image with pixel values in range [0..255]. If you want pixel values to range in the interval [0..1], you simply need to divide it
for_learning = single( gray_imag )/ 255.0;
See single and double for more information

Related

What does the C do in Image Processing's Logarithmic Transformation do?

Log Transform for image is defined as this
s=T(r) = c*log(r+1)
where
s is the output image
r is the input image
c = 255/log(1+Maximum pixel value from the input image).
If the "Maximum pixel value from the input image" is 255 then the C value will be
105.886458025=255/log(256)
This does not make sense. 105.89 is a very high intensity value. Multiplying with this C value will yield a very bright image. Using the 'tire' image from matlab I get the output below:
I=imread('tire.tif');
I2=im2double(I);
J=105*log(1+I2);
imshow(I)
Is my understanding correct?
Image for demonstration
Alternate image
c is a scaling factor.
The following script works both on Matlab and Octave.
clc;
close all;
clearvars;
%imageFileName = 'https://www.forestfoliage.com/wp-content/original/2010_10/Fall-Foliage-mountain-sunset.jpg';
imageFileName = 'https://pixnio.com/free-images/2020/06/27/2020-06-27-11-50-57-1200x800.jpg';
I = imread(imageFileName);
inputMin = min(I(:))
inputMax = max(I(:))
I2 = double(I);
outputMax = 255
c = outputMax/log10(1 + double(inputMax))
J = uint8(double(c) * log10(1 + I2));
%I2(1:5,1:5,:)
%J(1:5,1:5,:)
imshow(I)
title("Raw")
pause(5)
imshow(J)
title("Processed")
im2double documentation:
im2double(I) converts the image I to double precision. I can be a grayscale intensity image, a truecolor image, or a binary image. im2double rescales the output from integer data types to the range [0, 1].
So, we will use double() instead. Thanks to #CrisLuengo for this. Earlier, I was rescaling the scaled output.
In Matlab,
Images stored as matrices of type double should have values in the range [0, 1].
Images stored as integer matrices should have values in the range [0, 255].
On line 12, we are casting the matrix to an integer matrix for this reason.
From the imshow() documentation,
If you specify a truecolor image of data type single or double, then values should be in the range [0, 1]. If pixel values are outside this range, then you can use the rescale function to scale pixel values to the range [0, 1]. The 'DisplayRange' argument has no effect when the input image is truecolor.

How to rescale image data before converting data types

This is a follow up to my previous post here
I'm using the following lines of code to convert the data type(from uint16 to uint8) of z-stack images in MATLAB
%Multiple image tiff conversion%
File_Name = "Test_Image.tiff";
Image_Data = imfinfo(File_Name);
Number_Of_Images = length(Image_Data);
Tiff_Structure = struct('Image_File',[]);
for Image_Index = 1: Number_Of_Images
Image = imread(File_Name,Image_Index);
Uint8_Image = im2uint8(Image);
%For more information and plotting individual images%
Tiff_Structure(Image_Index).Image_File = Uint8_Image;
%Saving the converted images to one tiff file%
imwrite(Uint8_Image,'Converted_Image.tiff','WriteMode','append');
end
In the documentation available here it is mentioned that
im2uint8(I) converts the grayscale, RGB, or binary image I to uint8,
rescaling or offsetting the data as necessary
I would like to know if it is possible to rescale the data before converting the datatype to uint8 and how this rescaling can be done.
Test_Image.Tiff
Suggestions will be really helpful.
EDIT:
Plotting the histogram of the image data gives the following
img_data = imfinfo(f);
n_img = length(img_data);
imgs = cell(1, numel(img_data));
for i = 1:numel(img_data)
imgs{i} = imread(f, i);
end
imgs = cat(3, imgs{:});
figure(1)
imhist(imgs(:), 256)
Assuming Image has values in the range 0-65535 (16bit)
to scale the values into an 8bit image:
first divided the image by 65535 (2^16) - this will normalize value range to 0-1
now you need to rescale to 8bit range of values, multiplying the image by 255
so basically:
scaled_image = uint8(double(Image)./65535*255)
Note: To preserve the dynamic range of the image it might be better to choose a different value to normalize with, e.g some max value across all stack

What is the difference between a uint8 and a single image?

I already know uint8 contains intensity values between 0 and 255 (28-1) and single contains values between 0 and 1, it is used to hold larger values without upsetting the range error. But, apart from that, are there any other differences?
What is the difference between imagesc((I/64)*64) and imagesc((Is/64)*64), where I is uint8 and Is is single?
imagesc just calls image underneath. As for image, it behaves a bit differently if integers or floats are supplied, as can be learned from image's documentation:
If C is of type double, then an RGB triplet value of [0 0 0] corresponds to black and [1 1 1] corresponds to white.
If C is an integer type, then the image uses the full range of data to determine the color. For example, if C is of type uint8, then [0 0 0] corresponds to black and [255 255 255] corresponds to white. If CData is of type int8, then [-128 -128 -128] corresponds to black and [127 127 127] corresponds to white.
...
Converting Between Data Types
To convert indexed image data from an integer type to type double, add 1. For example, if X8 is indexed image data of type uint8, convert it to type double using:
X64 = double(X8) + 1;
To convert indexed image data from type double to an integer type, subtract 1 and use round to ensure that all the values are integers. For example, if X64 is indexed image data of type double, convert it to uint8 using:
X8 = uint8(round(X64 - 1));
To convert true color image data from an integer type to type double, rescale the data. For example, if RGB8 is true color image data of type uint8, convert it to double using:
RGB64 = double(RGB8)/255;
To convert true color image data from type double to an integer type, rescale the data and use round to ensure that all the values are integers. For example, if RGB64 is image data of type double, convert it to uint8 using:
RGB8 = uint8(round(RGB64*255));
I = uint8(255*rand(1e3));
Is = single(I)/255;
tmpI = (I/64)*64;
tmpIs = (Is/64)*64;
% plot for prosterity
% figure;
% subplot(211)
% imagesc(tmpI)
% subplot(212)
% imagesc(tmpIs)
numel(unique(tmpI(:))) % gives 5
numel(unique(tmpIs(:))) % gives 256
Dividing an integer basically means binning of values, and then it stretches the data back to the original extend for plotting. In this case, you get 256/64 = 4 bins, with 0 as well, thus 5 possible values for your uint8 image. However, using single you retain all unique numbers, since the precision is a lot higher.
If you'd do the same test with a lot (order 2^52) elements in the rand and use double you'd see that that again has 2^32 times the number of unique elements of single, just as uint16 will have 2^8 the number of unique elements of uint8.

Convert indexed image colormap to uint8

I'm trying to read colormap of an image using this code:
[X, map] = imread('D:\Eye.png');
But map is rescaled to [0,1] type double. How can I get the colormap in uint8 range [0,255]?
This can be solved by simply rescaling map and casting it to uint8:
uint8(255*map);
Optionally, you can round it before casting (the default rounding scheme, as above, is floor):
uint8(round(255*map));

Image bit-plane decomposition

I was wondering how I could extract bit planes of an image for image compression in MATLAB?
Getting individual bit planes is very easy in MATLAB. Use the bitget function.
bitget takes in an array / matrix of an integral type (uint8, uint16, etc.) and it returns an array / matrix of the same size that gives you the bit at a specified position.
For example, supposing that your image was A of size M x N and you wanted the least significant bit, you would do this:
B = bitget(A, 1);
B would be a M x N matrix where each location gives you the least significant bit for the corresponding pixels in the image. You would change the second parameter from 1 up to as many bits as the type supported to get the desired bit location you want so from 1, the least significant bit, up to K, the most significant bit.
If you wanted all bit planes in a single 3D matrix, that can easily be done in the following way assuming an 8-bit unsigned integer grayscale image stored in A:
B = zeros(size(A, 1), size(A, 2), 8, 'uint8');
for idx = 1 : 8
B(:,:,idx) = bitget(A, idx);
end
This will produce a 3D matrix B of 8 slices where the first slice (B(:,:,1)) denotes the LSB at each pixel location up to the last slice (B(:,:,8)) which denotes the MSB at each pixel location.
Read more about bitget on MathWorks' official documentation on the function: http://www.mathworks.com/help/matlab/ref/bitget.html