Après avoir effectué certains traitements sur un tableau audio ou image, il doit être normalisé dans une plage avant de pouvoir être réécrit dans un fichier. Cela peut être fait comme suit:
# 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)
Existe-t-il une manière moins verbeuse et pratique de faire cela? matplotlib.colors.Normalize()
ne semble pas être lié.
audio /= np.max(np.abs(audio),axis=0)
image *= (255.0/image.max())
En utilisant /=
et *=
vous permet d’éliminer un tableau temporaire intermédiaire et d’économiser de la mémoire. La multiplication est moins chère que la division, donc
image *= 255.0/image.max() # Uses 1 division and image.size multiplications
est légèrement plus rapide que
image /= image.max()/255.0 # Uses 1+image.size divisions
Étant donné que nous utilisons des méthodes numpy de base, je pense que cette solution est aussi efficace que numpy.
Les opérations sur place ne modifient pas le type de données du tableau de conteneurs. Comme les valeurs normalisées souhaitées sont des valeurs flottantes, les tableaux audio
et image
doivent comporter un type de point en virgule flottante avant que les opérations in-situ ne soient effectuées. S'ils ne sont pas déjà de type d à virgule flottante, vous devrez les convertir en utilisant astype
. Par exemple,
image = image.astype('float64')
Si le tableau contient à la fois des données positives et négatives, je choisirais:
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
aussi, mérite d'être mentionné même si ce n'est pas la question de OP, normalisation :
e = (a - np.mean(a)) / np.std(a)
Vous pouvez également redimensionner avec sklearn
. Les avantages sont que vous pouvez ajuster la déviation standard, normaliser, en plus du centrage de la moyenne des données, et que vous pouvez le faire sur un axe, par entité ou par enregistrement.
from sklearn.preprocessing import scale
X = scale( X, axis=0, with_mean=True, with_std=True, copy=True )
Les arguments de mots clés axis
, with_mean
, with_std
s'expliquent d'eux-mêmes et sont affichés dans leur état par défaut. L'argument copy
exécute l'opération sur place s'il est défini sur False
. Documentation ici .
Vous pouvez utiliser la version "i" (comme dans idiv, imul ..), et elle n’a pas l’air mauvais:
image /= (image.max()/255.0)
Dans l’autre cas, vous pouvez écrire une fonction pour normaliser un tableau à n dimensions par des colonnes:
def normalize_columns(arr):
rows, cols = arr.shape
for col in xrange(cols):
arr[:,col] /= abs(arr[:,col]).max()
Vous essayez de min-max mettre à l'échelle les valeurs de audio
entre -1 et +1 et image
entre 0 et 255.
Utiliser sklearn.preprocessing.minmax_scale
, devrait facilement résoudre votre problème.
par exemple.:
audio_scaled = minmax_scale(audio, feature_range=(-1,1))
et
shape = image.shape
image_scaled = minmax_scale(image.ravel(), feature_range=(0,255)).reshape(shape)
note : à ne pas confondre avec l'opération qui met à l'échelle le norme (longueur) d'un vecteur à une certaine valeur (généralement 1), qui est également communément appelé la normalisation.
Une solution simple consiste à utiliser les scalers proposés par la bibliothèque sklearn.preprocessing.
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)
L'erreur X_rec-X sera zéro. Vous pouvez adapter la fonctionnalité à vos besoins, ou même utiliser un détartreur standard. Sk.StandardScaler ()
J'ai essayé de suivre this , et j'ai eu l'erreur
TypeError: ufunc 'true_divide' output (typecode 'd') could not be coerced to provided output parameter (typecode 'l') according to the casting rule ''same_kind''
Le tableau numpy
que je tentais de normaliser était un tableau integer
. Il semble qu'ils déconseillent la conversion de types dans les versions> 1.10
, Et vous devez utiliser numpy.true_divide()
pour résoudre ce problème.
arr = np.array(img)
arr = np.true_divide(arr,[255.0],out=None)
img
était un objet PIL.Image
.