Classifique imagens no Android usando o TensorFlow Lite e o Azure Custom Vision

A classificação de imagens permite que nossos aplicativos Xamarin reconheçam objetos nas fotografias.

Mais e mais comum é a capacidade de tirar uma foto e reconhecer seu conteúdo. Podemos observar isso em nossos aplicativos bancários ao fazer um depósito móvel, em aplicativos de fotos ao adicionar filtros e em aplicativos HotDog para determinar se nossa comida é um cachorro-quente.

Graças ao serviço Azure Custom Vision, não precisamos aprender algoritmos complexos de aprendizado de máquina para implementar a classificação de imagens.

Neste artigo, veremos como implementar a classificação de imagens usando o serviço Azure Custom Vision , TensorFlow Lite (plataforma de aprendizado de máquina de código aberto) eXamarin.Android .


Nota: No Xamarin.iOS, também podemos usar o serviço Azure Custom Vision com CoreML , mas é melhor salvá-lo para outro artigo.

imagem

Bibliotecas de classificação de imagens


Usaremos o serviço Azure Custom Vision e o TensorFlow Lite para implementar nossa classificação de imagens.

1. Serviço de Visão Personalizada do Azure


O serviço Azure Custom Vision simplifica a criação e o treinamento de um modelo de aprendizado de máquina - não exige experiência com Artificail Intelligence (AI) ou Machine Learning (ML).

Usando o portal da web do serviço Custom Vision , podemos fazer o seguinte sem escrever nenhum código de AI / ML:

  1. Download da imagem do treinamento
  2. Marque Tags / Tags de objeto (s) na imagem
  3. Repita (o modelo melhora com mais dados de treinamento)
  4. É isso aí - a Custom Vision cuida do resto!

2. TensorFlow Lite


O TensorFlow Lite é uma plataforma de aprendizado de máquina de código aberto que nos permite usar o TensorFlow em IoT e em dispositivos móveis.

O TensorFlow Lite e o TensorFlow estão disponíveis em código aberto no GitHub .

Implementando a classificação de imagens usando o Azure + Xamarin.Android


Um aplicativo completo de classificação de imagem de amostra está disponível no GitHub .

1. Modelo de treinamento


Usando o portal da web do serviço Custom Vision , treinamos primeiro modelos de classificação de imagens.

1. No portal da web do serviço Custom Vision, clique em Novo Projeto

imagem

2. Na janela Criar novo projeto , defina os seguintes parâmetros:

  • Nome: XamarinImageClassification
  • Descrição: identificar objetos em imagens
  • Recurso: [Crie um novo recurso]
  • Tipo de Projeto: Classificação
  • Tipos de classificação: vários rótulos (várias tags por imagem)
  • Domínios: Geral (compacto)
  • Recursos de exportação: plataformas básicas

3. Na janela Criar novo projeto , clique em Criar projeto

4. Na janela XamarinImageClassification, clique em Adicionar imagens

5. Selecione as imagens que contêm o objeto para identificação

6. Na janela Upload de imagem , adicione uma marca
Nota: neste exemplo, estamos trabalhando com imagens de cogumelos

7. Na janela Imagem enviar clique em Enviar
Nota: continue enviando imagens até ter pelo menos 5 imagens para cada tag

imagem

8. Na janela XamarinImageClassification , no canto superior direito da janela, clique no botão Train Model (imagem verde das engrenagens)

9. Na janela Choose Training Type , selecione Quick Training

10. Na janela Choose Training Type , selecione Train

imagem

2. Exportando um modelo treinado do serviço Azure Custom Vision


Agora que treinamos nosso modelo, vamos exportá-lo para uso em nosso aplicativo móvel .

Isso nos permitirá usar o modelo sem uma conexão à Internet, o que garantirá a melhor privacidade para o usuário, porque suas fotos nunca sairão do dispositivo móvel.

Para exportar nosso modelo, faça o seguinte:

1. Na janela XamarinImageClassifcation , na parte superior da página, selecione a guia Desempenho

2. Na guia Desempenho , clique no botão Exportar (seta apontando para baixo)

3. Na janela Escolha sua plataforma , selecione TensorFlow

imagem

4. Na lista suspensa Escolha sua plataforma , selecione TensorFlow Lite

5. Na janela Escolha sua plataforma , selecione Baixar

imagem

3. Importe o TensorFlow Lite para o nosso aplicativo Xamarin.Android


1. Instale o pacote NuGet apropriado em nosso projeto Xamarin.Android
Nota: Este pacote NuGet é um projeto de código aberto criado pela equipe Xamarin da Microsoft. Ele contém ligações C # para a biblioteca TensorFlow Lite original , permitindo que ela seja usada em nosso aplicativo Xamarin.Android

2. Descompacte o modelo exportado que baixamos do portal da web de serviço Custom Vision
Nota: dentro do arquivo zip estão labels.txt e model.tflite :

  • labels.txt contém tags de imagem criadas durante a preparação para o treinamento no site Custom Vision
  • models.tflite é o modelo de aprendizado de máquina que usamos para nossas previsões.

3. No Visual Studio, no projeto Xamarin.Android, clique com o botão direito do mouse na pasta Assets

