Reconhecimento de som e palavras para Android

Este tutorial mostra como usar o TensorFlow Lite com modelos de machine learning 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 baixar o 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 do 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 com 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, você baixa o exemplo do GitHub e o executa 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 uma versão mínima do SO do SDK 24 (Android 7.0 - Nougat) com o 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 amostra.

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 do git para usar check-out 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
    

Importar e executar o projeto

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

Para importar e construir 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 cria um novo projeto e o compila. Esse processo pode levar alguns minutos, dependendo da velocidade do seu computador e se você já usou 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 um 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 de projeto específicas para executar modelos de aprendizado de máquina do TensorFlow Lite e acessar funções de utilitário que convertem formatos de dados padrão, como áudio, em um formato de dados de 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 aprendizado de máquina 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ínima 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 que contém o modelo. O arquivo de modelo contém a lógica de previsão e normalmente inclui metadados sobre como interpretar os resultados da previsão, como nomes de classe de previsã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 em 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 criando 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)
    

Ativar aceleração de hardware

Ao inicializar um modelo do TensorFlow Lite em seu aplicativo, considere 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 unidade de processamento gráfico (GPUs) ou unidades de processamento de tensor (TPUs). O exemplo de código usa o NNAPI Delegate 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 representantes para executar modelos do TensorFlow Lite é recomendado, mas não obrigatório. Para obter mais informações sobre como usar representantes com o TensorFlow Lite, consulte Delegados do TensorFlow Lite .

Preparar dados para o modelo

Em 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 por 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 de dados usado 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 do Tensor que representam clipes de áudio de canal único ou mono gravados a 16 kHz em clipes de 0,975 segundo (15600 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 lida com a 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 para o 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

Em 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 as previsões do modelo de ML em um thread em 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.

Os 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 de entrada analisando clipes de áudio sobrepostos. Essa abordagem ajuda o modelo a evitar previsões perdidas para palavras cortadas no final de um clipe. No aplicativo de exemplo, cada vez que você executa uma previsão, o código pega o clipe de 0,975 segundo mais recente 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 pool de execução de encadeamento de análise de modelo para um comprimento menor que o comprimento dos clipes que estão sendo analisados. Por exemplo, se 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 a 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 para o modelo:

    fun startAudioClassification() {
      if (recorder.recordingState == AudioRecord.RECORDSTATE_RECORDING) {
        return
      }
      recorder.startRecording()
    }
    
  2. Defina com que frequência o modelo gera uma inferência 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)
      ...
    }
    

Parar 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 do Android ou fragmento 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 aplicativo deve processar executando lógica de negócios adicional, exibindo resultados para o usuário ou realizando outras ações. A saída de qualquer modelo do TensorFlow Lite varia de acordo com o número de previsões que ele produz (uma ou muitas) e as informações descritivas de cada previsão. No caso dos modelos no 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 de 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 os 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 representando a confiança da previsão, sendo 1 a classificação de confiança mais alta. Em geral, as previsões com pontuação abaixo de 50% (0,5) são consideradas inconclusivas. No entanto, a forma 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 nessas 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 do 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 .