dynamic
dynamic

Reputation: 48131

Matlab im2double normalization inconsistencness?

Can you explain the inconsisent behaviour of matlab im2double function?
Basically this function given as input a matrix A of int it normalizes the values in the range 0...1:

Example:

I1 = reshape(uint8(linspace(1,255,9)),[3 3])
I2 = im2double(I1)

I1 =

    1   96  192
   33  128  223
   65  160  255


I2 =

    0.0039    0.3765    0.7529
    0.1294    0.5020    0.8745
    0.2549    0.6275    1.0000

But now If i provide a matrix of double:

I1 =

    0.1000    0.2000
    1.5000    2.2000

The result of im2double is the same matrix I1 (so without any normalization). Can I understand this inconsisent behaviour?

Upvotes: 3

Views: 3839

Answers (2)

nimrodm
nimrodm

Reputation: 23829

The image processing toolbox supports two different representations of images. Images may be stored as integer RGB values (usually 8 bit 0..255 values). Or they may be stored as real numbers in the range 0..1.

im2double ensures you have the 2nd type of representation -- in case you want to treat the image as a real array and perform various mathematical operations on it.

So if the image is already of type double it has its values in the range 0..1 and no need to do anything. If its not, then the function converts the input to real and rescales it by multiplying by 1/255.

Upvotes: 4

Rody Oldenhuis
Rody Oldenhuis

Reputation: 38042

Type help im2double. The first few lines are

IM2DOUBLE takes an image as input, and returns an image of class double. If the input image is of class double, the output image is identical to it. If the input image is not double, IM2DOUBLE returns the equivalent image of class double, rescaling or offsetting the data as necessary.

So the behavior is intended. Indeed, when opening im2double.m in the editor, you'll see

function d = im2double(img, typestr)
...
if isa(img, 'double')
    d = img;
...

end

Whether it is intuitive, well, that's debatable :)

Anyway, there's a good reason for this behavior. With inputs of type int8 you know what the ceiling is (255). With that information you can re-scale the output (values/255). Similar for int16 (values/65535), etc.

However, when you're given a double, you don't have a realistic ceiling anymore. For most double values, values/realmax << realmin, so there's little sense in re-scaling.

You could argue that 255 would be a good default to scale to, with a warning saying that if 16-bit data is intended, you should give an extra argument or so. But well...that gets ugly and makes the function needlessly complicated. I for one can understand Mathworks' decision to keep the original in such events.

Upvotes: 4

Related Questions