Landim Tiago Rafael Giorgetti TCC
Landim Tiago Rafael Giorgetti TCC
Landim Tiago Rafael Giorgetti TCC
São Carlos
2017
TIAGO RAFAEL GIORGETTI LANDIM
São Carlos
2017
AUTORIZO A REPRODUÇÃO TOTAL OU PARCIAL DESTE TRABALHO,
POR QUALQUER MEIO CONVENCIONAL OU ELETRÔNICO, PARA FINS
DE ESTUDO E PESQUISA, DESDE QUE CITADA A FONTE.
6
7
ABSTRACT
8
9
Sumário
1. Introdução ........................................................................................................................18
1.1. Motivação ..................................................................................................................19
1.2. Objetivo .....................................................................................................................19
1.3. Justificativa ...............................................................................................................19
1.4. Organização do trabalho ..........................................................................................19
2. Embasamento Teórico.....................................................................................................20
2.1. Raspberry Pi..............................................................................................................20
2.2. Linux Embarcado ......................................................................................................20
2.3. Python .......................................................................................................................21
2.4. Descrição do Projeto ................................................................................................21
2.5. Reconhecimento de Voz...........................................................................................23
2.6. Conversão de texto para fala ...................................................................................26
2.7. MARF .........................................................................................................................26
3. Materiais e Métodos .........................................................................................................28
3.1. Instalação Raspbian e configurações iniciais ........................................................28
3.2. Wit.ai ..........................................................................................................................29
3.3. Flite ............................................................................................................................29
3.4. Jasper ........................................................................................................................29
3.5. Configuração das preferências do usuário.............................................................29
3.6. Módulos .....................................................................................................................30
3.7. Arquivos de sistema .................................................................................................31
3.8. Piwho .........................................................................................................................32
3.9. Treinamento do de modelos ....................................................................................32
4. Discussões .......................................................................................................................34
4.1. get_time() ..................................................................................................................34
4.4. WriteDown.py ............................................................................................................36
4.5. ReadFile.py................................................................................................................38
4.6. Movies.py ..................................................................................................................38
4.7. RecordAudio.py ........................................................................................................39
4.8. Recognition.py ..........................................................................................................40
4.9. Turn_Light_ON.py Turn_Light_OFF.py ...................................................................41
10
4.10. CreateSpeaker.py ..................................................................................................43
5. Resultados .......................................................................................................................48
5.1. Módulos de fala-para-texto e texto-para-fala ..........................................................48
5.2. Módulos implementados ..........................................................................................49
5.3. Identificação de usuário ...........................................................................................49
6. Conclusões..........................................................................................................................63
Referências .............................................................................................................................64
Apêndices................................................................................................................................67
11
Lista de Figuras
12
13
Lista de Gráficos
Gráfico 1: Média das distâncias para conjunto 1 x treinamentos para usuário „TIAGO‟ .............55
Gráfico 2: Média das distâncias para conjunto 2 x treinamentos para usuário „TIAGO‟ .............57
Gráfico 3: Média das distâncias para conjunto 3 x treinamentos para usuário „TIAGO‟ .............57
Gráfico 4: Média das distâncias para conjunto 4 x treinamentos para usuário „TIAGO‟ .............58
Gráfico 5: Média das distâncias para conjunto 5 x treinamentos para usuário „TIAGO‟ .............59
Gráfico 6: Média das distâncias para conjunto 1 x treinamentos para usuário „LUIS‟ ................60
Gráfico 7: Média das distâncias para conjunto 2 x treinamentos para usuário „LUIS‟ ................61
Gráfico 8: Média das distâncias para conjunto 3 x treinamentos para usuário „LUIS‟ ................61
Gráfico 9: Média das distâncias para conjunto 4 x treinamentos para usuário „LUIS‟ ................62
14
15
Lista de Tabelas
Tabela 1: Distâncias médias para cada conjunto em relação à quantidade de modelos treinados
- TIAGO ....................................................................................................................................54
Tabela 2: Taxa eficiência do reconhecimento de acordo com o número de modelos treinados 56
Tabela 3: Distâncias médias para cada conjunto em relação à quantidade de modelos treinados
- LUIS .......................................................................................................................................59
16
17
1. Introdução
18
1.1. Motivação
1.2. Objetivo
1.3. Justificativa
19
2. Embasamento Teórico
2.1. Raspberry Pi
20
2.3. Python
21
Figura 2: Diagrama do sistema
22
Por fim, todo o conteúdo armazenado no sistema, como resultado dos comandos, pode
ser visualizado numa página na web. São informações contidas no website: dados acerca do
projeto, fotos, áudios gravados, e a lista de comandos a serem realizados. Também pode ser
visualizado na página as tentativas de acesso sem permissão, quando uma voz não registrada
tenta ter acesso a alguns métodos, a imagem uma imagem é capturada e o horário é salvo.
Levando em conta esses fatos, a dificuldade em se trabalhar com voz se deve a alguns
aspectos:
23
noz / nós, acento / assento, manga (fruta / parte da camisa que cobre os braços), e em
inglês: red / read, them all / the mall, dentre outros.
● A estrutura gramatical e a semântica das palavras.
24
Figura 4: Conversão de fala para texto
25
2.6. Conversão de texto para fala
2.7. MARF
26
frequências do espectro de voz, obedecendo a lei de Nyquist. Outros formatos de áudio como
.MP3 não estavam implementados na versão do MARF utilizado neste projeto.
O treinamento possui uma primeira etapa de pré-processamento. Essa etapa do MARF
normaliza as amplitudes dos arquivos de áudio a serem treinados, elas devem permanecer no
intervalo [-1.0, 1.0]. A normalização é necessária para garantir que todas as vozes
permaneçam no mesmo nível.
A próxima etapa é a extração das características, realizada através de pequenas
porções da amostra da voz. A partir dessas pequenas porções é que são extraídas as
características da voz. Essa divisão é feita garantindo que a amplitude diminua gradativamente
conforme se aproxima dos extremos. Essa técnica de cortar a amostra em pedaços menores
para ser analisada é chamada de janela. Uma técnica de extração das características é o
Linear Predictive Coding (LPC). Essa técnica avalia as seções das formas de onda da fala
determinando um conjunto de coeficiente. Esse método possui um armazenamento limitado de
dados.
Os desenvolvedores do framework informam que a configuração que apresenta a
melhor taxa de treinamento e reconhecimento corresponde à utilização do pré processamento
com o algoritmo Endpoint, e a extração das características com a técnica LPC.
Essas duas etapas são realizadas tanto no processo de treinamento como de
identificação. No treinamento as características extraídas das amostras de áudio são
armazenadas para posterior comparação.
No reconhecimento a amostra a ser identificada tem suas características extraídas, em
seguida utiliza-se um método de classificação para determinar a proximidade entre as
características da amostra analisada e as do modelo treinado a ser comparado. Este valor é
chamado de distância e está contido no intervalo [0,1]. Quanto mais próximo de 0, mais
próximas são as características umas das outras e, quanto mais próximo de 1 menor a chance
de pertencerem ao mesmo indiívuo.
A Distância de Chebyshev é o método mais indicado para classificação. Sua
representação matemática é dada por:
27
3. Materiais e Métodos
Aa plataforma de código aberto Jasper foi utilizada como base para o projeto. Contendo
a configuração inicial de integração dos mecanismo de conversão de fala para texto com o Flite
para conversão de texto para áudio e, a busca dos códigos em Python a serem desenvolvidos.
28
3.2. Wit.ai
3.3. Flite
3.4. Jasper
29
Para a utilização do mecanismo de conversão de fala para texto escolhido, Wit.ai, foi
necessário obter um token de acesso diretamente do website do grupo. Para converter texto
em fala foi utilizado o mecanismo Flite.
O arquivo contendo as definições do usuário ficou no seguinte formato:
stt_engine: witai
witai-stt:
access_token: XXXXXXXXXXXXXXXXXXXXX
tts_engine: flite-tts
flite-tts:
voice: 'slt'
3.6. Módulos
WORDS = [“RANDOM”]
No método isValid(input) são definidos quais inputs são válidos, isso significa que
retorna True caso o input esteja relacionado com something e False caso contrário.
def isValid(text):
return bool(re.search(r'random', text, re.IGNORECASE))
Qualquer palavra utilizada no isValid deve também ser adicionada na lista WORDS.
30
A seguinte seção de código requisita o método handle(input, mic, profile), sendo input
relacionado com a fala, mic é o objeto do microfone utilizado para capturar a voz e, profile
refere-se às informações do usuário contidas em profile.yml.
message = random.choice(messages)
mic.say(message)
Cinco frases foram definidas para serem aleatoriamente ditas quando requisitada a
ação. Elas são armazenadas em messages para posteriormente serem escolhidas
aleatoriamente através de random.choice(messages). Em seguida o programa envia a frase
escolhida para ser transformada de texto para fala em mic.say.
Para iniciar o sistema o arquivo jasper.py deve ser executado, nele as informações
contidas no profile do usuário são carregadas para checar as configurações. O arquivo de
execução determina quais mecanismos de conversão de fala para texto e texto para fala se
deve utilizar baseado no que está definido no profile.
O arquivo conversation.py fica em execução infinitamente até que o Jasper seja
encerrado. Sua função é identificar as palavras-chave que o usuário disse ou se simplesmente
não houve nenhum comando.
O arquivo brain.py é responsável por cruzar as referências do input do usuário com a
lista de módulos. A ordem dos módulos importa, a execução é finalizada assim que o primeiro
módulo que contém o entrada informado é encontrado. Por isso os módulos são organizados
de acordo com sua prioridade, e esta deve ser definida dentro do código de cada módulo. A
31
entrada obtida pelo microfone é comparada com as possíveis palavras-chave (WORDS) de
cada módulo.
3.8. Piwho
Piwho é uma biblioteca gratuita e open source desenvolvida por Aditya Khandkar. A
biblioteca é baseada no framework MARF para uso em Raspberry Pi. Foi utilizada para o
treinamento dos usuários e o reconhecimento de voz.
32
0,NOME_DO_USUÁRIO_1,ARQUIVO_DE_TREINAMENTO_1.wav|ARQUIVO_DE_TR
EINAMENTO_2.wav|ARQUIVO_DE_TREINAMENTO_3.wav|
1,NOME_DO_USUÁRIO_2,ARQUIVO_DE_TREINAMENTO_4.wav|
2,NOME_DO_USUÁRIO_3,ARQUIVO_DE_TREINAMENTO_5.wav|
O reconhecimento indica o quão próximo o áudio está para cada modelo treinado. É
atribuído ao áudio analisado o modelo que mais aproxima suas características de voz.
33
4. Discussões
Esta seção trata dos módulos desenvolvidos em Python para este projeto.
4.1. get_time()
O primeiro módulo trata-se da obtenção da data e hora atual. Essa função não
implementa o reconhecimento de fala, porém foi é utilizada nas aplicações CaptureImage,
RecordAudio e CreateSpeaker.
Para este modulo utiliza-se o a biblioteca datetime. A classe datetime.datetime
corresponde a combinação de data e hora, com os atributos: year, month, day, hour, minute,
second, microsecond. No inicio do script a biblioteca deve ser importada.
import datetime
year = str(now.year)
if(now.month<10):
month = '0' + str(now.month)
else:
month = str(now.month)
if(now.day<10):
day = '0' + str(now.day)
else:
day = str(now.day)
if(now.hour<10):
hour = '0' + str(now.hour)
else:
34
hour = str(now.hour)
if(now.minute<10):
minute = '0' + str(now.minute)
else:
minute = str(now.minute)
if(now.second<10):
second = '0' + str(now.second)
else:
second = str(now.second)
4.2. Search.py
Uma biblioteca em Python para realizar buscas no site do wikipedia foi utilizado. Sua
utilização é relativamente simples. Através da entrada por voz, a aplicação procura na
plataforma do Wikipedia o assunto determinado, retornando o sumário da pesquisa. A função
wikipedia.summary(name, sentences=2) realiza a pesquisa, onde, name corresponde ao
assunto a ser buscado e sentences à quantidade de parágrafos iniciais do sumário. O resultado
da busca é por fim convertido em áudio.
4.3. CaptureImage.py
import pygame
import pygame.camera
from pygame.locals import *
pygame.init()
pygame.camera.init()
35
A câmera deve ser aberta e inicializada para que em seguida um frame seja capturado.
A câmera é encontrada em /dev/video0, e sua resolução máxima é de 352x288 pixel.
cam = pygame.camera.Camera("/dev/video0",(352,288))
cam.start()
image = cam.get_image()
A imagem é salva e, ao final, a câmera deve ser liberada. A variável “name” indica com
qual nome que a imagem será armazenada.
pygame.image.save(image, name)
cam.stop()
Nesta aplicação as imagens são salvas com a data e hora da captura do frame, sendo
name o retorno da função get_time().
4.4. WriteDown.py
O sistema faz uma pergunta sobre o que deve ser escrito e escuta a resposta. Essa
resposta, atribuída à response é do tipo unicode caso algo seja pronunciado. É realizada uma
checagem sobre o tipo de response. Caso seja unicode, a frase dita pelo usuário será escrita
em uma linha do arquivo de texto, caso contrário nada será escrito.
36
bool = type(response) is unicode
if(bool):
f.write(response + '\n')
else:
mic.say('You said nothing')
mic.say('Anything else?')
response = mic.activeListen()
bool = type(response) is unicode
if(bool==True):
.
.
.
else:
mic.say('Nothing else to write down')
Uma resposta afirmativa permite que mais frases sejam adicionadas ao arquivo de
texto. A resposta é afirmativa se corresponder a palavra “YES”. Essa identificação é realizada
pela função def yes(text), que funciona da mesma forma que a identificação das palavras-
chave. Ao identificar que contém a afirmação na frase, a função retorna o valor verdadeiro.
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
Com uma resposta afirmativa o script continua, é perguntando o que deve ser
adicionado no arquivo, a resposta é escutada e, novamente, se for do tipo unicode (significando
que foi identificado uma fala) é escrita, caso contrário o sistema informa que nada foi dito. Logo
em seguida mais uma vez é perguntado ao usuário se deseja continuar adicionando no arquivo
de texto. Para uma resposta afirmativa, o sistema continua o procedimento de escrita.
Enquanto a resposta for afirmativa, contendo a palavra “YES”, sistema permanece em loop
escrevendo no arquivo.
while yes(response):
mic.say('What else would you like me to write down?')
response = mic.activeListen()
bool = type(response) is unicode
if(bool):
37
f.write(response + '\n')
else:
mic.say('You said nothing')
mic.say('Anything else?')
response = mic.activeListen()
4.5. ReadFile.py
Esta função realiza a leitura de um arquivo de texto previamente armazenado. Uma vez
identificada a palavra-chave “READ” na fala do usuário, o sistema pergunta o nome do arquivo
a ser lido. A fala do usuário deve conter apenas o nome do arquivo, caso a fala pronunciada
não corresponda a nenhum arquivo armazenado, o sistema informa que ocorreu um erro em
sua operação. A resposta é ouvida através do comando fileName = mic.activeListen(). A
variável fileName contém o nome do arquivo buscado, seu conteúdo é convertido para letras
minúsculas e então o arquivo é aberto e lido pelo sistema.
fileName = fileName.lower()
name = os.path.join('/home/pi/NoteFiles', fileName + ".txt")
f = open(name, "r")
content = f.read()
mic.say(content)
f.close()
mic.say('This is everything written in this file')
Ao fim do programa o arquivo é fechado e é informado que todo seu conteúdo foi lido.
4.6. Movies.py
38
from imdb import IMDb
Para esta pesquisa, a frase dita pelo usuário deve conter uma das palavras-chave:
“Movie” ou “Movies”. Após o sistema identificar uma das duas palavras-chave, é requisitado
que o usuário informe o filme desejado. Apenas o nome do filme deve ser recebido pela função
mic.activeListen(), caso contrário tudo o que for dito será admitido como o título de um filme. A
consulta é realizada pela função IMDb().search_movie(name), onde name é a variável que
armazenou o conteúdo de mic.activeListen(). Essa primeira consulta retorna vetor de cinco
filmes cujo título contenham o que estava armazenado em movie_name. O tamanho deste
vetor foi definida arbitrariamente.
O sistema retorna por voz um título que contenha o que estava armazenado em
movie_name e pergunta se este era o filme desejado. Assim como foi feito no script
WriteDown.py, a função def yes(text) retorna verdadeiro para uma frase que contenha a
palavra “YES”, senão retorna valor falso.
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
Uma vez confirmado o título, é realizada outra consulta no banco do IMDb para
recuperar as informações do filme. Oito informações são recuperadas: título, nota da avaliação,
duração em minutos, gênero, sinopse, diretores, produtores e elenco. Como os filmes contém
um grande número de integrantes nas suas categorias (diretor, produtor e elenco), foi definido
um limite de três pessoas por categoria. Ao final da consulta todas essas informações são
convertidas em áudio.
Há a possibilidade de o vetor resultante da primeira consulta não retornar o título
desejado, para este caso o usuário não deve confirmar nenhum dos títulos, desta forma o
sistema informará que não foi possível encontrar o filme requisitado.
4.7. RecordAudio.py
Para essa função ser ativada é necessário que duas palavras-chave sejam
pronunciadas em seguida.São elas: “RECORD” e “AUDIO”. O sistema informa uma mensagem
39
de erro caso a fala contenha uma palavra ou mais entre record e audio. Uma vez reconhecida
as palavras-chave, o sistema pergunta ao usuário o que deve ser gravado. A resposta é ouvido
pelo métod recordListen().
record = mic.recordListen()
O método mic.recordListen() possui a mesma estrutura do método mic.activeListen(),
porém com algumas diferenças em seu código. O tempo que o usuário pode falar é de 180
segundos em recordListen(), isso permite frases maiores e que um pensamento inteiro possa
ser armazenado sem quebras. Como os arquivos de áudio devem ser armazenados para
posterior consulta, o método get_time() é utilizado, desta forma não há conflito de mais de um
áudio com o mesmo nome.
Por fim o sistema informa que o áudio foi gravado com sucesso.
mic.say('Audio recorded')
4.8. Recognition.py
Inicialmente deve-se importar o módulo Piwho para poder utilizar seus métodos.
A palavra-chave que a fala deve conter para acessar essa função é “RECOGNIZE”.
Inicialmente o sistema solicita ao usuário pronunciar qualquer frase, esta frase é escutada pelo
método mic.activeListen(). A frase é salva em um arquivo de áudio no diretório
„/home/pi/recordings/Reconhecer‟ no formato .WAV com o seguinte nome:
„recordingToRecognize.wav‟. A classe SpeakerRecognizer() do módulo recognition é atribuído
à variável recog.
40
Para determinar a identidade do locutor, é passado como parâmetro o caminho para o
arquivo de áudio em que foi salvo a fala do indivíduo. O método identify_speaker identifica a
pessoa do arquivo de áudio passado como parâmetro de acordo com as identificações contidas
em speaker.txt e modelo treinado. O método retorna uma lista com as pessoas cujas
características de voz mais se assemelham às características analisadas no arquivo de áudio
informado. O usuário com as características mais próximas está na posição zero da lista. À
variável name é, primeiramente, atribuída uma lista vazia, em seguida name recebe a lista de
usuários identificados. Caso o indivíduo que não esteja adicionado ao banco de dados em
speaker.txt, então o primeiro nome contido na lista será o do usuário do banco cujas
características são as mais próximas às do áudio. O nome contido em name[0] é então
pronunciado pelo sistema, finalizando o script.
name = []
name = recog.identify_speaker('/home/pi/recordings/Reconhecer/recordingToRecognize.wav')
person = name[0]
mic.say(„You are ‟ + person)
RPi.GPIO é uma biblioteca em Python que permite o controle das porta GPIO da
Raspberry Pi. Esta biblioteca já vem inclusa na versão do Raspian.
A porta GPIO (General Purpose Input/Output) são basicamente pinos que permitem a interface
entre a Raspberry e o exterior, fazendo a comunicação de entrada e saída de sinais digitais.
Estão localizados numa das extremidades da placa, próximos da saída de vídeo e, há um total
de 26 pinos. A figura 4 exibe o posicionamento de cada pino.
41
Figura 5: Pinagem da porta GPIO
Fonte: Simple Guide to the RPi GPIO Header and Pins. Disponível em: <
http://www.raspberrypi-spy.co.uk/2012/06/simple-guide-to-the-rpi-gpio-header-and-pins/>
Acesso em: 22 mar. 2017
Quando definidos como Input, os pinos podem ser ligados ou desligados externamente,
quando definidos como Output, os programas da placa que definem quando os pinos estão
ligados ou não.
Três funções foram desenvolvidas para interfacear o sistema com um elemento externo,
no caso o elemento consiste de uma lâmpada. Um dos programas é utilizado para o
acionamento da iluminação, outro para o desligamento da mesma e, o último possibilita tanto
acender quanto desligar a lâmpada. O interfaceamento entre a Raspberry e a iluminação
ocorre através da porta GPIO conectada a um módulo de relé.O relé suporta cargas de até 10A
em 125VAC ou 250VAC.
O módulo de relé possui três pinos de entradas para a conexão com a Raspberry Pi
(VCC, GRD, IN), sendo o sinal de acionamento do relé recebido pela entrada IN. Outras três
entradas para a conexão com os equipamentos elétricos, que são: NA (Normalmente Aberto),
C (Comum), NF (Normalmente Fechado). Um dos terminais do soquete é conectado ao
Comum, e pela entrada NA é feita a ligação com a tomada. O outro terminal do soquete
também é conectado à tomada. O pino 7 da porta GPIO quando configurado como saída fecha
o circuito entre NA e C, acionando a lâmpada. Para a porta configurada como entrada, o
circuito abre fazendo a lâmpada se apagar.
42
Deve-se importar a biblioteca para utilizar RPi.GPIO no script em Python:
Após esta configuração inicial, foi necessário determinar o modo do pino (entrada ou
saída). Foi definido o pino 7 como saída pelo comando: GPIO.set(7, GPIO.OUT). Como último
passo dessa função, deve-se escrever o nível lógico no pino (alto ou baixo). Ao setar o pino
com GPIO.output(7, HIGH) fornece uma tensão de 3.3V ligando o LED, já o comando
GPIO.output(7, LOW) desliga o LED ao enviar 0V.
4.10. CreateSpeaker.py
Este módulo trata da criação de um novo usuário, este usuário passará a ter permissão
para a leitura dos arquivos de texto salvos. Apenas um usuário principal, pré determinado,
possui permissão para registrar novos indivíduos. O sistema inicia o processo perguntando se
há permissão para a criação de novos usuários. As características da voz de resposta são
comparada com as características salvas de „TIAGO‟ na função permissionGranted(). Se o
valor da distância entre essas características for menor do que 0,30, a função retorna
verdadeiro, se for maior que 0,30, retorna falso.
def permissionGranted():
#Recognize the speaker, if the speaker is TIAGO, then return TRUE otherwise return
FALSE
recog = recognition.SpeakerRecognizer()
name = []
name =
recog.identify_speaker('/home/pi/recordings/Reconhecer/recordingToRecognize.wav')
while x == False:
if dist.keys()[i] == 'TIAGO':
value = dist.values()[i]
x = True
else:
43
i=i+1
if float(value) < 0.30:
return True
else:
return False
Uma vez obtida a permissão é perguntado o nome do novo usuário e é requisitado que
o novo usuário pronuncie duas frases. Essas duas frases correspondem às amostras que a
serem utilizadas para o treinamento de suas características. Ao fim deste processo o novo
usuário é adicionado no arquivo speaker.txt e seu modelo de treinamento ao arquivo .gzbin.
Caso a permissão não tenha sido garantida, o horário da tentative de acesso é
adicionada ao arquivo de texto permissionIntruder e, uma imagem do indivíduo que requisitou o
acesso é capturada. Essas informações podem ser posteriormente conferidas na página
Intrusos do website.
4.11. Webpage
Neste item sera explicado a interação entre a página web e a Raspberry Pi. Para a
programação web foram utilizadas as linguagens PHP e HTML 5. Um template foi utilizado
como base do código. O servidor utilizado para a webpage foi o Apache, um servidor web livre.
Todos os arquivos utilizados na página foram transferidos para o diretório „/var/www/html‟. Na
figura 6 tem-se uma imagem da página principal do site, nela há algumas informações sobre o
projeto. Também contém 3 links de redirecionamento para outros endereços, estes links
correspondem à: Imagens, Arquivos e Intrusos. Além destes 3 ainda há o link Home que
redireciona o usuário para a página principal do site.
44
Figura 6: Página inicial do website
45
A página Arquivos (ver Figura 8) realiza o mesmo procedimento de Imagens. Os
conteúdo dos arquivos de texto armazenados no diretório „home/pi/NoteFiles‟ são exibidos em
sequência, começando do arquivo mais recente.
Por fim, o último link corresponde à página Intrusos (ver figura 9). Essa página é
responsável por exibir todos os indivíduos sem permissão que tentaram acessar algum módulo
restrito, como é o caso de ReadFile.py e CreateSpeaker.py.
Essa página se divide em dois segmentos. No primeiro são exibidos os módulos que algum
indivíduo sem autorização tentou realizar o acesso e, o horário em que a tentativa ocorreu.
Essas informações estavam salvas no arquivo de texto permissionIntruder.txt, adicionadas
pelos módulos citados acima. A segunda seção desta página contém as imagens capturadas
no momento da tentativa de acesso. O objetivo das informações contidas nessa página o
controle do acesso ao sistema. Nada será exibido na tela caso não tenha ocorrido nenhuma
tentativa de acesso aos módulos restritos.
46
Figura 9: Tela da página Intrusos
47
5. Resultados
Neste momento cada etapa do projeto é avaliada, desde o reconhecimento de voz com
o modulo Jasper, passando pelos scripts desenvolvidos e até a identificação de voz com o
Piwho.
Inicialmente o mecanismo de conversão de fala para texto utilizado foi o Google Speech
API. Foram realizados testes online no sistema do Google para analisar a resposta e a eficácia
do mecanismo. A primeira situação envolvia falas no idioma inglês ao mesmo tempo em que
ruídos ocorriam no ambiente. Em nenhum momento eles foram identificados como palavras ou
causaram falhas na identificação das palavras. Em uma segunda situação, músicas eram
tocadas ao fundo e, novamente, apenas as palavras ditas pela pessoa foram convertidas em
texto, a música não causou nenhuma tipo de interferência.
Apesar de apresentar o melhor desempenho em relação aos outros mecanismos, o uso
da API foi descontinuado no projeto, isso ocorreu devido à sua limitação. Para se utilizar
gratuitamente a API existe um limite de 60 minutos de áudio a ser convertido por mês. Como o
projeto requer o uso contínuo desta função, mecanismo Wit.ai. teve que ser implementado.
Percebeu-se que em alguns momentos a palavra “JASPER” não é corretamente
reconhecida. Essa falha de reconhecimento ocorre para indivíduos cujo idioma nativo não é o
inglês. O sistema do Google foi utilizado para estes testes. Como a voz produzida corresponde
à um nativo, não ocorrem falhas no reconhecimento.
O sistema de conversão de texto Flite cumpriu sua função com sucesso em todas as
situações em que foi necessitado. Durante todo o desenvolvimento do projeto, o Flite não gerou
respostas de voz erradas para nenhum dos módulos desenvolvidos. Em todas as suas
chamadas, os textos foram convertidos em áudio corretamente e sem pausas, erros ou
alterações na voz definida.
48
5.2. Módulos implementados
Para o método de busca no Wikipedia foram realizados testes para conferir o tempo de
resposta da função. É de interesse para o usuário do sistema que o tempo de espera seja o
menor possível.
Para uma internet com velocidade de 14Mb/s, os resultados aproximados foram de 18
segundos, 13 segundos.
A demora no tempo de resposta pode ser atribuída à limitações tanto de hardware como
da velocidade da internet.
Para o método WriteDown.py, de escrita em arquivos de texto, o sistema reconhece
erroneamente a palavra “RIGHT” ao invés de “WRITE”. Como essa falha ocorre regularmente o
script WriteDown.py foi alterado para ser admitida qualquer uma das palavras-chave: “WRITE”
e “RIGHT”. Além da semelhança na pronúncia das duas palavras, esse erro ocorre também
devido ao sotaque de um usuário cuja língua nativa não é inglês.
No método de obtenção de informações sobre um filme em específico, a busca é
realizada pela internet, pois essa é a única forma possível de se ter acesso ao banco do IMDb.
As estatísticas do próprio IMDb apontam que seu banco contém um total de 4.293.589 títulos,
iniciando no ano de 1874. Ao observar este número e, considerando que são realizadas duas
vezes a consulta ao banco, já era esperado que a busca e comparação dos títulos não
retornasse as informações rapidamente.
A primeira consulta, pelos cinco filmes, demorou 8 minutos e 33 segundos. A consulta
pelas informações do filme específico demorou um tempo de 10 minutos e 2 segundos.
A quantidade de informações requisitadas, como gênero, duração, produtores, elenco,
etc, não afeta no tempo. O tempo depende da busca no banco e, como esperado, é necessário
um tempo em minutos para percorrer um banco com milhões de elementos.
Alguns testes foram realizados a fim de avaliar a eficiência do sistema. Para os testes,
foram utilizados dois usuários: „TIAGO‟ e „LUIS‟.
Os testes para a identificação do usuário foram realizados utilizando um total de 22
amostras de áudio. Essas 22 amostras se dividem em 5 conjuntos:
49
Conjunto 2. 3 arquivos correspondem à falas do usuário „LUIS‟;
Conjunto 3. 7 arquivos correspondem à falas de indivíduos não registrados;
Conjunto 4. 3 arquivos correspondem à fragmentos de músicas;
Conjunto 5. 2 arquivos correspondem à falas em português do usuário „TIAGO‟
O teste teve como objetivo determinar como a quantidade de modelos treinados para
um mesmo usuário afeta sua identificação. 7 situações foram testadas, sendo incremental o
número de treinamentos para o usuário „TIAGO‟ e limitado a 3 modelos treinados para o
usuário „LUIS. Os testes são os seguintes:
Inicialmente, o treinamento realizado utilizou apenas uma amostra para cada usuário.
Para cada um dos 5 conjuntos de arquivos de áudio, foi calculada a distância entre as
características da amostra treinada do usuário „TIAGO‟ e as características cada amostras dos
conjuntos.
50
Figura 10: Distâncias entre as características de cada amostra e as características do usuário
51
Figura 11: Distâncias média entre as características de cada amostra e as características do
usuário
Para continuar a análise, foi realizado o segundo teste, em que foram treinados duas
amostras para cada usuário. Os mesmo cinco conjuntos de amostras foram utilizados
novamente, as distâncias entre as características cada uma de suas amostras de cada
conjunto e as características do usuário „TIAGO‟.
Mais uma vez foi realizada a média entre as distâncias das amostras para cada
conjunto, obtendo-se novas 5 distâncias, correspondentes às distâncias entre as características
de cada conjunto e as características do usuário.
As etapas descritas anteriormente foram realizadas até para o restante das 7 situações,
incrementando o número de modelos de treinamentos para o usuário „TIAGO‟.
52
Figura 13: Distâncias médias entre as características de cada amostra e as características do
usuário para treinamentos com de 1 à 7 modelos
53
Tabela 1: Distâncias médias para cada conjunto em relação à quantidade de modelos treinados -
TIAGO
54
Gráfico 1: Média das distâncias para conjunto 1 x treinamentos para usuário ‘TIAGO’
55
Tabela 2: Taxa eficiência do reconhecimento de acordo com o número de modelos treinados
2 24.0902
3 28.2645
4 23.0363
5 23.5691
6 30.3702
7 33.6263
56
Gráfico 2: Média das distâncias para conjunto 2 x treinamentos para usuário ‘TIAGO’
Gráfico 3: Média das distâncias para conjunto 3 x treinamentos para usuário ‘TIAGO’
57
as distâncias não foram menores que 0,384726. Mesmo estando distantes de zero, as
amostras musicais apresentaram valores mais próximos do que falas dos conjuntos 2 e 3.
Gráfico 4: Média das distâncias para conjunto 4 x treinamentos para usuário ‘TIAGO’
58
Gráfico 5: Média das distâncias para conjunto 5 x treinamentos para usuário ‘TIAGO’
Ao se treinar um mesmo usuário com uma nova amostra, o modelo será atualizado,
melhorando sua capacidade de reconhecimento. Porém não altera a distância das
características quando um indivíduo não registrado tenta ser reconhecido.
O mesmo procedimento foi realizado para o usuário „LUIS‟, porém para estes testes não
se utilizou as amostras do conjunto 5. A tabela 3 apresenta os resultados obtidos.
Tabela 3: Distâncias médias para cada conjunto em relação à quantidade de modelos treinados -
LUIS
59
Para melhor visualização e comparação dos resultados, os dados foram transportados
para representação gráfica. Os gráficos de 6 a 9 exibem os resultados para os conjuntos de 1 a
4, respectivamente.
Enquanto o gráfico 3 indicava os resultados das características de amostras do usuário
„LUIS‟ em relação as treinadas do usuário „TIAGO‟, o gráfico 6 apresenta a situação invertida,
as características de amostras do „TIAGO‟ são comparadas com as treinadas de „LUIS‟. Os
valores encontrados para ambas situações são semelhantes, nos dois casos as distâncias
ficam no intervalo de 0,5 à 0,75.
Gráfico 6: Média das distâncias para conjunto 1 x treinamentos para usuário ‘LUIS’
60
Gráfico 7: Média das distâncias para conjunto 2 x treinamentos para usuário ‘LUIS’
Gráfico 8: Média das distâncias para conjunto 3 x treinamentos para usuário ‘LUIS’
61
Gráfico 9: Média das distâncias para conjunto 4 x treinamentos para usuário ‘LUIS’
62
6. Conclusões
63
Referências
BLACK, A. W.; LENZO, K. A. Flite: a small, fast speech synthesis engine. 2014 Disponível
em: <http://www.festvox.org/flite/doc/flite.pdf> Acesso em: 26 nov. 2016.
Google Speech API Disponível em: <https://cloud.google.com/speech/> Acesso em: 26 nov.
2016.
BOSKER, B Siri Rising: The Inside Story Of Siri's Origins (And Why She Could
Overshadow The iPhone). <http://www.huffpostbrasil.com/entry/siri-do-engine-apple-
iphone_n_2499165> Acesso em: 22 mar. 2017.
64
Kleback, M. Tutorial: Raspberry Pi GPIO Pins and Python. Disponível em:
<http://makezine.com/projects/tutorial-raspberry-pi-gpio-pins-and-python/> Acesso em: 22 mar.
2017.
The MARF Research and Development Group Modular. Audio Recognition Framework
v.0.3.0.6 (0.3.0 final) and its Applications. Montréal, Québec, Canada. Dezembro 2007.
The Raspberry Pi Foundation, Getting Started With you Raspberry Pi. Disponível em:
<https://www.raspberrypi.org/help/videos/#noobs-setup> Acesso em: 21 nov. 2016.
WIT.AI. WIT.AI 2015 Disponível em: < https://wit.ai/ > Acesso em 22. Mar. 2017.
65
Xbox Wire Staff. The Ultimate Assistant: Halo’s Cortana Coming to Windows Phone.
Disponível em: <https://news.xbox.com/2014/04/03/games-cortana-companion-blog-post>
Acesso em: 22 mar. 2017.
66
Apêndices
CaptureImage.py
import re
import os
import datetime
import pygame
import pygame.camera
from pygame.locals import *
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
def isValid(text):
return bool(re.search(r'\b(picture)\b', text, re.IGNORECASE))
if(now.day<10):
day = '0' + str(now.day)
else:
day = str(now.day)
if(now.hour<10):
hour = '0' + str(now.hour)
67
else:
hour = str(now.hour)
if(now.minute<10):
minute = '0' + str(now.minute)
else:
minute = str(now.minute)
if(now.second<10):
second = '0' + str(now.second)
else:
second = str(now.second)
fileName = year + month + day + '_' + hour + '-' + minute + '-' + second
fileName = fileName.lower()
name = os.path.join('/var/www/html/images/JasperImages', fileName + ".jpg")
pygame.init()
pygame.camera.init()
cam = pygame.camera.Camera("/dev/video0",(300,250))
cam.start()
image = cam.get_image()
pygame.image.save(image, name)
cam.stop()
mic.say('Image captured successfully')
CreateNewUser.py
import re
import os
import shutil
from piwho import recognition
import datetime
68
import pygame
import pygame.camera
from pygame.locals import *
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
def isValid(text):
return bool(re.search(r'\b(speaker)\b', text, re.IGNORECASE))
now = datetime.datetime.now()
year = str(now.year)
if(now.month<10):
month = '0' + str(now.month)
else:
month = str(now.month)
if(now.day<10):
day = '0' + str(now.day)
else:
day = str(now.day)
if(now.hour<10):
hour = '0' + str(now.hour)
else:
hour = str(now.hour)
if(now.minute<10):
69
minute = '0' + str(now.minute)
else:
minute = str(now.minute)
if(now.second<10):
second = '0' + str(now.second)
else:
second = str(now.second)
fileName = year + month + day + '_' + hour + '-' + minute + '-' + second
print fileName
70
else:
permission = False
if permission==True:
#New User's name
mic.say('What is the new user name?')
new_user = mic.activeListen()
#First sentence
mic.say('You have to say two sentences. Go ahead say the first one after the beep')
user = mic.activeListen2()
shutil.move("/home/pi/recordings/Reconhecer/recordingToRecognize.wav","/home/pi/recordings
/speaker_NewUser/new_user1.wav")
mic.say('Now the second sentence please')
#Second sentence
user = mic.activeListen2()
shutil.move("/home/pi/recordings/Reconhecer/recordingToRecognize.wav","/home/pi/recordings
/speaker_NewUser/new_user2.wav")
#Ask if can continue
mic.say('If everything is correct, and with that I mean, if the new user said correctely
the two sentences, say YES, otherwise you will have to start everything again')
response = mic.activeListen()
if yes(response):
#Train the model
recog = recognition.SpeakerRecognizer('/home/pi/recordings/speaker_NewUser')
recog.speaker_name = new_user
recog.train_new_data()
mic.say('New user created, your name is bla')
else:
mic.say('You did everything wrong, start it again!')
#Permission not granted, which means name[0] != 'TIAGO', create .txt file to inform the
intruder
else:
mic.say('You are not allowed to perform this action')
71
mic.say('Informing intruder')
name = os.path.join('/home/pi/NoteFiles', "permissionIntruder.txt")
#name = os.path.join('/home/pi/JasperIntruder', "permissionIntruder" + ".txt")
f = open(name, "a")
print('OPEN')
f.write(fileName + ' \n')
name = os.path.join('/var/www/html/images/JasperIntruder/', fileName + ".jpg")
os.system('fswebcam --no-banner -S 3 --jpeg 50 --save ' + name)
f.close()
mic.say('DONE')
LED_ON.py
import re
import RPi.GPIO as GPIO
WORDS = ["LIGHT"]
def isValid(text):
return bool(re.search(r'\b(light)\b', text, re.IGNORECASE))
LED_OFF.py
import re
import RPi.GPIO as GPIO
WORDS = ["DARK"]
72
def isValid(text):
return bool(re.search(r'\b(dark)\b', text, re.IGNORECASE))
Light_ON.py
import re
import RPi.GPIO as GPIO
WORDS = ["LAMP"]
def on(text):
return bool(re.search(r'\b(on)\b', text, re.IGNORECASE))
def isValid(text):
return bool(re.search(r'\b(lamp)\b', text, re.IGNORECASE))
73
Recognition.py
import re
import os
from piwho import recognition
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
def isValid(text):
return bool(re.search(r'\b(recognize)\b', text, re.IGNORECASE))
RecordAudio.py
import re
import os
from piwho import recognition
74
WORDS = ["RECORD"]
def isValid(text):
return bool(re.search(r'\b(record)\b', text, re.IGNORECASE))
Search.py
import re
import wikipedia
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
def isValid(text):
return bool(re.search(r'\b(search|set)\b', text, re.IGNORECASE))
WriteDown.py
75
import re
import os
def yes(text):
return bool(re.search(r'\b(yes)\b', text, re.IGNORECASE))
def isValid(text):
return bool(re.search(r'\b(write|right)\b', text, re.IGNORECASE))
mic.say('Anything else?')
response = mic.activeListen()
bool = type(response) is unicode
print bool
if(bool==True):
76
while yes(response):
mic.say('What else would you like me to write down?')
response = mic.activeListen()
bool = type(response) is unicode
if(bool):
f.write(response + '\n')
print(response)
else:
mic.say('You said nothing')
mic.say('Anything else?')
response = mic.activeListen()
else:
mic.say('Nothing else to write down')
f.close()
mic.say('Everything was wrote')
77