Reconhecimento de sons e palavras para Android

Este tutorial mostra como usar o TensorFlow Lite com modelos de aprendizado de máquina pré-criados para reconhecer sons e palavras faladas em um aplicativo Android. Modelos de classificação de áudio como os mostrados neste tutorial podem ser usados ​​para detectar atividades, identificar ações ou reconhecer comandos de voz.

Demonstração animada de reconhecimento de áudio Este tutorial mostra como fazer download do código de exemplo, carregar o projeto no Android Studio e explica as principais partes do exemplo de código para que você possa começar a adicionar essa funcionalidade ao seu próprio aplicativo. O código do aplicativo de exemplo usa a biblioteca de tarefas do TensorFlow para áudio , que lida com a maior parte da gravação e pré-processamento de dados de áudio. Para obter mais informações sobre como o áudio é pré-processado para uso com modelos de aprendizado de máquina, consulte Preparação e aumento de dados de áudio .

Classificação de áudio com aprendizado de máquina

O modelo de aprendizado de máquina neste tutorial reconhece sons ou palavras de amostras de áudio gravadas com um microfone em um dispositivo Android. O aplicativo de exemplo neste tutorial permite alternar entre o YAMNet/classifier , um modelo que reconhece sons, e um modelo que reconhece palavras faladas específicas, que foi treinado usando a ferramenta TensorFlow Lite Model Maker . Os modelos executam previsões em clipes de áudio que contêm 15.600 amostras individuais por clipe e têm cerca de 1 segundo de duração.

Exemplo de configuração e execução

Para a primeira parte deste tutorial, baixe o exemplo do GitHub e execute-o usando o Android Studio. As seções a seguir deste tutorial exploram as seções relevantes do exemplo, para que você possa aplicá-las aos seus próprios aplicativos Android.

requisitos de sistema

  • Android Studio versão 2021.1.1 (Bumblebee) ou superior.
  • Android SDK versão 31 ou superior
  • Dispositivo Android com versão mínima do sistema operacional SDK 24 (Android 7.0 - Nougat) com modo de desenvolvedor ativado.

Obtenha o código de exemplo

Crie uma cópia local do código de exemplo. Você usará esse código para criar um projeto no Android Studio e executar o aplicativo de exemplo.

Para clonar e configurar o código de exemplo:

  1. Clone o repositório git
    git clone https://github.com/tensorflow/examples.git
    
  2. Opcionalmente, configure sua instância git para usar checkout esparso, para que você tenha apenas os arquivos do aplicativo de exemplo:

    cd examples
    git sparse-checkout init --cone
    git sparse-checkout set lite/examples/audio_classification/android
    

Importe e execute o projeto

Crie um projeto a partir do código de exemplo baixado, compile o projeto e execute-o.

Para importar e criar o projeto de código de exemplo:

  1. Inicie o Android Studio .
  2. No Android Studio, escolha Arquivo > Novo > Importar Projeto .
  3. Navegue até o diretório de código de exemplo que contém o arquivo build.gradle ( .../examples/lite/examples/audio_classification/android/build.gradle ) e selecione esse diretório.

Se você selecionar o diretório correto, o Android Studio criará um novo projeto e o compilará. Este processo pode demorar alguns minutos, dependendo da velocidade do seu computador e se você utilizou o Android Studio para outros projetos. Quando a compilação for concluída, o Android Studio exibirá uma mensagem BUILD SUCCESSFUL no painel de status Build Output .

Para executar o projeto:

  1. No Android Studio, execute o projeto selecionando Run > Run 'app' .
  2. Selecione um dispositivo Android conectado com microfone para testar o aplicativo.

As próximas seções mostram as modificações que você precisa fazer em seu projeto existente para adicionar essa funcionalidade ao seu próprio aplicativo, usando este aplicativo de exemplo como ponto de referência.

Adicionar dependências do projeto

