Why does the Min-Max normalization produces inaccurate results when used in dtype='<i2' in python

30 Views Asked by At

I am working with a X-Ray image, and I am trying to do a Min-Max Normalization of the image to switch the range of values in the image between [0,1], for further processing. The following is the function that I created for this task.

def MinMaxNormalize(array):
    return (array - np.amin(array))/(np.amax(array) - np.amin(array))

The function works well with any other type of data, but for some reason is producing odd results when using an image of dtype= '<i2'. I am using this type of data based on the manual the manufacturer provided me. I am loading the image the following way:

datasetpath = 'folder_path/'
imagepath = 'Image_folder/'
image_name = 'Fish.raw'

# Specify the dimensions of your image
width = 4096 # specify width of the image
height =  4096# specify height of the image

# Read raw image data
with open(datasetpath + imagepath + image_name, "rb") as f:
    raw_data = np.fromfile(f, dtype='<i2', count=width*height)

# Reshape raw data to match image dimensions
imarray = np.array(raw_data.reshape((height, width)))
image_norm = MinMaxNormalize(imarray)

The image loads well, but the normalization is producing values in the range of [-130,130] and I am getting the following warning:

RuntimeWarning: overflow encountered in scalar subtract
  return (array - np.amin(array))/(np.amax(array) - np.amin(array))

I tried doing manually with each value, but when I do this piece np.amax(array) - np.amin(array) I get the same warning and a non-accurate number, but if I use the raw numerical values there is no problem. Can someone explain to me what am I missing or doing incorrectly?

1

There are 1 best solutions below

0
Cris Luengo On

Your array is of type 16-bit signed integer. Something like this:

array = np.array([-30000, 0, 30000], dtype=np.int16)

When you now compute

np.amax(array) - np.amin(array)

you are subtracting two 16-bit integers, producing again a 16-bit integer:

<stdin>:1: RuntimeWarning: overflow encountered in scalar subtract
-5536

Because the result of 30000 + 30000 doesn't fit in a signed 16-bit integer, you get overflow in the operation. The result is a non-sensical -5536.

Because you want to produce a floating-point image (no integer type can contain data normalized to [0,1]), your easiest way (and maybe most efficient) is to convert the array to a floating-point format first:

array = array.astype(np.float32)

Now you can use in-place operators for the normalization:

array -= np.amin(array)
array /= np.amax(array)