Why a matrix multiply a variable and then be divided by the same variable produce different results?

1 visualización (últimos 30 días)
clear all;
matFilename='./test.tif';
b=mean(mean(imread(matFilename)));
matData1=imread(matFilename)*(b/b); %%line 4
matData2 = imread(matFilename)*b/b; %%line 5
figure;
subplot(1,2,1)
imshow(matData1,[]);
subplot(1,2,2)
imshow(matData2,[]);
Hello, I am confused by the code show above, b is just a number, so why the matrix multiply b and then divide the same b (line 5) would not be the same as the matrix itself (line 4), as the image showed?
The sample image file is attached on the .zip file.
Thanks!

Respuesta aceptada

Stephen23
Stephen23 el 26 de Oct. de 2020
Editada: Stephen23 el 26 de Oct. de 2020
"I am confused by the code show above, b is just a number, so why the matrix multiply b and then divide the same b (line 5) would not be the same as the matrix itself (line 4), as the image showed?"
You have not taken into account operator precedence:
and the behavior of numeric operations on integer data (by which I mean arrays with integer data class, not just whole numbers). These two operations are NOT the same when x has an integer data type (for sake of this argument we assume b is a scalar double):
x*(b/b) % line 4
x*b/b % line 5
Because of operator precedence, "line 4" is equivalent to:
x*(1)
x
but "line 5" is equivalent to
(x*b)/b
which is not the same thing at all because with integer data classes those operations are not associative (we cannot just arbitrarily change the order of the operations, unlike the maths you learned in school) and can over/underflow and lose information. Which for your image data, they certainly do!
For example what happens if we multiply uint8(255) by 1000? Do we get expect to get 255000? No, we do not, because uint8 only supports values from 0 to 255 and the documentation tells us that operations returning a value outside its range simply saturates to its highest value, so we expect the output to be 255. Ditto for underflow.
Lets try it:
>> x = uint8([0,127,255])
x =
0 127 255
>> b = 1000;
>> x*b % all non-zero values saturate to 255!
ans =
0 255 255
>> x*b/b % line 4, all values saturate to 0!
ans =
0 0 0
And for comparison:
>> x*(b/b) % line 5, equivalent to x/1 == x
ans =
0 127 255
If you want to perform those operations in an "arbitrary" order then you will either need to consider the data class very carefully, or simply convert to a floating-point class beforehand**, e.g.:
im = im2double(imread(matFilename)); % convert to floating-point!
b = mean(mean(im));
matData1 = im*(b/b);
matData2 = im*b/b;
** strictly speaking also not completely associative, but close enough in most cases.

Más respuestas (0)

Categorías

Más información sobre Numeric Types en Help Center y File Exchange.

Productos

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by