1

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?

Dev-iL
  • 22,722
  • 7
  • 53
  • 89
Crossfit_Jesus
  • 99
  • 1
  • 14
  • "_single contains values between 0 and 1_" - that's inaccurate. A `single`-precision variable _may contain_ fractions, but can also contain integers. You should read about the [floating-point representation](https://en.wikipedia.org/wiki/Floating-point_arithmetic) of numbers. – Dev-iL Jul 17 '19 at 08:04

2 Answers2

3

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));
Community
  • 1
  • 1
Dev-iL
  • 22,722
  • 7
  • 53
  • 89
1
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.

Adriaan
  • 15,941
  • 7
  • 35
  • 67