
Há dois anos, Sundar Pichai, diretor do Google, disse que a empresa do mobile-first se torna a IA e se concentra no aprendizado de máquina. Um ano depois, o Machine Learning Kit foi lançado - um conjunto de ferramentas com as quais você pode usar efetivamente o ML no iOS e no Android.
Fala-se muito sobre o ML Kit nos EUA, mas quase não há informações em russo. E como o usamos para algumas tarefas no Yandex.Money, decidi compartilhar minha experiência e mostrar com exemplos como usá-lo para fazer coisas interessantes.
Meu nome é Yura, e no ano passado trabalhei na equipe Yandex.Money em uma carteira móvel. Falaremos sobre aprendizado de máquina no celular.
Nota Editorial: Este post é uma recontagem do relatório de Yuri Chechetkin “Do celular primeiro à IA primeiro” do mitap Yanox.Money Android Paranoid .
O que é o kit ML?
Esse é o SDK para celular do Google que facilita o uso do aprendizado de máquina em dispositivos Android e iOS. Não é necessário ser um especialista em ML ou em inteligência artificial, porque em algumas linhas de código você pode implementar coisas muito complexas. Além disso, não é necessário saber como funcionam as redes neurais ou a otimização de modelos.
O que o kit ML pode fazer?
Os recursos básicos são bastante amplos. Por exemplo, você pode reconhecer texto, faces, localizar e rastrear objetos, criar etiquetas para imagens e seus próprios modelos de classificação, digitalizar códigos de barras e tags QR.
Já usamos o reconhecimento de código QR no aplicativo Yandex.Money.
Há também um kit ML
- Reconhecimento de referência;
- Definição do idioma em que o texto está escrito;
- Tradução de textos no dispositivo;
- Resposta rápida a uma carta ou mensagem.
Além de um grande número de métodos prontos para uso, há suporte para modelos personalizados, o que praticamente oferece inúmeras possibilidades - por exemplo, você pode colorir fotografias em preto e branco e fazê-las coloridas.
É importante que você não precise usar nenhum serviço, API ou back-end para isso. Tudo pode ser feito diretamente no dispositivo, para não carregar o tráfego do usuário, não recebermos muitos erros relacionados à rede, não precisamos processar vários casos, por exemplo, falta de Internet, perda de conexão e assim por diante. Além disso, no dispositivo, ele funciona muito mais rápido do que através de uma rede.

