Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Observação
Para maior funcionalidade, o PyTorch também pode ser usado com DirectML no Windows.
Na parte anterior deste tutorial, você aprendeu a criar e exportar um modelo no formato ONNX. Agora, mostraremos como inserir o modelo exportado em um aplicativo do Windows e executá-lo localmente em um dispositivo chamando APIs do WinML.
Quando terminarmos, você terá um aplicativo de classificação de imagem em funcionamento.
Sobre o aplicativo de amostra
Nesta etapa do tutorial, você criará um aplicativo capaz de classificar imagens usando seu modelo de ML. A interface do usuário básica dele permite que você selecione uma imagem do dispositivo local e usa o modelo ONNX de classificação que você criou e treinou na parte anterior para classificá-la. As marcações retornadas pelo modelo são exibidas ao lado da imagem.
Aqui, percorreremos esse processo com você.
Observação
Se você optar por usar o exemplo de código predefinido, poderá clonar o arquivo de solução. Clone o repositório, navegue até este exemplo e abra o arquivo classifierPyTorch.sln com o Visual Studio. Vá diretamente para a parte Iniciar o aplicativo desta página para vê-lo em uso.
A seguir, vamos descrever como criar o aplicativo e adicionar código do Windows ML a ele.
Criar um aplicativo UWP do Windows ML (C#)
Para criar um aplicativo do Windows ML funcional, você precisará fazer o seguinte:
- Carregar um modelo de machine learning.
- Carregar uma imagem no formato necessário.
- Associar as entradas e as saídas do modelo.
- Avaliar o modelo e exibir os resultados significativos.
Você também precisará criar uma interface do usuário básica, pois é difícil criar um aplicativo baseado em imagem satisfatório na linha de comando.
Abrir um novo projeto no Visual Studio
- Vamos começar. Abra o Visual Studio e escolha criar um novo projeto.
- Na barra de pesquisa, digite
UWPe selecioneBlank APP (Universal Windows). Isso abre um projeto em C# de um aplicativo UWP (Plataforma Universal do Windows) de página única com controles e layout predefinidos. Selecionenextpara abrir uma janela de configuração para o projeto.
- Na janela de configuração, faça o seguinte:
- Nomeie o projeto. Aqui, o chamamos de classifierPyTorch.
- Escolha o local do projeto.
- Se você está usando o VS2019, verifique se
Create directory for solutionestá marcado. - Se estiver usando o VS2017, verifique se a opção
Place solution and project in the same directoryestá desmarcada.
Pressione create para criar o projeto. A janela de versão de destino mínima pode aparecer. Verifique se sua versão mínima está definida como Windows 10, versão 1809 (10.0; build 17763) ou superior.
- Depois que o projeto for criado, navegue até a pasta do projeto, abra a pasta
[….\classifierPyTorch \Assets]e copie oImageClassifier.onnxarquivo para esse local.
Explorar a solução do projeto
Vamos explorar sua solução de projeto.
O Visual Studio criou automaticamente vários arquivos cs-code dentro do Gerenciador de Soluções.
MainPage.xaml contém o código XAML da GUI e MainPage.xaml.cs contém o código do aplicativo, também conhecido como code-behind. Se você já criou um aplicativo UWP, esses arquivos devem ser muito familiares.
Criar a GUI do aplicativo
Primeiro, vamos criar uma GUI simples para o aplicativo.
Clique duas vezes no arquivo de código
MainPage.xaml. No aplicativo em branco, o modelo XAML da GUI do aplicativo está vazio, de modo que precisaremos adicionar alguns recursos da interface do usuário.Adicione o código abaixo a
MainPage.xaml, substituindo marcas<Grid>e</Grid>.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel Margin="1,0,-1,0">
<TextBlock x:Name="Menu"
FontWeight="Bold"
TextWrapping="Wrap"
Margin="10,0,0,0"
Text="Image Classification"/>
<TextBlock Name="space" />
<Button Name="recognizeButton"
Content="Pick Image"
Click="OpenFileButton_Click"
Width="110"
Height="40"
IsEnabled="True"
HorizontalAlignment="Left"/>
<TextBlock Name="space3" />
<Button Name="Output"
Content="Result is:"
Width="110"
Height="40"
IsEnabled="True"
HorizontalAlignment="Left"
VerticalAlignment="Top">
</Button>
<!--Display the Result-->
<TextBlock Name="displayOutput"
FontWeight="Bold"
TextWrapping="Wrap"
Margin="25,0,0,0"
Text="" Width="1471" />
<TextBlock Name="space2" />
<!--Image preview -->
<Image Name="UIPreviewImage" Stretch="Uniform" MaxWidth="300" MaxHeight="300"/>
</StackPanel>
</Grid>
Adicionar o modelo ao projeto usando o Gerador de Código do Windows ML (mlgen)
O Gerador de Código do Windows Machine Learning, ou mlgen, é uma extensão do Visual Studio para ajudá-lo a começar a usar APIs WinML em aplicativos UWP. Ele gera código de modelo quando você adiciona um arquivo ONNX treinado ao projeto UWP.
O gerador de código do Windows Machine Learning, mlgen, cria uma interface (para C#, C++/WinRT e C++/CX) com classes wrapper que chamam a API do Windows ML para você. Assim, você pode carregar, associar e avaliar facilmente um modelo em seu projeto. Vamos usá-lo neste tutorial para lidar com muitas dessas funções para nós.
O gerador de código está disponível para o Visual Studio 2017 e posterior. Recomendamos usar o Visual Studio. Observe que, no Windows 10 versão 1903 e posterior, o mlgen não está mais incluído no SDK do Windows 10, de modo que você precisa baixar e instalar a extensão. Se você estiver acompanhando este tutorial a partir da introdução, já terá lidado com isso, mas caso contrário, deverá baixar para o VS 2019 ou para o VS 2017.
Observação
Para saber mais sobre mlgen, confira a documentação do mlgen
Se ainda não fez isso, instale o mlgen.
Clique com o botão direito do mouse na pasta
Assetsno Gerenciador de Soluções no Visual Studio e selecioneAdd > Existing Item.Navegue até a pasta de ativos dentro de
classifierPyTorch [….\classifierPyTorch \Assets], localize o modelo ONNX que você copiou nela e selecioneadd.Após você adicionar um modelo ONNX à pasta de ativos no gerenciador de soluções no VS, o projeto deverá ter dois novos arquivos:
-
ImageClassifier.onnx– o modelo no formato ONNX. -
ImageClassifier.cs– arquivo de código WinML gerado automaticamente.
- Para que o modelo seja criado quando você compilar o aplicativo, selecione o arquivo
ImageClassifier.onnxe escolhaProperties. ParaBuild Action, selecioneContent.
Código do arquivo ONNX
Agora, vamos explorar um código que acaba de ser gerado no arquivo ImageClassifier.cs.
O código gerado inclui três classes:
-
ImageClassifierModel: essa classe inclui dois métodos para instanciação de modelo e avaliação de modelo. Ele nos ajudará a criar a representação do modelo de machine learning, criar uma sessão no dispositivo padrão do sistema, associar as entradas e saídas específicas ao modelo e avaliar o modelo de maneira assíncrona. -
ImageClassifierInput: essa classe inicializa os tipos de entrada que o modelo espera. A entrada de modelo depende dos requisitos de modelo para dados de entrada. -
ImageClassifierOutput: essa classe inicializa os tipos que o modelo terá como saída. A saída do modelo depende de como ela é definida pelo modelo.
Neste tutorial, não queremos lidar com a tensorização. Vamos fazer uma pequena alteração na classe ImageClassifierInput, alterar o tipo de dados de entrada e facilitar nossa vida.
- Faça as seguintes alterações no arquivo
ImageClassifier.cs:
Altere a variável input de um TensorFloat para um ImageFeatureValue.
public sealed class ImageClassifierInput
{
public ImageFeatureValue input; // shape(-1,3,32,32)
}
Carregar o modelo
Clique duas vezes no arquivo
MainPage.xaml.cspara abrir o code-behind do aplicativo.Substitua as instruções "using" pelo seguinte para ter acesso a todas as APIs que serão necessárias:
// Specify all the using statements which give us the access to all the APIs that we'll need
using System;
using System.Threading.Tasks;
using Windows.AI.MachineLearning;
using Windows.Graphics.Imaging;
using Windows.Media;
using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
- Adicione as declarações de variável a seguir dentro da classe
MainPage, acima da funçãopublic MainPage().
// All the required fields declaration
private ImageClassifierModel modelGen;
private ImageClassifierInput image = new ImageClassifierInput();
private ImageClassifierOutput results;
private StorageFile selectedStorageFile;
private string label = "";
private float probability = 0;
private Helper helper = new Helper();
public enum Labels
{
plane,
car,
bird,
cat,
deer,
dog,
frog,
horse,
ship,
truck
}
Agora, você vai implementar o método LoadModel. O método acessará o modelo ONNX e o armazenará na memória. Em seguida, você usará o método CreateFromStreamAsync para criar uma instância do modelo como um objeto LearningModel. A classe LearningModel representa um modelo de machine learning treinado. Uma vez instanciado, o LearningModel é o objeto inicial usado para interagir com o Windows ML.
Para carregar o modelo, você pode usar vários métodos estáticos na classe LearningModel. Nesse caso, você usará o método CreateFromStreamAsync.
O método CreateFromStreamAsync foi criado automaticamente com mlgen, portanto, você não precisa implementá-lo. Você pode examiná-lo clicando duas vezes no arquivo classifier.cs gerado por mlgen.
Observação
Para saber mais sobre a classe LearningModel, examine a documentação da classe LearningModel. Para saber mais sobre maneiras adicionais de carregar o modelo, examine a documentação Carregar um modelo
- Adicione uma chamada a um método
loadModelao construtor da classe principal.
// The main page to initialize and execute the model.
public MainPage()
{
this.InitializeComponent();
loadModel();
}
- Adicione a implementação do método
loadModeldentro dessa classeMainPage.
private async Task loadModel()
{
// Get an access the ONNX model and save it in memory.
StorageFile modelFile = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Assets/ImageClassifier.onnx"));
// Instantiate the model.
modelGen = await ImageClassifierModel.CreateFromStreamAsync(modelFile);
}
Carregar a imagem
- Precisamos definir um evento de clique para iniciar a sequência de quatro chamadas de método para execução do modelo: conversão, associação e avaliação, extração de saída e exibição de resultados. Adicione o método a seguir ao seu arquivo de código
MainPage.xaml.csdentro da classeMainPage.
// Waiting for a click event to select a file
private async void OpenFileButton_Click(object sender, RoutedEventArgs e)
{
if (!await getImage())
{
return;
}
// After the click event happened and an input selected, begin the model execution.
// Bind the model input
await imageBind();
// Model evaluation
await evaluate();
// Extract the results
extractResult();
// Display the results
await displayResult();
}
- Agora, você vai implementar o método
getImage(). Esse método vai selecionar um arquivo de imagem de entrada e salvá-lo na memória. Adicione o método a seguir ao seu arquivo de códigoMainPage.xaml.csdentro da classeMainPage.
// A method to select an input image file
private async Task<bool> getImage()
{
try
{
// Trigger file picker to select an image file
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
fileOpenPicker.FileTypeFilter.Add(".jpg");
fileOpenPicker.FileTypeFilter.Add(".png");
fileOpenPicker.ViewMode = PickerViewMode.Thumbnail;
selectedStorageFile = await fileOpenPicker.PickSingleFileAsync();
if (selectedStorageFile == null)
{
return false;
}
}
catch (Exception)
{
return false;
}
return true;
}
Em seguida, você implementará um método Bind() de imagem para obter a representação do arquivo no formato BGRA8 de bitmap. Porém, primeiro vai criar uma classe auxiliar para redimensionar a imagem.
- Para criar um arquivo auxiliar, clique com o botão direito do mouse no nome da solução (
ClassifierPyTorch) e escolhaAdd a new item. Na janela aberta, selecioneClasse dê um nome a ela. Aqui, nós a chamamos deHelper.
- Um novo arquivo de classe aparecerá dentro do seu projeto. Abra essa classe e adicione o seguinte código:
using System;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Media;
namespace classifierPyTorch
{
public class Helper
{
private const int SIZE = 32;
VideoFrame cropped_vf = null;
public async Task<VideoFrame> CropAndDisplayInputImageAsync(VideoFrame inputVideoFrame)
{
bool useDX = inputVideoFrame.SoftwareBitmap == null;
BitmapBounds cropBounds = new BitmapBounds();
uint h = SIZE;
uint w = SIZE;
var frameHeight = useDX ? inputVideoFrame.Direct3DSurface.Description.Height : inputVideoFrame.SoftwareBitmap.PixelHeight;
var frameWidth = useDX ? inputVideoFrame.Direct3DSurface.Description.Width : inputVideoFrame.SoftwareBitmap.PixelWidth;
var requiredAR = ((float)SIZE / SIZE);
w = Math.Min((uint)(requiredAR * frameHeight), (uint)frameWidth);
h = Math.Min((uint)(frameWidth / requiredAR), (uint)frameHeight);
cropBounds.X = (uint)((frameWidth - w) / 2);
cropBounds.Y = 0;
cropBounds.Width = w;
cropBounds.Height = h;
cropped_vf = new VideoFrame(BitmapPixelFormat.Bgra8, SIZE, SIZE, BitmapAlphaMode.Ignore);
await inputVideoFrame.CopyToAsync(cropped_vf, cropBounds, null);
return cropped_vf;
}
}
}
Agora, vamos converter a imagem no formato apropriado.
A classe ImageClassifierInput inicializa os tipos de entrada que o modelo espera. Em nosso caso, configuramos o código para esperar um ImageFeatureValue.
A classe ImageFeatureValue descreve as propriedades da imagem usada para passar para um modelo. Para criar um ImageFeatureValue, use o método CreateFromVideoFrame. Para obter detalhes mais específicos sobre por que esse é o caso e como essas classes e métodos funcionam, consulte a documentação da classe ImageFeatureValue
Observação
Neste tutorial, usamos a classe ImageFeatureValue em vez de um tensor. Se o Windows ML não oferecer suporte ao formato de cor do modelo, essa não será uma opção. Para obter um exemplo de como trabalhar com conversões de imagem e tensorização, consulte o Exemplo de Tensorização Personalizada.
- Adicione a implementação do método
convert()ao seu arquivo de códigoMainPage.xaml.csdentro da classe MainPage. O método convert nos fará uma representação do arquivo de entrada em um formato BGRA8.
// A method to convert and bide the input image.
private async Task imageBind ()
{
UIPreviewImage.Source = null;
try
{
SoftwareBitmap softwareBitmap;
using (IRandomAccessStream stream = await selectedStorageFile.OpenAsync(FileAccessMode.Read))
{
// Create the decoder from the stream
BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream);
// Get the SoftwareBitmap representation of the file in BGRA8 format
softwareBitmap = await decoder.GetSoftwareBitmapAsync();
softwareBitmap = SoftwareBitmap.Convert(softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
}
// Display the image
SoftwareBitmapSource imageSource = new SoftwareBitmapSource();
await imageSource.SetBitmapAsync(softwareBitmap);
UIPreviewImage.Source = imageSource;
// Encapsulate the image within a VideoFrame to be bound and evaluated
VideoFrame inputImage = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
// Resize the image size to 32x32
inputImage=await helper.CropAndDisplayInputImageAsync(inputImage);
// Bind the model input with image
ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputImage);
image.modelInput = imageTensor;
// Encapsulate the image within a VideoFrame to be bound and evaluated
VideoFrame inputImage = VideoFrame.CreateWithSoftwareBitmap(softwareBitmap);
// bind the input image
ImageFeatureValue imageTensor = ImageFeatureValue.CreateFromVideoFrame(inputImage);
image.modelInput = imageTensor;
}
catch (Exception e)
{
}
}
Associar e avaliar o modelo
A seguir, você criará uma sessão com base no modelo, associará a entrada e a saída da sessão e avaliará o modelo.
Criar uma sessão para associar o modelo:
Para criar uma sessão, use a classe LearningModelSession. Essa classe é usada para avaliar modelos de machine learning e associa o modelo a um dispositivo que, por sua vez, executa e avalia o modelo. Você pode selecionar um dispositivo ao criar uma sessão para executar o modelo em um dispositivo específico do computador. O dispositivo padrão é a CPU.
Observação
Para saber mais sobre como escolher um dispositivo, examine a documentação Criar uma sessão .
Associar entradas e saídas do modelo:
Para associar entrada e saída, use a classe LearningModelBinding. Um modelo de machine learning tem recursos de entrada e saída, que transmitem informações para dentro e fora do modelo. Lembre-se de que os recursos necessários devem ter suporte nas APIs do Windows ML. A classe LearningModelBinding é aplicada em um LearningModelSession para associar valores aos recursos de entrada e saída nomeados.
A implementação da associação é gerada automaticamente pelo mlgen, portanto, você não precisa cuidar dela. A associação é implementada chamando os métodos predefinidos da classe LearningModelBinding. Em nosso caso, ela usa o método Bind para associar um valor ao tipo de recurso nomeado.
Avaliar o modelo:
Depois de criar uma sessão para associar o modelo e de associar valores às entradas e saídas do modelo, você pode avaliar as entradas do modelo e obter as previsões. Para executar o modelo, chame um dos métodos de avaliação predefinidos em LearningModelSession. Em nosso caso, usaremos o método EvaluateAsync.
Semelhante a CreateFromStreamAsync, o método EvaluateAsync também foi gerado automaticamente pelo Gerador de Código do WinML, portanto, você não precisa implementá-lo. Examine esse método no arquivo ImageClassifier.cs.
O método EvaluateAsync avaliará de modo assíncrono o modelo de machine learning usando os valores de recurso já associados nas associações. Ele criará uma sessão com LearningModelSession, associará a entrada e a saída com LearningModelBinding, executará a avaliação do modelo e obterá os recursos de saída do modelo usando a classe LearningModelEvaluationResult.
Observação
Para saber mais sobre outros métodos de avaliação para executar o modelo, verifique quais métodos podem ser implementados no LearningModelSession examinando a documentação da Classe LearningModelSession.
- Adicione o método a seguir ao arquivo de código
MainPage.xaml.csdentro da classe MainPage para criar uma sessão, associar e avaliar o modelo.
// A method to evaluate the model
private async Task evaluate()
{
results = await modelGen.EvaluateAsync(image);
}
Extrair e exibir os resultados
Agora, você precisará extrair a saída do modelo e exibir o resultado certo, o que será feito com a implementação dos métodos extractResult e displayResult. Você precisará encontrar a probabilidade mais alta para retornar o rótulo correto.
- Adicione o método
extractResultao seu arquivo de códigoMainPage.xaml.csdentro da classeMainPage.
// A method to extract output from the model
private void extractResult()
{
// Retrieve the results of evaluation
var mResult = results.modelOutput as TensorFloat;
// convert the result to vector format
var resultVector = mResult.GetAsVectorView();
probability = 0;
int index = 0;
// find the maximum probability
for(int i=0; i<resultVector.Count; i++)
{
var elementProbability=resultVector[i];
if (elementProbability > probability)
{
index = i;
}
}
label = ((Labels)index).ToString();
}
- Adicione o método
displayResultao seu arquivo de códigoMainPage.xaml.csdentro da classeMainPage.
private async Task displayResult()
{
displayOutput.Text = label;
}
Pronto! Você criou com êxito o aplicativo Windows Machine Learning com uma GUI básica para testar o modelo de classificação. A próxima etapa é iniciar o aplicativo e executá-lo localmente em seu dispositivo Windows.
Iniciar o aplicativo
Depois de concluir a interface do aplicativo, adicionar o modelo e gerar o código do Windows ML, você poderá testar o aplicativo.
Habilite o modo de desenvolvedor e teste seu aplicativo com o Visual Studio. Verifique se os menus suspensos na barra de ferramentas superior estão definidos como Debug. Altere a Plataforma de Solução para x64 para executar o projeto no computador local se seu dispositivo for de 64 bits ou x86 se for de 32 bits.
Nosso modelo foi treinado para classificar as seguintes imagens: avião, carro, ave, gato, veado, cão, sapo, cavalo, navio, caminhão. Para testar o aplicativo, você usará a imagem do carro de Lego criada para este projeto. Vamos ver como o aplicativo classifica o conteúdo da imagem.
Salve essa imagem em seu dispositivo local para testar o aplicativo. Altere o formato da imagem para
.jpg, se necessário. Você também pode adicionar outra imagem relevante do dispositivo local em um formato .jpg ou .png.Para executar o projeto, selecione o botão
Start Debuggingna barra de ferramentas ou pressioneF5.Quando o aplicativo for iniciado, pressione Escolher imagem e selecione a imagem do dispositivo local.
O resultado será exibido na tela imediatamente. Como você pode ver, nosso aplicativo do Windows ML classificou com êxito a imagem como um carro.
Resumo
Você acabou de criar seu primeiro aplicativo do Windows Machine Learning, da criação do modelo até a execução bem-sucedida.
Recursos adicionais
Para saber mais sobre os tópicos mencionados neste tutorial, visite os seguintes recursos:
- Ferramentas do Windows ML: conheça mais ferramentas como o Painel do Windows ML, o WinMLRunner e o gerador de código do Windows ML mlgen.
- Modelo ONNX: saiba mais sobre o formato ONNX.
- Desempenho e memória do Windows ML: saiba mais sobre como gerenciar o desempenho do aplicativo com o Windows ML.
- Referência da API do Windows Machine Learning: saiba mais sobre três áreas de APIs do Windows ML.