martes, 20 de noviembre de 2012

Reporte de contribución Redes Neuronales

Proyecto: Speaker Recognition System

El proyecto consiste en hacer una red neuronal que sea capaz de reconocer al locutor, y así poder validar que entre al sistema o no. Es decir con solo escuchar la voz de una persona es posible decir si es la persona indicada o no.

Mi contribución se divide en 2 partes, primero continuar con el tratamiento del audio y mejorar los cálculos ya hechos, para poder alimentar la neurona, que consistió en codificar en python formulas matemáticas y trabajo de investigación, segundo la realización de la interfaz para que el usuario pueda acceder al sistema.

Repositorio
Otro link


Entradas de datos:

Se terminó con el tratamiento de la señal que se había dado ya en la primera parte, estos fueron los pasos definitivos y correctos que seguí y que utilizamos para la entrada de la red neuronal.

La Investigación y Codificación del tratamiento de las señales, para poder dar las entradas a la red neuronal.

Extracción de Características

Es el proceso en el que se extrae la información de la señal para poder representar al locutor mediante un modelo propio.
Para representar la señal de la voz se usará el coeficiente MFCC (Mel Frequency Cepstrum Coefficients).
Los MFCC se pueden calcular trabajando en el dominio de la frecuencia.



Tramado y Enventanada: Estos dos pasos tienen como meta disminuir la distorsión, la función de wavfile.read nos da una lista de la señal ya aplicado el tramado y enventanado.

FFT: Se hace la transformada rápida de Fourier, que convierte cada trama de N muestras del dominio temporal al dominio de la frecuencia. El resultado de este paso
se conoce como el espectro de la señal.

Transformación a escala Mel: La percepción humana de las frecuencias no sigue una escala lineal. Por esto se debe hacer un escalado de las frecuencias en Hz a una escala subjetiva conocida como la escala Mel. Se da mayor importancia a la información contenida en las bajas frecuencias en consonancia con el comportamiento del oído humano.

Cepstrum: Se convierte el espectro Log Mel al tiempo. Para esto primero se calcula el logaritmo de SK. Luego como los coeficientes Mel (y su logaritmo) son números reales, se los puede convertir al dominio temporal usando la Transformada Discreta del Coseno (DCT). Este resultado es el que llamamos MFCC.

 Código:

#!/usr/bin/python
import matplotlib.pyplot as plt
from scipy.io import wavfile
import numpy as np
import math
import scipy.fftpack
from pylab import *
GRAFICAS = False
def ampl_tiempo(a):
"""amplitud contra el tiempo
"""
datos = a[1]
amplitud = []
t = np.arange(len(datos))
for i in range(len(datos)):
amplitud.append(a[1][i])
plt.plot(t, amplitud)
plt.title('Analisis de audio',size='large', color='r')
plt.xlabel('tiempo', size='large')
plt.ylabel('amplitud (dB)', size='large')
if GRAFICAS: plt.show()
#print len(amplitud)
return amplitud
def frec(amplitud):
datos_frecuencia = np.fft.fft(amplitud)
#print len(datos_frecuencia)
t = np.arange(len(amplitud))
frecuencia = []
for i in range(len(datos_frecuencia)):
frecuencia.append(abs(datos_frecuencia[i]))
plt.plot(frecuencia, 'r')
plt.title('Fast Fourier Transform',size='large', color='r')
plt.xlabel('Tiempo', size='large')
plt.ylabel('Amplitud (dB)', size='large')
if GRAFICAS: plt.show()
plt.plot(amplitud,frecuencia, 'r')
plt.title('Analisis de audio',size='large', color='r')
plt.xlabel('Frecuencia (Hz)', size='large')
plt.ylabel('Amplitud (dB)', size='large')
if GRAFICAS: plt.show()
return frecuencia
def spect(amplitud):
Pxx, freqs, bins, im= plt.specgram(amplitud)
plt.colorbar(im).set_label(u'Intensidad (dB)')
plt.title('Espectrograma',size='large', color='r')
plt.xlabel('tiempo', size='large')
plt.ylabel('Frecuencia (Hz)', size='large')
if GRAFICAS: plt.show()
def mel(frecuencia, amplitud):
frecuencia.sort()
mel_datos = []
mel_datos_tot = []
n = 20
total_frec = len(frecuencia)
intervalo = total_frec/n
frec_40 = []
for i in range(n):
frec_40.append(frecuencia[i*intervalo])
#print frec_40
#print len(frec_40)
t = np.arange(len(frecuencia))
for i in frec_40:
mel_esc = 2595*(math.log10(1+(i/700)))
mel_datos.append(mel_esc)
#mel_datos.sort()
for i in frecuencia:
mel_esc = 2595*(math.log10(1+(i/700)))
mel_datos_tot.append(mel_esc)
#mel_datos_tot.sort()
######
plt.plot(frec_40, mel_datos)
plt.title('Escala Mel',size='large', color='r')
plt.xlabel('Frecuencia (Hz)', size='large')
plt.ylabel('mels', size='large')
if GRAFICAS: plt.show()
######
c = []
s = True
for i in range(len(frec_40)):
if s == True:
c.append(1)
s = False
else:
c.append(0)
s = True
l = []
f = True
for i in range(len(frecuencia)):
if f == True:
l.append(1)
f = False
else:
l.append(0)
f = True
#####
#print 'mel: ', mel_datos
plt.plot(mel_datos,c)
plt.title('Escala Mel',size='large', color='r')
plt.xlabel('Frecuencia (Hz)', size='large')
plt.ylabel('mels', size='large')
#plt.show()
#####
return mel_datos
view raw gistfile1.py hosted with ❤ by GitHub



