The following code snippet results a double image.
f = imread('C:\Users\Administrator\Desktop\2.tif');
h = double(f);
figure;
imshow(h);
whereas, this other code snippet results a uint8 image.
f = imread('C:\Users\Administrator\Desktop\2.tif');
figure;
imshow(f);
While displaying these two figures, the displayed results of these two images using imshow are different, but what is the reason behind this difference?
Images of type double are assumed to have values between 0 and 1 and uint8 images are assumed to have values between 0 and 255. Since your double data contains values between 0 and 255 (since you simply cast it as a double and don't perform any scaling), it will appear as mostly white since most values are greater than 1.
You can use the second input to imshow to indicate that you would like to ignore this assumption and automatically scale the display to the dynamic range of the data
imshow(h, [])
Or you can normalize the double version using mat2gray prior to displaying the image
h = mat2gray(h);
imshow(h)
Related
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.
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.
The following code snippet results a double image.
f = imread('C:\Users\Administrator\Desktop\2.tif');
h = double(f);
figure;
imshow(h);
whereas, this other code snippet results a uint8 image.
f = imread('C:\Users\Administrator\Desktop\2.tif');
figure;
imshow(f);
While displaying these two figures, the displayed results of these two images using imshow are different, but what is the reason behind this difference?
Images of type double are assumed to have values between 0 and 1 and uint8 images are assumed to have values between 0 and 255. Since your double data contains values between 0 and 255 (since you simply cast it as a double and don't perform any scaling), it will appear as mostly white since most values are greater than 1.
You can use the second input to imshow to indicate that you would like to ignore this assumption and automatically scale the display to the dynamic range of the data
imshow(h, [])
Or you can normalize the double version using mat2gray prior to displaying the image
h = mat2gray(h);
imshow(h)
I have to save the image. But when I try and keep the dimensions same, pixel values change. Is there any way to keep both intact.
C=imread('download.jpg');
C=rgb2gray(C);
%convert to DCT
[r1 c1]=size(C);
CDCT=floor(dct2(C));
dct=floor(dct2(C));
[r c]= size(dCipherText);
bye=c; %lenght of message bits
for i=r1:r1
for j=c1:-1:c1-28
.....%some operation on CDCT
end
end
imshow(idct2(CDCT),[0 255])
i=idct2(CDCT);
set(gcf,'PaperUnits','inches','PaperPosition',[0 0 c1 r1])
print -djpeg fa.jpg -r1
end
Don't use print to save the picture.
Use:
imwrite(i,'downdload_dct.jpg')
print will use the paper dimensions etc defined on your figure, rather than the image data itself. imwrite uses the data in i. You don't need imshow if you just want to re-save the image.
--
Update - sorry I see now that when you mean 'scaling', you don't mean the scaling of the picture but of the pixel values, and converting back from scalars to a colour. imshow only "scales" things on the screen, not in your actual data. So you will need to do that manually / numerically. Something like this would work, assuming i is real.
% ensure i ranges from 1 to 255
i = 1 + 254*(i-min(i(:))*(max(i(:))-min(i(:))) ;
% convert indices to RGB colour values (m x n x 3 array)
i = ind2rgb(i,jet(256));
not tested!
I have a image which generated from 4 images. Each image has different type as the code
nrow=256;
ncol=256;
%% Image with double type
I1=randi(256,[nrow ncol]);
%% Image with float type in range
r2 = randn(nrow*ncol,1);
I2=reshape(r2,[nrow ncol]);
I3=I2.*20;
%% Binary image
I4=randi([0 1],[nrow ncol]);
%% make row images
I_int=[I1;I2;I3;I4]
imshow(I_int,[]);
However, the imshow can not show the above I_int image. It only show the image I3 and I2, while other I1,I4 are black. How can I use imshow to show above image with its detail? Thank all
First of all, the datatypes of your variables are not different (I'm a little confused why you think they are). It is always a good idea to use class to check this.
cellfun(#class, {I1, I2, I3, I4}, 'uni', 0)
'double' 'double' 'double' 'double'
The difference in display intensity is because the dynamic range of each of your subimages is very different.
I1 between 1 and 256
I2 between 0 and 1
I3 between 0 and 20
I4 between 0 and 1
As a result, when you combine them and display them using imshow, imshow (with the second input specified as []) sets axes clims to fit the min and max of your data. So black is set to 0 and white is 256. Because of this, I2 and I4 will appear mostly black since all of their pixels are between 0 and 1 which is much less than 256.
To fix this, you could normalize all the data (using mat2gray) prior to concatenation and display.
I_int = cat(1, mat2gray(I1), mat2gray(I2), mat2gray(I3), mat2gray(I4));
Alternately, you could display each of these images in their own axes where they will get their own clims that match their dynamic range.