After simple image decimation using: img_decim_arr = img_arr[::2,::2]
, I obtained histogram very similar to original image histogram:
Decimation using: skimage.measure.block_reduce(img_arr, block_size = (2,2), func=np.mean)
(2x2 block averaging) which is recommended method for downsampling (found on stackoverflow in some discussion) produces very characteristic histogram:
Every second bin is bigger. I am not sure maybe this is due to some aliasing effect. Can anyone please explain and give some theoretical hints about how downsampling affects image (2D signal) histogram?
The problem is the np.mean
function, because it does not round to integers and returns floats.
import numpy as np
import skimage.measure
a = (10 * np.random.randn(10,10) + 127).astype(np.uint8)
a
Out[4]:
array([[121, 124, 139, 129, 130, 114, 127, 96, 114, 135],
[127, 132, 102, 142, 119, 107, 138, 130, 141, 132],
[113, 132, 132, 118, 121, 120, 142, 115, 124, 128],
[127, 121, 129, 129, 121, 119, 126, 113, 128, 116],
[144, 131, 123, 131, 130, 137, 140, 142, 127, 128],
[127, 126, 124, 115, 127, 125, 122, 126, 147, 132],
[118, 119, 117, 117, 133, 149, 122, 120, 116, 138],
[147, 147, 127, 117, 123, 123, 136, 121, 139, 129],
[142, 129, 113, 111, 130, 116, 137, 127, 106, 148],
[132, 141, 141, 142, 119, 132, 126, 115, 131, 122]], dtype=uint8)
b = skimage.measure.block_reduce(a, block_size = (2,2), func=np.mean)
b
Out[6]:
array([[ 126. , 128. , 117.5 , 122.75, 130.5 ],
[ 123.25, 127. , 120.25, 124. , 124. ],
[ 132. , 123.25, 129.75, 132.5 , 133.5 ],
[ 132.75, 119.5 , 132. , 124.75, 130.5 ],
[ 136. , 126.75, 124.25, 126.25, 126.75]])
That might give you interesting side-effects in your own logic. It definitely screws with matplotlibs histogram function, because having floats makes it think differently about how to place the bin borders.
Check this out:
a = (10 * np.random.randn(200,200) + 127).astype(np.uint8)
b = skimage.measure.block_reduce(a, block_size = (2,2), func=np.mean)
hist(b.ravel(), bins=255)
The white bits are actually zero in the array that the hist
function returns. It gets even worse if you force rounding in my toy example:
hist(b.ravel().astype(np.uint8), bins=255)
Giving it the bins and the range solves the problem. Even if you zoom close
hist(b.ravel().astype(np.uint8), bins=255, range=(0,255))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With