La otra parte de mi contribución es la Ventana que verá el usuario cuando entrene la red, se realizó una interfaz sencilla que muestra en la parte principal un texto para que el usuario pueda leerlo, en la parte siguiente un input text para que escriba su nombre de usuario, después botones para iniciar la grabación y otro botón para salir del sistema. Una parte de esto la hizo también mi compañero Roberto Martínez.

También integré el código de la interfaz con el de tratamiento de los datos, para que al grabar el usuario su voz automáticamente se vaya al tratamiento y se pueda meter el dato a la red neuronal y así saber si si es la persona o no lo es. Se importaron las funciones del archivo audio.py que es el que nos ayuda a sacar los datos importantes del audio.

Código:

# -*- coding: utf-8 -*-
#!/usr/bin/python
#Redes neuronales
#7mo Semestre de ITS UANL
#Cecy Urbina, Ramon Gzz, Roberto Mtz
#Interfaz grafica para la entrada de audio, donde el usuario leera un texto
#mientras se graba en un archivo de audio.
from Tkinter import *
import random
import pyaudio
import wave
import sys
import time
import audio
import numpy as np
from scipy.io import wavfile
class Grabadora:
'''Clase que graba el audio de la lectura del texto,
con tres funciones, iniciar, terminar y grabar
'''
def __init__(self):
self.chunk = 1024
self.format = pyaudio.paInt16
self.channels = 1
self.rate = 44100
self.record_seconds = 5
self.p = pyaudio.PyAudio()
self.audio = []
self.stream = self.p.open(format = self.format,
channels = self.channels,
rate = self.rate,
input = True,
frames_per_buffer = self.chunk)
def iniciar(self):
'''Se prepara el archivo para comenzar a grabar y
se graba los segundos indicados
'''
print "* Empezando a grabar . . ."
self.all = []
for i in range(0, self.rate / self.chunk * self.record_seconds):
data = self.stream.read(self.chunk)
self.all.append(data)
def terminar(self, nombre):
'''Se prepara el archivo final y se guarda
en el formato wav con el nombre de temporal
'''
print u'* Terminando'
self.stream.close()
self.p.terminate()
# escribo los datos en el wav
data = ''.join(self.all)
WAVE_OUTPUT_FILENAME = ""+nombre+".wav"
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(self.channels)
wf.setsampwidth(self.p.get_sample_size(self.format))
wf.setframerate(self.rate)
wf.writeframes(data)
wf.close()
def grabar(self, nombre):
'''llama a las funciones para iniciar y
terminar la grabacion
'''
self.iniciar()
self.terminar(nombre)
class Interfaz:
'''Interfaz grafica que muestra el texto que se va a leer
con el boton para comenzar a grabar y para cancelar
'''
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.frame.pack()
self.name = ""
#texto que aparecera para leer
self.texto = Text(self.frame)
self.texto.insert(INSERT, self.leerArchivo())
self.texto.configure(state='disabled', padx=15, pady=15, height=10)
self.texto.grid(row=0, column=0, columnspan=2, sticky=W+E+N+S, padx=15, pady=15)
#para introducir el nombre del usuario
self.e = Entry(self.frame)
self.e.grid(row=1, column=0, columnspan=2, sticky=W+E+N+S,padx=300, pady=15)
#boton que comenzara la grabacion
self.hi_there = Button(self.frame, text="COMENZAR", fg="blue", command=self.grabar)
self.hi_there.grid(row=2,padx=15, pady=15)
#boton para terminar la grabacion
self.button = Button(self.frame, text="CANCELAR", fg="red", command=self.frame.quit)
#self.button = Button(self.frame, text="CANCELAR", fg="red", command=self.error)
self.button.grid(row=2,column=1, padx=15, pady=15)
def grabar(self):
'''graba el archivo wav de audio
'''
time.sleep(1)
grabadora = Grabadora()
self.name = self.e.get()
print self.name
grabadora.grabar(self.name)
datos = self.obtener_datos()
###escribe los datos en un archivo dependiendo del usuario
f = open("datos_entradas", "w")
for i in range(len(datos)):
f.write("%f, " % datos[i])
if self.name == 'cecy':
f.write("0, 0")
elif self.name == "roberto":
f.write("0, 1")
elif self.name == "ramon":
f.write("1, 0")
else:
f.write("1, 1")
f.close()
time.sleep(2)
self.exito()
def error(self):
'''Muestra pantalla de error
'''
x = self.frame.winfo_width()
y = self.frame.winfo_height()
self.frame.destroy()
self.frame = Frame(self.master, width=x, height=y)
self.canvas = Canvas(self.frame, width=x, height=y, bg="white")
self.canvas.create_text(390, 55, text="No identificado", fill="black", font=("Helvectica","15"))
self.canvas.create_text(300, 25, text="Intentalo otra vez!", fill="black", font=("Helvectica","40"))
self.canvas.create_text(125, 200, text=":-(", fill="grey", font=("Helvectica", "200"))
self.frame.pack()
self.canvas.pack(fill=BOTH)
def exito(self):
'''Muestra pantalla de exito
'''
x = self.frame.winfo_width()
y = self.frame.winfo_height()
self.frame.destroy()
self.frame = Frame(self.master, width=x, height=y)
self.canvas = Canvas(self.frame, width=x, height=y, bg="white")
self.canvas.create_text(390, 55,text="Identificado exitosamente", fill="black", font=("Helvectica","15"))
self.canvas.create_text(400, 25,text="Bienvenido!", fill="black", font=("Helvectica","40"))
self.canvas.create_text(125, 200, text=":-)", fill="grey", font=("Helvectica", "200"))
self.frame.pack()
self.canvas.pack(fill=BOTH)
#time.sleep(2)
#self.error()
def leerArchivo(self):
'''lee una archivo de los disponibles
'''
eleccion = random.randint(1, 7)
archivo_elegido = "lecturas/"+str(eleccion)+".txt"
print archivo_elegido
f = open(archivo_elegido, "r")
completo = f.read()
return completo
def obtener_datos(self):
'''manda llamar las funciones del archivo
audio.py, que analiza
'''
a=wavfile.read(""+self.name+".wav")
m = np.fft.fft(a[1])
t = np.arange(110081)
amplitud = audio.ampl_tiempo(a)
frecuencia = audio.frec(amplitud)
audio.spect(amplitud)
datos = audio.mel(frecuencia, amplitud)
return datos
def main():
root = Tk()
App = Interfaz(root)
root.title("Lectura de texto para entrenamiento de la red neuronal")
root.mainloop()
if __name__ == "__main__":
main()
view raw gistfile1.py hosted with ❤ by GitHub



Esta vez mis contribuciones corresponden a los commits: [35, 36, 41, 46, 47]
Y los commits anteriores fueron: [12, 13, 26, 27, 28, 29, 30, 31, 32]

Repositorio:



Gráficas del tratamiento de datos:





1 comentario: