Universidad politécnica de madrid escuela técnica superior de ingenieros



Descargar 3.96 Mb.
Página22/44
Fecha de conversión18.08.2020
Tamaño3.96 Mb.
1   ...   18   19   20   21   22   23   24   25   ...   44
dir_gram: Es el directorio en el que están las gramáticas de la tarea y, por lo tanto, tiene el mismo valor que el directorio de los diccionarios.




  • regeneraComprensión: Es un flag que indica al sistema la necesidad de generar los dicheros de compresión, es decir, asociar las frases con los comandos por las que deben traducirse una vez sean reconocidas. Si tiene un valor igual a 0, no se regenerará la comprensión y, por lo tanto, el tiempo que tardará el sistema en estar preparado para reconocer será menor. Hay que tener cuidado con este flag porque si se realiza un cambio en el fichero de comandos y el flag está a 0, el sistema no asimilará los nuevos cambios realizados.




  • Locutor: guarda el nombre del usuario que habla al sistema.

Una vez definidas las principales variables de configuración y agrupadas en un único fichero de configuración, también decidimos seleccionamos nueve variables para que se presentasen al usuario del sistema mediante una ventana y éste pudiese modificar su valor, evitando que modifique los valores del fichero “urbano.ini” algo que no sería deseable si se trata de un usuario eventual o inexperto. Las variables seleccionadas para ser presentadas en la ventana de configuración son las siguientes:




  • Tipo de entorno: Mediante un checkBox el usuario puede indicar si se encuentra en un entorno ruidoso o en un entorno no ruidoso. A partir del cuadro seleccionado, el sistema ya internamente asigna a las variables del detector los valores correspondientes al tipo de entorno. Si no se selecciona ninguna de las opciones, se carga la configuración por defecto definida en “urbano.ini”. Para más información, véase [San-Segundo1997]




//vemos que tipo de entorno esta seleccionado

if(m_ruidoso.GetCheck()==BST_CHECKED)

{

nivel_low = 3; //dBs



nivel_speech = 6; //dBs

nivel_high = 9; //dBs


entornoRuidoso=TRUE;

}

else if(m_noRuidoso.GetCheck()==BST_CHECKED)



{

nivel_low = 6; //dBs

nivel_speech = 20; //dBs

nivel_high = 25; //dBs


entornoRuidoso=FALSE;

}

else



{

//Cargamos la configuracion por defecto

double aux, ValorPorDefecto;

char nombreSeccion[MAX_PATH];


sprintf(nombreSeccion,"Linea 0");
// Nivel bajo de energía habla continua.

ValorPorDefecto = 5; // dBs.

if (SIN_ERROR != DameProfileDouble (nom_fich_configuracion,

nombreSeccion, "Nivel low del detector HC",

ValorPorDefecto, &aux, verboseProfile))

warningPrintf_telef("Nivel low del detector: Lectura del *.ini

INCORRECTA");

nivel_low = (int16)aux;


// Nivel de voz habla continua.

ValorPorDefecto = 10; // dBs.

if (SIN_ERROR != DameProfileDouble (nom_fich_configuracion,

nombreSeccion, "Nivel speech del detector HC", ValorPorDefecto,

&aux, verboseProfile))

warningPrintf_telef("Nivel speech del detector: Lectura del *.ini

INCORRECTA");

nivel_speech = (int16)aux;


// Nivel alto de energía habla continua.

ValorPorDefecto = 20; // dBs.

if (SIN_ERROR != DameProfileDouble (nom_fich_configuracion,

nombreSeccion, "Nivel high del detector HC", ValorPorDefecto,

&aux, verboseProfile))

warningPrintf_telef("Nivel high del detector: Lectura del *.ini

INCORRECTA");

nivel_high = (int16)aux;


entornoRuidoso=TRUE;

}


Cuadro 11: Comprobación del tipo de entorno seleccionado y asignación de valores



  • Activación vocal: Mediante un checkBox el usuario indica al sistema si desea que el reconocedor reconozca en cualquier momento o sólo a partir de que haya dicho una frase de activación. El procedimiento a seguir para determinar qué cuadro se ha seleccionado es similar al que se lleva a cabo con el tipo de entorno y, como ocurre también en ese caso, se carga la configuración por defecto de “urbano.ini” en caso de que no se seleccione ningún cuadro.




  • Tipo de comprensión: Mediante esta variable el usuario indica si desea utilizar trigramas como método de compresión o reglas de transformación. El proceso a seguir para determinar el elemento seleccionado es similar a los anteriores.




  • Regeneración de la comprensión: Como hemos indicado antes, esta variable indica al sistema si es necesario repetir el proceso de generación de reglas y trigramas o no. Se implementa también mediante checkBoxes, empleándose el mismo sistema para determinar qué ha seleccionado el usuario y cargando la configuración por defecto en caso de que no haya seleccionado nada.




  • Flexibilidad del reconocimiento: Mediante esta variables se modifica el valor del factor de suavizado. Un reconocimiento flexible significa que el sistema es bastante tolerante para comprender frases que no se encuentren en el conjunto de frases predefinidas. Cuanto más estricto, más se limita la comprensión a las frases predefinidas.

Todas las variables anteriormente descritas se han implementado mediante checkBoxes que ofrecen al usuario los posibles valores que puede tomar ese campo. A continuación se enumeran las variables implementadas mediante cuadros de edición ya que el usuario debe introducir su valor mediante el teclado porque no tienen un número finito de posibilidades:




  • Nombre del usuario: En él se introduce el nombre del usuario que va a interactuar con el sistema.




  • Directorio de tarea: Ruta del directorio que se corresponde con la tarea que va desarrollarse. Ha tenido que ser previamente definido y contener al menos los ficheros que se indicaron en el apartado 4.1.2. La ruta que se introduzca debe terminar con el carácter “ \ ” ya que en caso contrario el sistema no funcionará correctamente.




  • Puerto de reconocimiento: En este cuadro el usuario introduce el número de puerto que utilizará para comunicarse con el cliente.




  • SoundBlaster: Este cuadro permite al usuario indicar cuál es el dispositivo que se corresponde con la tarjeta de entrada de audio.

El aspecto de la ventana de configuración es el siguiente:



Figura 10: Ventana de configuración del sistema


Uno de los principales problemas que se nos presentaron fue conseguir que la ventana de configuración tuviese prioridad sobre el resto de hebras para que los valores introducidos en ella tuviesen alguna efectividad ya que la ventana se lanzaba cuando ya se habían inicializado todas las variables a través de los ficheros de configuración. Para ello, lo que hicimos fue modificar el método de inicialización de la ventana principal del reconocedor en el fichero “robintdlg.cpp”. Antes de que en este método se llamase al método encargado de la inicialización principal, lanzábamos la ventana de configuración de manera que las demás hebras quedasen bloqueadas hasta que se cerrase la configuración.
Dicha ventana sólo se muestra en caso de que el sistema esté funcionando en modo no automático. En caso contrario, se carga la configuración por defecto definida en el fichero “urbano.ini” sin que aparezca ninguna ventana.
Otro de los problemas más importantes que nos surgió en el desarrollo de este método de configuración fue la posibilidad de que el usuario introdujese el número del puerto que se empleará para la comunicación entre cliente y servidor. Si el usuario introducía un puerto diferente al especificado en el fichero de configuración, ignoraba el nuevo valor, quedándose con el definido por defecto. Esto se debía a que antes de comenzar con la inicialización de la ventana de diálogo, se creaba el servidor de manera estática:

CServidor Server;




Cuadro 12: Inicialización original del servidor
La modificación que se ha hecho ha sido crear el servidor como un puntero que se inicializa en el método “inicializaciónPpal” de “robintdlg.cpp” justo antes de lanzar el thread de reconocimiento, pero después de haber configurado el sistema:

server=new CServidor;



server->StartThread();


Cuadro 13: Nueva inicialización del servidor
Una vez configurado el sistema, teníamos que introducir las modificaciones necesarias en “robintdlg.cpp”, fichero en el que se llevan a cabo todas las operaciones relacionadas con la interfaz gráfica del sistema, para que los casos de uso explicados en el capítulo 4 tuviesen aplicación real. Para ello, se ha seguido el siguiente esquema de implementación:


Figura 11: Diagrama de la implementación de los casos de uso

Como puede verse sólo algunas combinaciones de las variables “modoAutomatico”, “adaptacionNecesaria” y “locutor” tiene sentido y son las que se muestran en la figura 9. Hay otras configuraciones carentes de significado como puede ser la siguiente:
modoAutomatico=1

adaptacionNecesaria=1

locutor=carlos
Esta configuración no tendría sentido ya que en el caso de estar activo el modo automático, el sistema ignora el valor de la variable “adaptacionNecesaria” de manera que, aunque esté indicado que es necesario llevar a cabo el proceso de adaptación, el sistema lo ignorará y que está definido el modo automático y éste tiene mayor prioridad que la adaptación.
El proceso de adaptación se explicará con más detalle en el capítulo 6. Para determinar si un usuario es conocido o no se ejecuta el método “buscaLocutor ()” de “robintdlg.cpp” cuya implementación es la siguiente:


int buscaLocutor()

{

char linea[MAXPATH];


FILE* fichero;

if((fichero= fopen(listaLocutores,"r"))==NULL)

warningPrintf("No se puedo abrir el fichero de locutores");
for(int contador=0;feof(fichero)==0;contador++)

{

fgets(linea,100,fichero);


if (strlen(linea)>0)

{

if (linea[strlen(linea)-1]=='\n' ||linea[strlen(linea)-1]=='\r')



{

linea[strlen (linea) - 1] = '\0';

}
}

else


{

linea[0]=0;

}

/* Si alguno de los locutores leidos del fichero coincide con el locutor



actual, devuelve uno indicando que el locutor que esta utilizando el

sistema es conocido*/

if(strcmp(linea,locutorActual)==0)

{

return 1;



}

}
fclose(fichero);


/*Si no ha encontrado ninguna coincidencia en el fichero con el nombre

del locutor actual devuelve cero para indicar que el locutor es

desconocido*/

return 0;

}


Cuadro 14: Implementación del método "buscaLocutor()"

Si el modo automático está activo, el sistema debe encontrar de forma automática los modelos acústicos que debe cargar. En el caso de que el locutor nunca haya trabajado con el sistema es sencillo ya que se emplearán los modelos genéricos que se encuentran en el directorio “data”. La complicación parece si el locutor es conocido, ya que el sistema debe navegar por los directorios personales el locutor y encontrar los modelos adecuados. Para lograrlo se realizan las siguientes operaciones:



if(locutorConocido)

{

char nom_tarea[MAXPATH];



char fich_comandos[MAXPATH];

char micro[MAXPATH];

char dir_micro[MAXPATH];

char entorno[MAXPATH];

char fichero_modelos[MAXPATH];
// Leemos el nombre base del fichero .ini

if (SIN_ERROR!=DameProfileString (nom_fich_configuracion, "GRAMATICA",

"NomFicheroTextoEntrenamiento","robint.txt", fich_comandos, MAXPATH, TRUE))

warningPrintf("en %s falta la sección [GRAMATICA] o la variable

NomFicheroTextoEntrenamiento", nom_fich_configuracion);

strcpy(nom_tarea,fich_comandos);

flhPonerExtension(nom_tarea,"");
/*Leemos del fichero de configuracion el tipo de microfono que usamos*/

if (SIN_ERROR!=DameProfileString (nom_fich_configuracion, "WAV","microfono",

"cable", micro, MAXPATH, TRUE))

warningPrintf("en %s falta la sección [WAV] o la variable microfono",

nom_fich_configuracion);
if(strcmp(micro,"cable")==0)

{

strcpy(dir_micro,"MCC");



}

else if(strcmp(micro,"inalambrico")==0)

{

strcpy(dir_micro,"MCC");



}

if(entornoRuidoso)

{

strcpy(entorno,"ruido");



}

else


{

strcpy(entorno,"noRuido");

}
/*Con todos los elementos creamos el directorio donde estan los modelos del

usuario*/

sprintf(directorio_usuario,"..\\data\\Modelos\\%s\\%s\\%s\\%s",locutorActual

,dir_micro,entorno,nom_tarea);

sprintf(fichero_modelos,"%s\\SpeechDat_Continua_MMF.ascii",directorio_usuario);
/*Antes de asignar definitivamente ese directorio como el directorio en el que

se encuentran los modelos que se van a utilizar, comprobamos si existe y, en

caso contrario,asignamos al directorio de los modelos que definido por

defecto en el fichero de configuracion*/

if((_access(fichero_modelos,0))!= -1)

{

sprintf(directorio_final_modelos,"%s\\",directorio_usuario);



}

else


{

if (SIN_ERROR!=DameProfileString (nom_fich_configuracion, "MODELOS",

"dir_hmm", "..\\..\\datos\\modelos\\", directorio_final_modelos,

STRINGLENGTH, TRUE))

warningPrintf("en %s falta la sección [MODELOS] o la variable

dir_hmm", nom_fich_configuracion);

}

}


Cuadro 15: Proceso para cargar automáticamente los modelos de un locutor conocido

Si nos encontramos en el modo no automático pero no es necesario adaptar, parecerá una ventana emergente para que el usuario seleccione el fichero de modelos que desea cargar. Dicha ventana se abrirá en el directorio “data” si el locutor es desconocido y el la carpeta personal del locutor si ya ha trabajado antes con el sistema realizando el proceso de adaptación. Para crear esa ventana y abrirla en el directorio correcto el proceso es el siguiente:




//creamos una ventana de dialogo para cargar el modelo deseado

CFileDialog filedialog(TRUE,NULL,NULL,OFN_HIDEREADONLY,

"All Files (*.*)|*.*||",this);

//ponemos el titulo

filedialog.m_ofn.lpstrTitle = "Seleccione el modelo a cargar";

sprintf(directorio_usuario,"..\\data\\Modelos\\%s\\",locutorActual);


/*Comprobamos si el directorio que queremos existe y en caso contrario, ponemos el directorio de los modelos por defecto como directorio inicial de apertura de la ventana*/
filedialog.m_ofn.lpstrInitialDir=directorio_usuario;

//creamos la ventana

if (filedialog.DoModal() == IDOK)

{

char driver[MAXPATH];



char fich[MAXPATH];

char extension[MAXPATH];

char dir[MAXPATH];
//si el usuario pulsa el boton "Aceptar" guarda el path del fichero //seleccionado

CString filePath = filedialog.GetPathName();


//separamos los elementos del path para quedarmos solo con el //directorio

_splitpath(filePath, driver, dir, fich, extension);


strcpy(directorio_final_modelos,dir);
flagModeloSeleccionado=TRUE;

}

else



{

//si el usuario no selecciona ningun modelo se carga el directorio por //defecto

if (SIN_ERROR!=DameProfileString (nom_fich_configuracion,

"MODELOS", "dir_hmm","..\\..\\datos\\modelos\\",

directorio_final_modelos, STRINGLENGTH, TRUE))

warningPrintf("en %s falta la sección [MODELOS] o la

variable dir_hmm", nom_fich_configuracion);

flagModeloSeleccionado=TRUE;

}


Cuadro 16: Creación de la ventana para seleccionar el modelo a cargar

Una vez se han cargado los modelos, estará terminado todo el proceso de configuración del sistema, abriéndose la ventana principal del reconocedor y permitiendo al usuario ordenar acciones al robot mediante comandos de voz.

5.- GENERACIÓN AUTOMÁTICA DEL SUBSISTEMA DE COMPRENSIÓN

ADAPTADO A UNA TAREA

Como se explicaba en el capítulo 2, uno de los métodos que empleados en la desambiguación del etiquetado morfosintáctico es aplicar reglas de transformación. En este capítulo se explicará detalladamente el procedimiento por el cual se generan las reglas adaptadas a la tarea que se está realizando.

5.1.- Aproximación al sistema
El sistema tiene definidas 27 funciones para crear reglas de transformación, cada una con un identificador y un número de parámetros concretos, cuya descripción detallada puede verse en el anexo V.
Mediante dichas funciones, se irán generando y probando todas las posibles reglas que se obtengan al combinar los distintos conceptos y palabras que componen el vocabulario de una tarea. El objetivo principal de este proceso es obtener las reglas que mejor asocien una frase dicha por el usuario del sistema con el comando o comandos que lleva asociados y por el que debe ser traducido. De esta manera, las reglas que no den lugar a un elevado porcentaje de acierto serán desechadas.
El empleo de reglas como método de comprensión es lento ya que tiene que comprobar todas las posibles combinaciones de conceptos y palabras hasta obtener las mejores reglas. Además, esto empeora a medida que aumenta el tamaño del vocabulario, pudiendo dar lugar a situaciones en las que el vocabulario tiene un tamaño tan grande que la máquina sobre la que se ejecuta no tiene suficiente capacidad de procesamiento como para obtener todas las reglas.
Pese a este inconveniente, las reglas son una forma fiable de comprensión y traducción de la frase dicha por un usuario.

5.2.- Implementación de la comprensión mediante reglas
En el momento de generar las reglas que permitirán comprender lo que el usuario del sistema está diciendo, traduciéndolo por un comando a partir del fichero de comandos, lo primero que se hace es cargar en la estructura DatosComprension las palabras función, que serán en su mayoría artículos (determinados, indeterminados, posesivos, demostrativos), preposiciones, verbos auxiliares, verbos modales, verbos en modo imperativo, pronombres (personales,interrogativos).Este proceso se realiza mediante el método “cargaPalabrasFuncion”.

5.2.1.- Método “cargaPalabrasFuncion”


Como parámetros se pasa un puntero a la estructura DatosComprension y el nombre del fichero que contiene las palabras función. Estas palabras función son palabras no fiables o irrelevantes para la comprensión, palabras “basura” a partir de las cuales el sistema no debe aprender ninguna regla, especialmente en el caso de que haya pocos ejemplos de los que obtener reglas. Esto es necesario ya que, en caso de que haya pocos ejemplos, el sistema podría aprender reglas a partir de estas palabras, enmascarando otras posibles reglas que serían mucho más fiables o unívocas, puesto que en el momento que se asocia una frase con un concepto, el sistema no vuelve a evaluar la frase para buscar otra palabra más característica a la hora de aislarla para asignarle un concepto.
Una vez disponemos de todas las palabras función del vocabulario, se ejecuta que método “main_ppal” que es el procesador de comprensión y se emplea para aprender y/o aplicar las reglas.
5.2.1.- Método “main_ppal”
Tiene los siguientes argumentos:

1   ...   18   19   20   21   22   23   24   25   ...   44


La base de datos está protegida por derechos de autor ©odont.info 2019
enviar mensaje

    Página principal