How to normalize a NumPy array within a specific range?

After performing some processing in an array of audio or images, it must be normalized within the range before it can be written back to the file. This can be done like this:

# Normalize audio channels to between -1.0 and +1.0 audio[:,0] = audio[:,0]/abs(audio[:,0]).max() audio[:,1] = audio[:,1]/abs(audio[:,1]).max() # Normalize image to between 0 and 255 image = image/(image.max()/255.0) 

Is there a way to do this in more detail, more convenient? matplotlib.colors.Normalize() does not seem to be relevant.

+99
python arrays numpy scipy convenience-methods
Nov 14 '09 at 17:52
source share
7 answers
 audio /= np.max(np.abs(audio),axis=0) image *= (255.0/image.max()) 

Using /= and *= eliminates the intermediate temporary array, thereby saving some memory. Multiplication is cheaper than division, therefore

 image *= 255.0/image.max() # Uses 1 division and image.size multiplications 

a little faster than

 image /= image.max()/255.0 # Uses 1+image.size divisions 

Since we use the basic numpy methods here, I think this is about as effective a numpy solution as it can be.

+113
Nov 14 '09 at 18:22
source share

If the array contains both positive and negative data, I would go with:

 import numpy as np a = np.random.rand(3,2) # Normalised [0,1] b = (a - np.min(a))/np.ptp(a) # Normalised [0,255] as integer c = 255*(a - np.min(a))/np.ptp(a).astype(int) # Normalised [-1,1] d = 2.*(a - np.min(a))/np.ptp(a)-1 

It is also worth mentioning, even if this is not an OP issue, standardization :

 e = (a - np.mean(a)) / np.std(a) 
+36
Jul 08 '17 at 7:08
source share

You can also scale with sklearn . The advantage is that you can adjust the standard deviation normalization, in addition to the average data center, and that you can do this on any axis, by function or by record.

 from sklearn.preprocessing import scale X = scale( X, axis=0, with_mean=True, with_std=True, copy=True ) 

The keyword arguments axis , with_mean , with_std are self-evident and appear in their default state. The copy argument performs an in-place operation if it is set to False . The documentation is here .

+35
Jan 17 '14 at 20:53
source share

You can use version "i" (as in idiv, imul ..), and it doesnโ€™t look half bad:

 image /= (image.max()/255.0) 

Otherwise, you can write a function to normalize an n-dimensional array with colums:

 def normalize_columns(arr): rows, cols = arr.shape for col in xrange(cols): arr[:,col] /= abs(arr[:,col]).max() 
+11
Nov 14 '09 at 18:04
source share

A simple solution is to use the scaling offered by the sklearn.preprocessing library.

 scaler = sk.MinMaxScaler(feature_range=(0, 250)) scaler = scaler.fit(X) X_scaled = scaler.transform(X) # Checking reconstruction X_rec = scaler.inverse_transform(X_scaled) 

Error X_rec-X will be zero. You can customize feature_range for your needs or even use the standard sk.StandardScaler () scanner

+3
Feb 21 '18 at 2:59
source share

I tried to do this and got an error

 TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind'' 

The numpy array I was trying to normalize was an integer array. They seem to be deprecated of type dropping in versions> 1.10 , and you need to use numpy.true_divide() to solve this problem.

 arr = np.array(img) arr = np.true_divide(arr,[255.0],out=None) 

img was a PIL.Image object.

+2
May 14 '18 at 6:50
source share

You are trying min-max to scale the audio values โ€‹โ€‹between -1 and +1 and image between 0 and 255.

Using sklearn.preprocessing.minmax_scale should easily solve your problem.

eg:

 audio_scaled = minmax_scale(audio, feature_range=(-1,1)) 

as well as

 shape = image.shape image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape) 

Note : This should not be confused with an operation that scales the norm (length) of a vector to a specific value (usually 1), which is also commonly called normalization.

+2
Apr 05 '19 at 1:08
source share



All Articles