Em seu próprio aplicativo, você deve adicionar dependências específicas do projeto para executar modelos de machine learning do TensorFlow Lite e acessar funções utilitárias que convertem formatos de dados padrão, como áudio, em um formato de dados tensor que pode ser processado pelo modelo que você está usando.

O aplicativo de exemplo usa as seguintes bibliotecas do TensorFlow Lite:

As instruções a seguir mostram como adicionar as dependências de projeto necessárias ao seu próprio projeto de aplicativo Android.

Para adicionar dependências de módulo:

  1. No módulo que usa o TensorFlow Lite, atualize o arquivo build.gradle do módulo para incluir as dependências a seguir. No código de exemplo, este arquivo está localizado aqui: .../examples/lite/examples/audio_classification/android/build.gradle

    dependencies {
    ...
        implementation 'org.tensorflow:tensorflow-lite-task-audio'
    }
    
  2. No Android Studio, sincronize as dependências do projeto selecionando: File > Sync Project with Gradle Files .

Inicialize o modelo de ML

No seu aplicativo Android, você deve inicializar o modelo de machine learning do TensorFlow Lite com parâmetros antes de executar previsões com o modelo. Esses parâmetros de inicialização dependem do modelo e podem incluir configurações como limites de precisão mínimos padrão para previsões e rótulos para palavras ou sons que o modelo pode reconhecer.

Um modelo do TensorFlow Lite inclui um arquivo *.tflite contendo o modelo. O arquivo de modelo contém a lógica de predição e normalmente inclui metadados sobre como interpretar os resultados da predição, como nomes de classes de predição. Os arquivos de modelo devem ser armazenados no diretório src/main/assets do seu projeto de desenvolvimento, como no exemplo de código:

  • <project>/src/main/assets/yamnet.tflite

Por conveniência e legibilidade do código, o exemplo declara um objeto complementar que define as configurações do modelo.

Para inicializar o modelo no seu aplicativo:

  1. Crie um objeto complementar para definir as configurações do modelo:

    companion object {
      const val DISPLAY_THRESHOLD = 0.3f
      const val DEFAULT_NUM_OF_RESULTS = 2
      const val DEFAULT_OVERLAP_VALUE = 0.5f
      const val YAMNET_MODEL = "yamnet.tflite"
      const val SPEECH_COMMAND_MODEL = "speech.tflite"
    }
    
  2. Crie as configurações para o modelo construindo um objeto AudioClassifier.AudioClassifierOptions :

    val options = AudioClassifier.AudioClassifierOptions.builder()
      .setScoreThreshold(classificationThreshold)
      .setMaxResults(numOfResults)
      .setBaseOptions(baseOptionsBuilder.build())
      .build()
    
  3. Use este objeto de configurações para construir um objeto AudioClassifier do TensorFlow Lite que contém o modelo:

    classifier = AudioClassifier.createFromFileAndOptions(context, "yamnet.tflite", options)
    

Habilitar aceleração de hardware

Ao inicializar um modelo do TensorFlow Lite em seu aplicativo, você deve considerar o uso de recursos de aceleração de hardware para acelerar os cálculos de previsão do modelo. Os delegados do TensorFlow Lite são módulos de software que aceleram a execução de modelos de aprendizado de máquina usando hardware de processamento especializado em um dispositivo móvel, como unidades de processamento gráfico (GPUs) ou unidades de processamento de tensores (TPUs). O exemplo de código usa o delegado NNAPI para lidar com a aceleração de hardware da execução do modelo:

val baseOptionsBuilder = BaseOptions.builder()
   .setNumThreads(numThreads)
...
when (currentDelegate) {
   DELEGATE_CPU -> {
       // Default
   }
   DELEGATE_NNAPI -> {
       baseOptionsBuilder.useNnapi()
   }
}

O uso de delegados para executar modelos do TensorFlow Lite é recomendado, mas não obrigatório. Para obter mais informações sobre como usar delegados com o TensorFlow Lite, consulte Delegados do TensorFlow Lite .

Preparar dados para o modelo