Reconhecimento de texto
Tarefa: dada uma fotografia, você precisa colocar o texto circulado em um retângulo.
Começamos com a dependência em Gradle. Basta conectar uma dependência e estamos prontos para trabalhar.
dependencies {
Vale a pena especificar os metadados que informam que o modelo será baixado no dispositivo durante o download do aplicativo no Play Market. Se você não fizer isso e acessar a API sem um modelo, obteremos um erro e o modelo deverá ser baixado em segundo plano. Se você precisar usar vários modelos, é aconselhável especificá-los separados por vírgulas. Em nosso exemplo, usamos o modelo de OCR, e o nome do restante pode ser encontrado na documentação .
<application ...> ... <meta-data android:name="com.google.firebase.ml.vision.DEPENDENCIES" android:value="ocr" /> <!-- To use multiple models: android:value="ocr,model2,model3" --> </application>
Após a configuração do projeto, você precisa definir os valores de entrada. O ML Kit funciona com o tipo FirebaseVisionImage, temos cinco métodos, cuja assinatura eu escrevi abaixo. Eles convertem os tipos usuais de Android e Java nos tipos de ML Kit, com os quais é conveniente trabalhar.
fun fromMediaImage(image: Image, rotation: Int): FirebaseVisionImage fun fromBitmap(bitmap: Bitmap): FirebaseVisionImage fun fromFilePath(context: Context, uri: Uri): FirebaseVisionImage fun fromByteBuffer( byteBuffer: ByteBuffer, metadata: FirebaseVisionImageMetadata ): FirebaseVisionImage fun fromByteArray( bytes: ByteArray, metadata: FirebaseVisionImageMetadata ): FirebaseVisionImage
Preste atenção nos dois últimos - eles funcionam com uma matriz de bytes e com um buffer de bytes, e precisamos especificar metadados para que o ML Kit entenda como lidar com tudo isso. Os metadados, de fato, descrevem o formato, neste caso, a largura e a altura, o formato padrão, IMAGE_FORMAT_NV21 e rotação.
val metadata = FirebaseVisionImageMetadata.Builder() .setWidth(480) .setHeight(360) .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21) .setRotation(rotation) .build() val image = FirebaseVisionImage.fromByteBuffer(buffer, metadata)
Quando os dados de entrada são coletados, crie um detector que reconheça o texto.
Existem dois tipos de detectores, no dispositivo e na nuvem, eles são criados literalmente em uma linha. Vale ressaltar que o detector no dispositivo funciona apenas em inglês. O detector de nuvem suporta mais de 20 idiomas; eles devem ser especificados no método especial setLanguageHints.
O número de idiomas suportados é superior a 20, todos estão no site oficial. No nosso exemplo, apenas inglês e russo.
Depois de inserir um detector, basta chamar o método processImage neste detector. Obtemos o resultado na forma de uma tarefa, na qual penduramos dois retornos de chamada - para obter sucesso e para erro. A exceção padrão ocorre com erro e o tipo FirebaseVisionText obtém êxito com o onSuccessListener.
val result: Task<FirebaseVisionText> = detector.processImage(image) .addOnSuccessListener { result: FirebaseVisionText ->
Como trabalhar com o tipo FirebaseVisionText?
Consiste em blocos de texto (TextBlock), aqueles por sua vez consistem em linhas (Linha) e linhas de elementos (Elemento). Eles estão aninhados um no outro.
Além disso, cada uma dessas classes possui cinco métodos que retornam dados diferentes sobre o objeto. Um retângulo é a área em que o texto está localizado, a confiança é a precisão do texto reconhecido, os pontos de canto são os pontos de canto no sentido horário, começando no canto superior esquerdo, nos idiomas reconhecidos e no próprio texto.
FirebaseVisionText contains a list of FirebaseVisionText.TextBlock which contains a list of FirebaseVisionText.Line which is composed of a list of FirebaseVisionText.Element. fun getBoundingBox(): Rect
Para que é isso?
Podemos reconhecer o texto inteiro na figura e seus parágrafos, partes, linhas ou apenas palavras. E como exemplo, podemos iterar sobre, em cada estágio, pegar um texto, pegar as bordas desse texto e desenhar. Muito confortável
Planejamos usar essa ferramenta em nosso aplicativo para reconhecer cartões bancários, cujas etiquetas estão localizadas fora do padrão. Nem todas as bibliotecas de reconhecimento de cartões funcionam bem e, para cartões personalizados, o ML Kit seria muito útil. Como há pouco texto, é muito fácil processar dessa maneira.
Reconhecimento de objetos na foto

Usando a ferramenta a seguir como exemplo, eu gostaria de mostrar que o princípio de operação é aproximadamente o mesmo. Nesse caso, reconhecimento do que é representado no objeto. Também criamos dois detectores, um no dispositivo e outro na nuvem. Podemos especificar a precisão mínima como parâmetros. O padrão é 0,5, indicado 0,7 e pronto para uso. Também obtemos o resultado na forma de FirebaseImageLabel, esta é uma lista de rótulos, cada um dos quais contém um ID, descrição e precisão.
Harold escondendo a felicidade

Você pode tentar entender como Harold esconde a dor e se ele é feliz ao mesmo tempo. Usamos uma ferramenta de reconhecimento de rosto, que, além de reconhecer as características faciais, pode dizer o quão feliz é uma pessoa. Como se viu, Harold está 93% feliz. Ou ele esconde a dor muito bem.

De fácil a fácil, mas um pouco mais complicado. Modelos personalizados.
Tarefa: classificação do que é retratado na foto.
Tirei uma foto do laptop e reconheci o modem, o computador de mesa e o teclado. Parece a verdade. Existem mil classificadores, e ele leva três deles que melhor descrevem esta foto.

Ao trabalhar com modelos personalizados, também podemos trabalhar com eles no dispositivo e na nuvem.
Se trabalharmos na nuvem, você precisará acessar o Firebase Console, a guia ML Kit e o toque personalizado, onde podemos fazer upload de nosso modelo para o TensorFlow Lite, porque o ML Kit funciona com modelos com esta resolução. Se o usarmos em um dispositivo, podemos simplesmente colocar o modelo em qualquer parte do projeto como um ativo.

Apontamos a dependência do intérprete, que pode trabalhar com modelos personalizados, e não esquecemos a permissão para trabalhar com a Internet.
<uses-permission android:name="android.permission.INTERNET" /> dependencies {
Para os modelos que estão no dispositivo, você deve indicar no Gradle que o modelo não deve ser compactado, pois pode estar distorcido.
android {
Quando configuramos tudo em nosso ambiente, precisamos definir condições especiais, que incluem, por exemplo, o uso de Wi-Fi, também exigem carregamento e exigem que o dispositivo ocioso esteja disponível no Android N - essas condições indicam que o telefone está carregando ou está no modo de espera.
var conditionsBuilder: FirebaseModelDownloadConditions.Builder = FirebaseModelDownloadConditions.Builder().requireWifi() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Quando criamos um modelo remoto, definimos as condições de inicialização e atualização, além de sinalizar se nosso modelo deve ser atualizado. O nome do modelo deve corresponder ao nome especificado no console do Firebase. Quando criamos o modelo remoto, devemos registrá-lo no Firebase Model Manager.
val cloudSource: FirebaseRemoteModel = FirebaseRemoteModel.Builder("my_cloud_model") .enableModelUpdates(true) .setInitialDownloadConditions(conditions) .setUpdatesDownloadConditions(conditions) .build() FirebaseModelManager.getInstance().registerRemoteModel(cloudSource)
Realizamos as mesmas etapas para o modelo local, especificamos seu nome, o caminho para o modelo e o registramos no Firebase Model Manager.
val localSource: FirebaseLocalModel = FirebaseLocalModel.Builder("my_local_model") .setAssetFilePath("my_model.tflite") .build() FirebaseModelManager.getInstance().registerLocalModel(localSource)
Depois disso, você precisa criar essas opções onde especificamos os nomes de nossos modelos, instalamos o modelo remoto, instalamos o modelo local e criamos um intérprete com essas opções. Podemos especificar um modelo remoto ou apenas local, e o intérprete entenderá com quem trabalhar.
val options: FirebaseModelOptions = FirebaseModelOptions.Builder() .setRemoteModelName("my_cloud_model") .setLocalModelName("my_local_model") .build() val interpreter = FirebaseModelInterpreter.getInstance(options)
O ML Kit não sabe nada sobre o formato dos dados de entrada e saída dos modelos personalizados, portanto, é necessário especificá-los.
Os dados de entrada são uma matriz multidimensional, em que 1 é o número de imagens, 224x224 é a resolução e 3 é uma imagem RGB de três canais. Bem, o tipo de dados é bytes.
val input = intArrayOf(1, 224, 224, 3)
Os valores de saída são 1000 classificadores. Definimos o formato dos valores de entrada e saída em bytes com as matrizes multidimensionais especificadas. Além de bytes, float, long, int também estão disponíveis.
Agora vamos definir os valores de entrada. Pegamos o Bitmap, compactamos para 224 por 224, convertemos para ByteBuffer e criamos valores de entrada usando FirebaseModelInput usando um construtor especial.
val bitmap = Bitmap.createScaledBitmap(yourInputImage, 224, 224, true) val imgData = convertBitmapToByteBuffer(bitmap) val inputs: FirebaseModelInputs = FirebaseModelInputs.Builder() .add(imageData) .build()
E agora, quando há um intérprete, o formato dos valores de entrada e saída e os próprios valores de entrada, podemos executar a solicitação usando o método run. Transferimos todos os itens acima como parâmetros e, como resultado, obtemos o FirebaseModelOutput, que contém um genérico do tipo especificado. Nesse caso, era uma matriz de bytes, após a qual podemos iniciar o processamento. São exatamente os milhares de classificadores que solicitamos e exibimos, por exemplo, os três primeiros mais adequados.
interpreter.run(inputs, inputOutputOptions) .addOnSuccessListener { result: FirebaseModelOutputs -> val labelProbArray = result.getOutput<Array<ByteArray>>(0)
Implementação de um dia
Tudo é muito fácil de implementar e o reconhecimento de objetos com ferramentas integradas pode ser realizado em apenas um dia. A ferramenta está disponível no iOS e Android. Além disso, você pode usar o mesmo modelo TensorFlow para ambas as plataformas.
Além disso, existem vários métodos disponíveis imediatamente, que podem cobrir muitos casos. A maioria das APIs está disponível no dispositivo, ou seja, o reconhecimento funcionará mesmo sem a Internet.
E o mais importante - suporte para modelos personalizados que podem ser usados como você deseja em qualquer tarefa.
Links úteis
Documentação do kit ML
Projeto de demonstração do kit Github ML
Machine Learning para celular com Firebase (Google I / O'19)
Machine Learning SDK para desenvolvedores de dispositivos móveis (Google I / O'18)
Criando um scanner de cartão de crédito usando o Firebase ML Kit (Medium.com)