evento
19/11, 23 - 21/11, 23
Ganhe a vantagem competitiva de que precisa com poderosas soluções de IA e Cloud ao participar online do Microsoft Ignite.
Registe-se agoraEste browser já não é suportado.
Atualize para o Microsoft Edge para tirar partido das mais recentes funcionalidades, atualizações de segurança e de suporte técnico.
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.
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ê.
Nota
Se você optar por usar o exemplo de código predefinido, poderá clonar o arquivo da 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.
Para criar um aplicativo do Windows ML funcional, você precisará fazer o seguinte:
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.
UWP
e selecione Blank 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. Selecione next
para abrir uma janela de configuração para o projeto.Create directory for solution
está marcado.Place solution and project in the same directory
está desmarcada.Pressione create
para criar o projeto. A janela de versão de destino mínima pode aparecer. Verifique se a versão mínima está definida como Windows 10, versão 1809 (10.0; build 17763) ou posterior.
[….\classifierPyTorch \Assets]
e copie o arquivo ImageClassifier.onnx
para esse local.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.
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>
O Gerador de Código do Windows Machine Learning, ou mlgen, é uma extensão do Visual Studio que ajuda você a começar a usar APIs do 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 está acompanhando o tutorial desde a introdução, você já cuidou disso. Caso contrário, baixe-o para o VS 2019 ou o VS 2017.
Nota
Para saber mais sobre o 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 Assets
no Gerenciador de Soluções no Visual Studio e selecione Add > Existing Item
.
Navegue até a pasta de ativos dentro de classifierPyTorch [….\classifierPyTorch \Assets]
, localize o modelo ONNX que você copiou nela e selecione add
.
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.ImageClassifier.onnx
e escolha Properties
. Para Build Action
, selecione Content
.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.
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)
}
Clique duas vezes no arquivo MainPage.xaml.cs
para 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;
MainPage
, acima da função public 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.
Nota
Para saber mais sobre a classe LearningModel
, examine a documentação da classe LearningModel. Para saber mais sobre outras maneiras de carregar o modelo, examine a documentação Carregar um modelo
loadModel
ao construtor da classe principal. // The main page to initialize and execute the model.
public MainPage()
{
this.InitializeComponent();
loadModel();
}
loadModel
dentro dessa classe MainPage
. 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);
}
MainPage.xaml.cs
dentro da classe MainPage
. // 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();
}
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ódigo MainPage.xaml.cs
dentro da classe MainPage
. // 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.
ClassifierPyTorch
) e escolha Add a new item
. Na janela aberta, selecione Class
e dê um nome a ela. Aqui, nós a chamamos de Helper
.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, confira a documentação da classe ImageFeatureValue
Nota
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, confira o Exemplo de tensorização personalizado.
convert()
ao seu arquivo de código MainPage.xaml.cs
dentro 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)
{
}
}
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.
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.
Nota
Para saber mais sobre como escolher um dispositivo, examine a documentação Criar uma sessão.
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.
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
.
Nota
Para saber mais sobre outros métodos de avaliação para executar o modelo, verifique quais métodos podem ser implementados em LearningModelSession examinando a documentação da Classe LearningModelSession.
MainPage.xaml.cs
dentro 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);
}
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.
extractResult
ao seu arquivo de código MainPage.xaml.cs
dentro da classe MainPage
. // 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();
}
displayResult
ao seu arquivo de código MainPage.xaml.cs
dentro da classe MainPage
. 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.
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 Debugging
na barra de ferramentas ou pressione F5
.
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.
Você acabou de criar seu primeiro aplicativo do Windows Machine Learning, da criação do modelo até a execução bem-sucedida.
Para saber mais sobre os tópicos mencionados neste tutorial, visite os seguintes recursos:
evento
19/11, 23 - 21/11, 23
Ganhe a vantagem competitiva de que precisa com poderosas soluções de IA e Cloud ao participar online do Microsoft Ignite.
Registe-se agora