Descrição do Problema
Estou querendo usar o reconhecimento de voz como parte de um projeto de hardware, que gostaria de ser completamente independente (estou usando pequenos dispositivos de baixa potência e baixa velocidade, como Arduino e Raspberry Pi, Kinects etc., nenhum computador tradicional com um sistema operacional envolvido, portanto, um projeto fechado / autocontido).
O reconhecimento de voz pode ser muito complicado, dependendo do nível de sofisticação que você deseja. Eu tenho o que acredito ser um conjunto relativamente simples de requisitos. Eu só quero reconhecer minha própria voz e tenho um pequeno dicionário de 20 ou mais palavras que gostaria de reconhecer. Portanto, não preciso de bibliotecas complexas de reconhecimento de voz e texto ou de qualquer um dos excelentes softwares de terceiros que encontro pelos mecanismos de pesquisa da Internet (não há falta deles!). Acredito que meus requisitos sejam "simples o suficiente" (dentro do razoável) para que eu possa codificar minha própria solução. Eu estou querendo saber se alguém escreveu seu próprio processo como este, e meu método é massivamente falho? Existe uma maneira melhor de fazer isso sem exigir um alto nível de matemática ou ter que escrever um algoritmo complexo? Essa é a solução que tentei pensar abaixo.
Descrição da solução
Escreverei isso em C, mas desejo discutir um processo agnóstico da linguagem, concentrando-se no próprio processo. Então, vamos ignorar isso, se pudermos.
1 Pré-gravarei meu dicionário de palavras para corresponder às que estão sendo faladas. Podemos imaginar que tenho 20 gravações de minhas 20 palavras diferentes, ou talvez frases curtas ou sentenças de duas ou três palavras. Eu acredito que isso facilita o processo de comparar dois arquivos de gravação do que converter o áudio em texto e comparar duas strings.
2) Um microfone está conectado ao meu dispositivo de hardware executando meu código. [1] O código está continuamente colhendo amostras de comprimento fixo, digamos 10 ms, por exemplo, e armazenando 10 amostras consecutivas, por exemplo, em um estilo de registro circular. [2] (Estou inventando essas figuras de cima para baixo, para que sejam apenas exemplos para descrever o processo).
[1] Isso provavelmente seria conectado através de um filtro passa-banda e amplificador operacional, como seriam feitas as gravações do dicionário, para manter menores as amostras de áudio armazenadas e coletadas.
[2] Não sei exatamente como vou colher uma amostra, preciso elaborar um método, embora produzisse uma figura numérica (número inteiro / número flutuante / duplo) que represente o áudio de uma amostra de 10 ms (talvez um valor CRC ou soma MD5 da amostra de áudio) ou um fluxo de figuras (talvez um fluxo de leituras de áudio de frequências). Por fim, uma "amostra" será uma ou mais figuras numéricas. Esta parte terá muito mais hardware envolvido, portanto não será realmente discutida aqui.
3) O código examina 10 amostras consecutivas armazenadas e procura um aumento de volume para indicar que uma palavra ou frase está sendo dita (uma pausa do silêncio) e depois aumenta a coleta de amostras consecutivas para dizer 500 amostras, por exemplo. Isso significa que ele captura 5 segundos de áudio em amostras de 10 ms.
São essas amostras ou "fatias" que são comparadas entre o som armazenado e o som capturado. Se uma porcentagem suficientemente alta de amostras capturadas corresponder às armazenadas equivalentes, o código assumirá a mesma palavra.
The start of a store recording of the world "hello" for example,
stored words are split into 10 msec samples also
Stored Sample No | 1| 2| 3| 4| 5| 6| 7| 8|
Stored Sample Value |27|38|41|16|59|77|200|78|
Incoming audio (me saying "hello") with some "blank" samples
at the start to symbolise silence
Incoming Sample No | 1| 2| 3| 4| 5| 6| 7| 8| 9|10| 11|12|
Incoming Sample Value | | | |20|27|38|46|16|59|77|200|78|
4) Depois que o código coleta um fluxo de amostra completo, ele retira as amostras em branco no início para produzir a seguinte gravação de áudio. Também poderia mover a amostra para trás e para frente alguns lugares para melhor alinhar com a amostra armazenada.
Isso produz um conjunto de amostras como o abaixo:
Stored Sample No | 1| 2| 3| 4| 5| 6| 7| 8|
Stored Sample Value |27|38|41|16|59|77|200|78|
Incoming Sample No |-1| 1| 2| 3| 4| 5| 6| 7| 8|
Incoming Sample Value |20|27|38|46|16|59|81|201|78|
5) Acredito que, ao ter um valor percentual de quão próxima cada amostra deve estar, a amostra 7 difere por um valor 1 menor que% 1 e um valor percentual para o número total de amostras que devem estar dentro da porcentagem correspondente da amostra , o código tem um nível de precisão facilmente ajustável.
Eu nunca fiz nada assim com áudio antes, poderia ser um monte de trabalho. É por isso que estou fazendo esta pergunta, se você talvez já saiba que a resposta a esta pergunta é óbvia (qualquer que seja essa resposta). Espero que isso não seja uma tarefa computacionalmente massiva, pois parte do hardware que utilizarei será de baixo nível. Nas centenas de Megahertz (talvez 1 Ghz usando um Rasp Pi com clock excessivo). Portanto, essa é uma maneira bastante grosseira de combinar amostras de áudio usando menor poder computacional. Não estou buscando resultados instantâneos, mas menos de 30 segundos para uma prova de conceito decente.
PS Não tenho o representante para marcar isso com uma nova tag como "áudio", "reconhecimento de áudio", "voz", "reconhecimento de voz" etc.
fonte
Respostas:
Bem, eu não acredito que o Arduino tenha o poder de fazer isso. seu funcionamento em 16Mhz Um Arduino possui cerca de 32K de memória. Mesmo 20 palavras amostradas em Mp3 (menores que WAV) não caberiam nele, apesar de ser apenas a sua própria voz.
O rasberi pi pode funcionar, operando a 700Mhz, dependendo da versão, pode ter 512MB de memória. Ainda não é muito dinheiro.
Você pode precisar de um fourier ( http://www.drdobbs.com/cpp/a-simple-and-efficient-fft-implementatio/199500857 )
Ou, se você pretende usar o volume, faça algumas médias com amostras anteriores, como
x = (x + x [n-1] + x [n-2] + x [n-3]) / 4 // isso é bastante simples preciso de mais
A próxima coisa que você precisa fazer é pensar se você plotaria esses valores X. Então, você precisa de algum tipo de detecção de inclinação dessa linha. as palavras
Então, depende um pouco de como gravar a inclinação para que o padrão caiba outra vez. Quero dizer, não se fala no ritmo exato que um computador pode corresponder e a inclinação pode ser um pouco mais íngreme. No final, acho que é um pouco o quão íngremes essas linhas são e seu comprimento e eixo y deve estar dentro de uma média
fonte
Arduino e Raspberry Pi são placas de prototipagem com pequenos chips. Você deve se concentrar no chip primeiro. Procure algo com uma caixa de ferramentas DSP (processamento de sinal digital), talvez você já tenha uma caixa de ferramentas DSP e não a conheça. As caixas de ferramentas DSP têm algoritmos de plantão, como fft (fast fourier transform) e ifft (inverso fft) para análise rápida no domínio da frequência.
Concentre-se no seu estilo programático: suas amostras estão em uma pilha ou fila? Você deseja uma fila para este tipo de dados. Uma fila se parece com:
Próxima iteração:
Observe como as coisas mudam para o "certo"? Eu acho que você descreveu um algoritmo "circular". Basta substituir as amostras mais antigas pelas segundas amostras mais antigas e depois substituir as segundas amostras mais antigas pelo terceiro mais antigo, ..., até o início da fila em que você insere seus dados mais recentes.
"O código está continuamente coletando amostras de comprimento fixo, digamos 10 ms" <- incorreto Pense desta maneira: O código está coletando discretamente amostras quantizadas (altura), a uma taxa de amostragem de 10000 amostras por segundo, o que separa cada amostra a 0,1 ms.
Qual é a sua frequência de amostragem? Qual é a taxa de bits no seu quantizador? Números mais baixos ajudarão você a liberar memória. Eu sugeriria uma baixa taxa de amostragem como 6600 amostras por segundo (Nyquist). Eu suspeito que 4 bits (16 níveis) seria suficiente para reconhecimento. Isso significa 3300 bytes de gravação por segundo. Agora faça fft e exclua tudo acima de 3300 Hz (filtro de telefonia). Agora você tem 1650 bytes usados por um segundo de som. Esses truques DSP economizarão muita memória.
Não sei quem pensa que 512 MB é pequeno. Com as informações acima, mais de 300.000 segundos de gravação ... mais de 3 dias seguidos.
Eu acho que você encontrará o domínio da frequência (usando o fft) como um ambiente melhor para realizar o reconhecimento de voz.
Espero não confundi-lo pior :)
fonte