4. No menu pop-up, selecione AdicionarItem Existente ...

5. No menu Adicionar Item Existente , selecione os dois arquivos descompactados recentemente:

  • models.tflite
  • labels.txt

6. No Visual Studio, em Xamarin.AndroidAtivos , clique com o botão direito do mouse em labels.txt

7. No menu pop-up, selecione Propriedades

8. Na janela Propriedades , selecione Build ActionAndroid Asset

9. No Visual Studio, em Xamarin.AndroidAtivos , clique com o botão direito do mouse em models.tflite

10. No menu pop-up, selecione Propriedades

11. Na janela Propriedades , selecione Build ActionAndroid Asset

imagem

4. Implementação do código de classificação de imagem para o Xamarin.Android


Agora que importamos o modelo, é hora de escrever um código.

Como lembrete, um aplicativo de classificação de imagem de amostra completo está disponível no GitHub .

No projeto Xamarin.Android , adicione ImageClassifcationModel.cs e TensorflowClassifier.cs :

ImageClassificationModel.cs


public class ImageClassificationModel 
{ 
    public ImageClassificationModel(string tagName, float probability) 
    { 
        TagName = tagName; 
        Probability = probability; 
    } 
   
    public float Probability { get; } 
    public string TagName { get; } 
}

TensorflowClassifier.cs


using System.Collections.Generic;
using System.IO;
using System.Linq;
using Android.App;
using Android.Graphics;
using Java.IO;
using Java.Nio;
using Java.Nio.Channels;

public class TensorflowClassifier
{
    //FloatSize     4,        4 
    const int FloatSize = 4;
    //PixelSize -     3,        : ,   .
    const int PixelSize = 3;

    public List<ImageClassificationModel> Classify(byte[] image)
    {
        var mappedByteBuffer = GetModelAsMappedByteBuffer();
        var interpreter = new Xamarin.TensorFlow.Lite.Interpreter(mappedByteBuffer);

        //   ,       
        var tensor = interpreter.GetInputTensor(0);
        var shape = tensor.Shape();

        var width = shape[1];
        var height = shape[2];

        var byteBuffer = GetPhotoAsByteBuffer(image, width, height);

        // StreamReader    labels.txt
        var streamReader = new StreamReader(Application.Context.Assets.Open("labels.txt"));

        // labels.txt  List<string>
        var labels = streamReader.ReadToEnd().Split('\n').Select(s => s.Trim()).Where(s => !string.IsNullOrEmpty(s)).ToList();

        //     Java.Lang.Object,    Xamarin.TensorFlow.List.Interpreter.
        var outputLocations = new float[1][] { new float[labels.Count] };
        var outputs = Java.Lang.Object.FromArray(outputLocations);

        interpreter.Run(byteBuffer, outputs);
        var classificationResult = outputs.ToArray<float[]>();

        // classificationResult     ,  ,     
        var classificationModelList = new List<ImageClassificationModel>();

        for (var i = 0; i < labels.Count; i++)
        {
            var label = labels[i]; classificationModelList.Add(new ImageClassificationModel(label, classificationResult[0][i]));
        }

        return classificationModelList;
    }

    // model.tflite  Java.Nio.MappedByteBuffer,    Xamarin.TensorFlow.Lite.Interpreter.
    private MappedByteBuffer GetModelAsMappedByteBuffer()
    {
        var assetDescriptor = Application.Context.Assets.OpenFd("model.tflite");
        var inputStream = new FileInputStream(assetDescriptor.FileDescriptor);

        var mappedByteBuffer = inputStream.Channel.Map(FileChannel.MapMode.ReadOnly, assetDescriptor.StartOffset, assetDescriptor.DeclaredLength);

        return mappedByteBuffer;
    }

    //     TensorFlow
    private ByteBuffer GetPhotoAsByteBuffer(byte[] image, int width, int height)
    {
        var bitmap = BitmapFactory.DecodeByteArray(image, 0, image.Length);
        var resizedBitmap = Bitmap.CreateScaledBitmap(bitmap, width, height, true);

        var modelInputSize = FloatSize * height * width * PixelSize;
        var byteBuffer = ByteBuffer.AllocateDirect(modelInputSize);
        byteBuffer.Order(ByteOrder.NativeOrder());

        var pixels = new int[width * height];
        resizedBitmap.GetPixels(pixels, 0, resizedBitmap.Width, 0, 0, resizedBitmap.Width, resizedBitmap.Height);

        var pixel = 0;

        //     Java.Nio.ByteBuffer
        for (var i = 0; i < width; i++)
        {
            for (var j = 0; j < height; j++)
            {
                var pixelVal = pixels[pixel++];

                byteBuffer.PutFloat(pixelVal >> 16 & 0xFF);
                byteBuffer.PutFloat(pixelVal >> 8 & 0xFF);
                byteBuffer.PutFloat(pixelVal & 0xFF);
            }
        }

        bitmap.Recycle();

        return byteBuffer;
    }
}

Isso é tudo! Agora podemos passar a imagem para TensorflowClassifier.Classify para obter o ImageClassificationModel .

Materiais para estudos adicionais


Confira os links abaixo:


All Articles