No seu aplicativo Android, seu código fornece dados ao modelo para interpretação, transformando dados existentes, como clipes de áudio, em um formato de dados do Tensor que pode ser processado pelo seu modelo. Os dados em um Tensor que você passa para um modelo devem ter dimensões ou formas específicas que correspondam ao formato dos dados usados ​​para treinar o modelo.

O modelo YAMNet/classificador e os modelos de comandos de fala personalizados usados ​​neste exemplo de código aceitam objetos de dados Tensor que representam clipes de áudio de canal único ou mono gravados a 16kHz em clipes de 0,975 segundos (15.600 amostras). Ao executar previsões em novos dados de áudio, seu aplicativo deve transformar esses dados de áudio em objetos de dados do Tensor desse tamanho e formato. A API de áudio da biblioteca de tarefas do TensorFlow Lite cuida da transformação de dados para você.

No código de exemplo da classe AudioClassificationHelper , o aplicativo grava áudio ao vivo dos microfones do dispositivo usando um objeto Android AudioRecord . O código usa AudioClassifier para construir e configurar esse objeto para gravar áudio em uma taxa de amostragem apropriada para o modelo. O código também usa AudioClassifier para construir um objeto TensorAudio para armazenar os dados de áudio transformados. Em seguida, o objeto TensorAudio é passado ao modelo para análise.

