Pergunta

Depois de fazer algum processamento em uma matriz de áudio ou imagem, ele precisa ser normalizado dentro de um intervalo antes de ser gravado de volta para um arquivo. Isso pode ser feito assim:

# 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 uma maneira menos detalhada da função de conveniência de fazer isso? matplotlib.colors.Normalize() não parece estar relacionado.

Foi útil?

Solução

audio /= np.max(np.abs(audio),axis=0)
image *= (255.0/image.max())

Usando /= e *= Permite eliminar uma matriz temporária intermediária, economizando alguma memória. A multiplicação é mais barata que a divisão, então

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

é marginalmente mais rápido que

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

Como estamos usando métodos básicos de Numpy aqui, acho que é uma solução tão eficiente quanto possível.


As operações no local não alteram o DTYPE da matriz de contêineres. Como os valores normalizados desejados são flutuantes, o audio e image As matrizes precisam ter o ponto de ponto flutuante DTYPE antes que as operações no local sejam executadas. Se eles ainda não são de Dtype de ponto flutuante, você precisará convertê-los usando astype. Por exemplo,

image = image.astype('float64')

Outras dicas

Se a matriz contiver dados positivos e negativos, eu iria com:

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

Além disso, vale a pena mencionar mesmo que não seja a pergunta do OP, estandardização:

e = (a - np.mean(a)) / np.std(a)

Você também pode redimensionar usando sklearn. As vantagens são que você pode ajustar normalizar o desvio padrão, além de centrar os dados e que você pode fazer isso no eixo, por recursos ou por registros.

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

Os argumentos da palavra -chave axis, with_mean, with_std são auto -explicativos e são mostrados em seu estado padrão. O argumento copy executa a operação no local se estiver definida como False. Documentação aqui.

Você pode usar a versão "I" (como na IDIV, Imul ..), e não parece tão ruim:

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

Para o outro caso, você pode escrever uma função para normalizar uma matriz n-dimensional da Colums:

def normalize_columns(arr):
    rows, cols = arr.shape
    for col in xrange(cols):
        arr[:,col] /= abs(arr[:,col]).max()

Uma solução simples é usar os Sconers oferecidos pela Biblioteca Sklearn.Precessing.

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)

O erro x_rec-x será zero. Você pode ajustar o recurso_Range para suas necessidades ou até mesmo usar um scaler scaler sk.standardscaler ()

Você está tentando escalar min-max os valores de audio entre -1 e +1 e image entre 0 e 255.

Usando sklearn.preprocessing.minmax_scale, deve resolver facilmente seu problema.

por exemplo:

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

e

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

Nota: Não deve ser confundido com a operação que escala o norma (comprimento) de um vetor a um determinado valor (geralmente 1), que também é comumente referido como normalização.

Eu tentei seguir isto, e obteve o erro

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

o numpy Array que eu estava tentando normalizar era um integer variedade. Parece que eles depreciaram o tipo de fundição em versões> 1.10, e você tem que usar numpy.true_divide() para resolver isso.

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

img eram um PIL.Image objeto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top