Para fornecer dados de áudio ao modelo de ML:

  • Use o objeto AudioClassifier para criar um objeto TensorAudio e um objeto AudioRecord :

    fun initClassifier() {
    ...
      try {
        classifier = AudioClassifier.createFromFileAndOptions(context, currentModel, options)
        // create audio input objects
        tensorAudio = classifier.createInputTensorAudio()
        recorder = classifier.createAudioRecord()
      }
    

Executar previsões

No seu aplicativo Android, depois de conectar um objeto AudioRecord e um objeto TensorAudio a um objeto AudioClassifier, você pode executar o modelo nesses dados para produzir uma previsão ou inferência . O código de exemplo deste tutorial executa previsões em clipes de um fluxo de entrada de áudio gravado ao vivo em uma taxa específica.

A execução do modelo consome recursos significativos, por isso é importante executar previsões do modelo de ML em um thread de segundo plano separado. O aplicativo de exemplo usa um objeto [ScheduledThreadPoolExecutor](https://developer.android.com/reference/java/util/concurrent/ScheduledThreadPoolExecutor) para isolar o processamento do modelo de outras funções do aplicativo.

Modelos de classificação de áudio que reconhecem sons com início e fim claros, como palavras, podem produzir previsões mais precisas em um fluxo de áudio recebido analisando clipes de áudio sobrepostos. Essa abordagem ajuda o modelo a evitar a perda de previsões para palavras cortadas no final de um clipe. No aplicativo de exemplo, cada vez que você executa uma previsão, o código captura o clipe mais recente de 0,975 segundo do buffer de gravação de áudio e o analisa. Você pode fazer com que o modelo analise clipes de áudio sobrepostos definindo o valor do interval do conjunto de execução do encadeamento de análise do modelo para uma duração menor que a duração dos clipes que estão sendo analisados. Por exemplo, se o seu modelo analisar clipes de 1 segundo e você definir o intervalo para 500 milissegundos, o modelo analisará a última metade do clipe anterior e 500 milissegundos de novos dados de áudio de cada vez, criando uma sobreposição de análise de clipe de 50%.

Para começar a executar previsões nos dados de áudio:

  1. Use o método AudioClassificationHelper.startAudioClassification() para iniciar a gravação de áudio do modelo:

    fun startAudioClassification() {
      if (recorder.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
        return
      }
      recorder.startRecording()
    }
    
  2. Defina a frequência com que o modelo gera uma inferência a partir dos clipes de áudio definindo um interval de taxa fixa no objeto ScheduledThreadPoolExecutor :

    executor = ScheduledThreadPoolExecutor(1)
    executor.scheduleAtFixedRate(
      classifyRunnable,
      0,
      interval,
      TimeUnit.MILLISECONDS)
    
  3. O objeto classifyRunnable no código acima executa o método AudioClassificationHelper.classifyAudio() , que carrega os dados de áudio mais recentes disponíveis do gravador e realiza uma previsão:

    private fun classifyAudio() {
      tensorAudio.load(recorder)
      val output = classifier.classify(tensorAudio)
      ...
    }
    

Interromper o processamento de previsão

Certifique-se de que o código do seu aplicativo pare de fazer a classificação de áudio quando o fragmento ou atividade de processamento de áudio do seu aplicativo perder o foco. A execução contínua de um modelo de aprendizado de máquina tem um impacto significativo na vida útil da bateria de um dispositivo Android. Use o método onPause() da atividade ou fragmento do Android associado à classificação de áudio para interromper a gravação de áudio e o processamento de previsão.

Para interromper a gravação e classificação de áudio:

  • Use o método AudioClassificationHelper.stopAudioClassification() para interromper a gravação e a execução do modelo, conforme mostrado abaixo na classe AudioFragment :

    override fun onPause() {
      super.onPause()
      if (::audioHelper.isInitialized ) {
        audioHelper.stopAudioClassification()
      }
    }
    

Lidar com a saída do modelo

No seu aplicativo Android, depois de processar um clipe de áudio, o modelo produz uma lista de previsões que o código do seu aplicativo deve processar executando lógica de negócios adicional, exibindo resultados ao usuário ou realizando outras ações. A saída de qualquer modelo do TensorFlow Lite varia em termos do número de previsões que ele produz (uma ou muitas) e das informações descritivas de cada previsão. No caso dos modelos do aplicativo de exemplo, as previsões são uma lista de sons ou palavras reconhecidas. O objeto de opções AudioClassifier usado no exemplo de código permite definir o número máximo de previsões com o método setMaxResults() , conforme mostrado na seção Inicializar o modelo de ML .

Para obter os resultados da previsão do modelo:

  1. Obtenha os resultados do método classify() do objeto AudioClassifier e passe-os para o objeto ouvinte (referência de código):

    private fun classifyAudio() {
      ...
      val output = classifier.classify(tensorAudio)
      listener.onResult(output[0].categories, inferenceTime)
    }
    
  2. Use a função onResult() do ouvinte para lidar com a saída executando a lógica de negócios ou exibindo resultados para o usuário:

    private val audioClassificationListener = object : AudioClassificationListener {
      override fun onResult(results: List<Category>, inferenceTime: Long) {
        requireActivity().runOnUiThread {
          adapter.categoryList = results
          adapter.notifyDataSetChanged()
          fragmentAudioBinding.bottomSheetLayout.inferenceTimeVal.text =
            String.format("%d ms", inferenceTime)
        }
      }
    

O modelo usado neste exemplo gera uma lista de previsões com um rótulo para o som ou palavra classificada e uma pontuação de previsão entre 0 e 1 como um Float que representa a confiança da previsão, sendo 1 a classificação de confiança mais alta. Em geral, as previsões com pontuação inferior a 50% (0,5) são consideradas inconclusivas. No entanto, a maneira como você lida com resultados de previsão de baixo valor depende de você e das necessidades do seu aplicativo.

Depois que o modelo retornar um conjunto de resultados de previsão, seu aplicativo poderá agir de acordo com essas previsões, apresentando o resultado ao usuário ou executando lógica adicional. No caso do código de exemplo, o aplicativo lista os sons ou palavras identificados na interface de usuário do aplicativo.

Próximos passos

Você pode encontrar modelos adicionais do TensorFlow Lite para processamento de áudio no TensorFlow Hub e na página do guia de modelos pré-treinados . Para obter mais informações sobre como implementar o aprendizado de máquina em seu aplicativo móvel com o TensorFlow Lite, consulte o Guia do desenvolvedor do TensorFlow Lite .