Tutorial: Use a Visão de IA do Azure para gerar metadados de imagem no Armazenamento do Azure

Neste tutorial, você aprenderá a integrar o serviço Visão de IA do Azure em um aplicativo Web para gerar metadados para imagens carregadas. Isso é útil para cenários de DAM (gerenciamento de ativos digitais), assim como quando uma empresa deseja gerar rapidamente legendas descritivas ou palavras-chave pesquisáveis para todas as suas imagens.

Você usará o Visual Studio para escrever um aplicativo Web MVC que aceite imagens carregadas por usuários e as armazene no armazenamento de blobs do Azure. Saiba como ler e gravar blobs em C# e usar metadados de blob para anexar informações adicionais aos blobs criados. Em seguida, você enviará cada imagem carregada pelo usuário para a API da Visão de IA do Azure para gerar uma legenda e pesquisar metadados para a imagem. Por fim, será possível implantar o aplicativo na nuvem usando o Visual Studio.

Este tutorial mostra como:

  • Criar uma conta de armazenamento e contêineres de armazenamento usando o portal do Azure
  • Criar um aplicativo Web no Visual Studio para implantá-lo no Azure
  • Usar a API da Visão de IA do Azure para extrair informações de imagens
  • Anexar metadados a imagens do Armazenamento do Azure
  • Verificar os metadados de uma imagem usando o Gerenciador de Armazenamento do Azure

Dica

A seção Usar a Visão de IA do Azure para gerar metadados é mais relevante para a análise de imagens. Pule para essa seção se quiser ver apenas como a Análise de Imagem é integrada a um aplicativo estabelecido.

Se você não tiver uma assinatura do Azure, crie uma conta gratuita antes de começar.

Pré-requisitos

Criar uma conta de armazenamento

Nesta seção, você criará uma conta de armazenamento usando o portal do Azure. Em seguida, você criará um par de contêineres: um para armazenar imagens carregadas pelo usuário e outro para armazenar miniaturas de imagem geradas com as imagens carregadas.

  1. Entre no portal do Azure através do seu navegador. Se for solicitada a conexão, faça isso usando sua conta Microsoft.

  2. Para criar uma conta de armazenamento, selecione + Criar um recurso na faixa de opções à esquerda. Em seguida, selecione Armazenamento, seguido de Conta de armazenamento.

    Creating a storage account

  3. Insira um nome exclusivo para a conta de armazenamento no campo Nome e verifique se uma marca de seleção verde aparece ao lado dele. O nome é importante porque forma uma parte da URL por meio da qual os blobs criados nessa conta são acessados. Coloque a conta de armazenamento em um novo grupo de recursos chamado "IntellipixResources" e selecione a região mais próxima de você. Conclua selecionando o botão Examinar + criar na parte inferior da tela para criar a nova conta de armazenamento.

    Observação

    Os nomes de contas de armazenamento devem ter entre três e 24 caracteres e podem conter somente números e letras minúsculas. Além disso, o nome inserido deve ser exclusivo no Azure. Se outra pessoa tiver escolhido o mesmo nome, você será notificado de que ele não está disponível com um ponto de exclamação vermelho no campo Nome.

    Specifying parameters for a new storage account

  4. Selecione Grupos de recursos na faixa de opções à esquerda. Em seguida, selecione o grupo de recursos "IntellipixResources".

    Opening the resource group

  5. Na guia que é aberta para o grupo de recursos, selecione a conta de armazenamento que você criou. Se a conta de armazenamento ainda não estiver lá, você pode selecionar Atualizar na parte superior da guia até que ela apareça.

    Opening the new storage account

  6. Na guia da conta de armazenamento, selecione Blobs para exibir uma lista de contêineres associados a essa conta.

    Viewing blobs button

  7. Atualmente, a conta de armazenamento não tem contêineres. Antes de criar um blob, é necessário criar um contêiner para armazená-lo. Escolha + Contêiner para criar um contêiner. Digite photos no campo Nome e escolha Blob como o Nível de acesso público. Em seguida, selecione OK para criar um contêiner chamado "fotos".

    Por padrão, os contêineres e o conteúdo deles são privados. Selecionar Blob como o nível de acesso torna os blobs no contêiner "photos" publicamente acessíveis, mas isso não torna o contêiner em si público. Isso é o que você deseja porque as imagens armazenadas no contêiner "photos" serão vinculadas por um aplicativo Web.

    Creating a

  8. Repita a etapa anterior para criar um contêiner chamado "thumbnails", garantindo mais uma vez que o Nível de acesso público do contêiner seja definido como Blob.

  9. Confirme se ambos os contêineres aparecem na lista de contêineres dessa conta de armazenamento e se os nomes estão escritos corretamente.

    The new containers

  10. Feche a tela "Serviço de blob". Selecione Chaves de acesso no menu do lado esquerdo da tela da conta de armazenamento e, em seguida, selecione o botão Copiar ao lado de CHAVE para a chave1. Cole essa chave de acesso em seu editor de texto preferencial para uso posterior.

    Copying the access key

Agora, uma conta de armazenamento foi criada para manter as imagens carregadas no aplicativo a ser criado e os contêineres para armazená-las.

Executar o Gerenciador de Armazenamento do Azure

O Gerenciador de Armazenamento do Azure é uma ferramenta gratuita que fornece uma interface gráfica para trabalhar com o Armazenamento do Azure em computadores que executam Windows, macOS e Linux. Ele fornece a maior parte da mesma funcionalidade do portal do Azure, além de outros recursos, como a capacidade de exibir metadados de blob. Nesta seção, você usará o Gerenciador de Armazenamento do Microsoft Azure para exibir os contêineres criados na seção anterior.

  1. Se você ainda não tiver instalado o Gerenciador de Armazenamento ou quiser ter certeza de que está executando a versão mais recente, acesse http://storageexplorer.com/ para fazer o download e instalar o produto.

  2. Inicie o Gerenciador de Armazenamento. Se a conexão for solicitada, use a mesma conta Microsoft usada para entrar no portal do Azure. Se você não vir a conta de armazenamento no painel esquerdo do Gerenciador de Armazenamento, selecione o botão Gerenciar contas destacado abaixo e verifique se a sua conta Microsoft e a assinatura usada para criar a conta de armazenamento foram adicionadas ao Gerenciador de Armazenamento.

    Managing accounts in Storage Explorer

  3. Selecione a seta pequena ao lado da conta de armazenamento para exibir seu conteúdo e, em seguida, selecione a seta ao lado de Contêineres de Blob. Confirme se os contêineres que você criou aparecem na lista.

    Viewing blob containers

No momento, os contêineres estão vazios, mas isso mudará depois que o aplicativo for implantado e você começar a carregar fotos. Instalar o Gerenciador de Armazenamento facilita a exibição do que foi gravado pelo aplicativo no armazenamento de blobs.

Criar um novo aplicativo Web no Visual Studio

Nesta seção, você criará um novo aplicativo Web no Visual Studio e adicionará códigos para implementar a funcionalidade básica necessária para carregar imagens, gravá-las no armazenamento de blobs e exibi-las em uma página da Web.

  1. Inicie o Visual Studio e use o comando Arquivo -> Novo -> Projeto para criar um projeto de Aplicativo Web ASP.NET do Visual C# chamado "Intellipix" (abreviação de "imagens inteligentes").

    Creating a new Web Application project

  2. Na caixa de diálogo “Novo aplicativo Web ASP.NET”, selecione MVC. Em seguida, selecione OK.

    Creating a new ASP.NET MVC project

  3. Reserve um momento para analisar a estrutura do projeto no Gerenciador de Soluções. Entre outras coisas, há uma pasta chamada Controladores, que contém os controladores MVC do projeto, e uma pasta chamada Exibições, que contém as exibições do projeto. Você trabalhará com ativos nessas pastas e em outras para implementar o aplicativo.

    The project shown in Solution Explorer

  4. Use o comando Depurar -> Iniciar sem depuração do Visual Studio (ou pressione Ctrl+F5) para iniciar o aplicativo no navegador. Veja a aparência do aplicativo em seu estado atual:

    The initial application

  5. Feche o navegador e retorne ao Visual Studio. No Gerenciador de Soluções, clique com o botão direito do mouse no projeto Intellipix e selecione Gerenciar Pacotes NuGet.... Selecione Navegar. Em seguida, digite imageresizer na caixa de pesquisa e selecione o pacote NuGet chamado ImageResizer. Por fim, selecione Instalar para instalar a versão estável mais recente do pacote. O ImageResizer contém APIs que serão usadas na criação de miniaturas das imagens carregadas no aplicativo. Selecione OK para quaisquer alterações e aceite as licenças apresentadas a você.

    Installing ImageResizer

  6. Repita esse processo para adicionar o pacote NuGet chamado WindowsAzure.Storage ao projeto. Este pacote contém APIs para acessar o Armazenamento do Azure de aplicativos .NET. Selecione OK para quaisquer alterações e aceite as licenças apresentadas a você.

    Installing WindowsAzure.Storage

  7. Abra Web.config e adicione a seguinte instrução à seção <appSettings>, substituindo ACCOUNT_NAME pelo nome da conta de armazenamento criada na primeira seção e ACCOUNT_KEY pela chave de acesso salva.

    <add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=ACCOUNT_NAME;AccountKey=ACCOUNT_KEY" />
    

    Importante

    O arquivo Web.config destina-se a reter informações confidenciais, como as chaves de assinatura, e todas as solicitações HTTP para um arquivo com a extensão .config são manipuladas pelo mecanismo ASP.NET, que retorna uma mensagem "Este tipo de página não é atendido". No entanto, se um invasor conseguir encontrar alguma outra exploração que permita exibir o conteúdo do Web.config, ele poderá expor essas informações. Consulte Proteger as cadeias de conexão e outras informações de configuração para obter as etapas adicionais que você poderá executar para proteger ainda mais os dados do Web.config.

  8. Abra o arquivo _Layout.cshtml na pasta Exibições/Compartilhado do projeto. Na linha 19, altere "nome do aplicativo" para "Intellipix". A linha deve ter a seguinte aparência:

    @Html.ActionLink("Intellipix", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
    

    Observação

    Em um projeto MVC de ASP.NET, _Layout.cshtml é uma exibição especial que serve como um modelo para outras. Normalmente, você define conteúdos de rodapé e título comuns a todas as exibições nesse arquivo.

  9. Clique com o botão direito do mouse na pasta Modelos do projeto e use o comando Adicionar -> Classe... para adicionar um arquivo de classe chamado BlobInfo.cs à pasta. Em seguida, substitua a classe BlobInfo vazia pela seguinte definição de classe:

    public class BlobInfo
    {
        public string ImageUri { get; set; }
        public string ThumbnailUri { get; set; }
        public string Caption { get; set; }
    }
    
  10. Abra HomeController.cs na pasta Controladores do projeto e adicione as seguintes instruções using na parte superior do arquivo:

    using ImageResizer;
    using Intellipix.Models;
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;
    using System.Configuration;
    using System.Threading.Tasks;
    using System.IO;
    
  11. Substitua o método Índice em HomeController.cs pela seguinte implementação:

    public ActionResult Index()
    {
        // Pass a list of blob URIs in ViewBag
        CloudStorageAccount account = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);
        CloudBlobClient client = account.CreateCloudBlobClient();
        CloudBlobContainer container = client.GetContainerReference("photos");
        List<BlobInfo> blobs = new List<BlobInfo>();
    
        foreach (IListBlobItem item in container.ListBlobs())
        {
            var blob = item as CloudBlockBlob;
    
            if (blob != null)
            {
                blobs.Add(new BlobInfo()
                {
                    ImageUri = blob.Uri.ToString(),
                    ThumbnailUri = blob.Uri.ToString().Replace("/photos/", "/thumbnails/")
                });
            }
        }
    
        ViewBag.Blobs = blobs.ToArray();
        return View();
    }
    

    O novo método Índice enumera os blobs no contêiner "photos" e envia uma matriz de objetos BlobInfo que representam esses blobs para a exibição por meio da propriedade ViewBag do MVC de ASP.NET. Posteriormente, você modificará a exibição para enumerar esses objetos e exibir uma coleção de miniaturas de foto. As classes usadas para acessar sua conta de armazenamento e enumerar os blobs CloudStorageAccount, CloudBlobClient e CloudBlobContainer são provenientes do pacote WindowsAzure.Storage instalado com o NuGet.

  12. Adicione o seguinte método à classe HomeController em HomeController.cs:

    [HttpPost]
    public async Task<ActionResult> Upload(HttpPostedFileBase file)
    {
        if (file != null && file.ContentLength > 0)
        {
            // Make sure the user selected an image file
            if (!file.ContentType.StartsWith("image"))
            {
                TempData["Message"] = "Only image files may be uploaded";
            }
            else
            {
                try
                {
                    // Save the original image in the "photos" container
                    CloudStorageAccount account = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);
                    CloudBlobClient client = account.CreateCloudBlobClient();
                    CloudBlobContainer container = client.GetContainerReference("photos");
                    CloudBlockBlob photo = container.GetBlockBlobReference(Path.GetFileName(file.FileName));
                    await photo.UploadFromStreamAsync(file.InputStream);
    
                    // Generate a thumbnail and save it in the "thumbnails" container
                    using (var outputStream = new MemoryStream())
                    {
                        file.InputStream.Seek(0L, SeekOrigin.Begin);
                        var settings = new ResizeSettings { MaxWidth = 192 };
                        ImageBuilder.Current.Build(file.InputStream, outputStream, settings);
                        outputStream.Seek(0L, SeekOrigin.Begin);
                        container = client.GetContainerReference("thumbnails");
                        CloudBlockBlob thumbnail = container.GetBlockBlobReference(Path.GetFileName(file.FileName));
                        await thumbnail.UploadFromStreamAsync(outputStream);
                    }
                }
                catch (Exception ex)
                {
                    // In case something goes wrong
                    TempData["Message"] = ex.Message;
                }
            }
        }
    
        return RedirectToAction("Index");
    }
    

    Esse é o método chamado quando você carrega uma foto. Ele armazena cada imagem carregada como um blob no contêiner "photos", cria uma imagem em miniatura da imagem original usando o pacote ImageResizer e armazena essa imagem em miniatura como um blob no contêiner "thumbnails".

  13. Abra Index.cshmtl na pasta Exibições/Página Inicial do projeto e substitua o conteúdo pelo código e pela marcação a seguir:

    @{
        ViewBag.Title = "Intellipix Home Page";
    }
    
    @using Intellipix.Models
    
    <div class="container" style="padding-top: 24px">
        <div class="row">
            <div class="col-sm-8">
                @using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
                {
                    <input type="file" name="file" id="upload" style="display: none" onchange="$('#submit').click();" />
                    <input type="button" value="Upload a Photo" class="btn btn-primary btn-lg" onclick="$('#upload').click();" />
                    <input type="submit" id="submit" style="display: none" />
                }
            </div>
            <div class="col-sm-4 pull-right">
            </div>
        </div>
    
        <hr />
    
        <div class="row">
            <div class="col-sm-12">
                @foreach (BlobInfo blob in ViewBag.Blobs)
                {
                    <img src="@blob.ThumbnailUri" width="192" title="@blob.Caption" style="padding-right: 16px; padding-bottom: 16px" />
                }
            </div>
        </div>
    </div>
    
    @section scripts
    {
        <script type="text/javascript" language="javascript">
            if ("@TempData["Message"]" !== "") {
                alert("@TempData["Message"]");
            }
        </script>
    }
    

    A linguagem usada aqui é Razor, que permite inserir códigos executáveis na marcação HTML. A instrução @foreach no meio do arquivo enumera os objetos BlobInfo enviados pelo controlador em ViewBag e cria elementos HTML <img> com base neles. A propriedade src de cada elemento é inicializada com o URI do blob que contém a miniatura da imagem.

  14. Baixe e descompacte o arquivo photos.zip do repositório GitHub de dados de amostra. Essa é uma variedade de fotos diferentes que você pode usar para testar o aplicativo.

  15. Salve as alterações e pressione Ctrl+F5 para iniciar o aplicativo no navegador. Em seguida, selecione Carregar uma Foto e carregue uma das imagens baixadas. Confirme se uma versão em miniatura da foto aparece na página.

    Intellipix with one photo uploaded

  16. Carregue mais algumas imagens da pasta photos. Confirme se elas também aparecem na página:

    Intellipix with three photos uploaded

  17. Clique com o botão direito no navegador e selecione Exibir origem da página para exibir o código-fonte da página. Encontre os elementos <img> que representam as miniaturas de imagem. Observe que as URLs atribuídas às imagens se referem diretamente a blobs no armazenamento de blobs. Isso porque você definiu o Nível de acesso públicodos contêineres como Blob, o que torna os blobs neles acessíveis publicamente.

  18. Volte para o Gerenciador de Armazenamento do Azure (ou reinicie-o se você não o deixou em execução) e selecione o contêiner "photos" na conta de armazenamento. O número de blobs no contêiner deve ser igual ao número de fotos que você carregou. Clique duas vezes em um dos blobs para baixá-lo e ver a imagem armazenada nele.

    Contents of the

  19. Abra o contêiner "thumbnails" no Gerenciador de Armazenamento. Abra um dos blobs para exibir as imagens em miniatura geradas com os uploads de imagem.

O aplicativo ainda não oferece uma maneira de exibir as imagens originais carregadas. O ideal é que a seleção de uma miniatura de imagem exiba a imagem original. O recurso será adicionado em seguida.

Adicionar uma caixa de luz para exibir fotos

Nesta seção, você usará uma biblioteca JavaScript gratuita e de software livre para adicionar um visualizador de caixa de luz que permite aos usuários ver as imagens originais que eles carregaram (em vez de apenas as miniaturas da imagem). Os arquivos são fornecidos para você. Tudo o que você precisa fazer é integrá-los ao projeto e fazer uma pequena modificação em Index.cshtml.

  1. Baixe os arquivos lightbox.css e lightbox.js do repositório GitHub de códigos.

  2. No Gerenciador de Soluções, clique com o botão direito do mouse na pasta Scripts do projeto e use o comando Adicionar -> Novo Item... para criar um arquivo lightbox.js. Cole o conteúdo do arquivo de exemplo no repositório GitHub de códigos.

  3. Clique com o botão direito do mouse na pasta "Conteúdo" do projeto e use o comando Adicionar -> Novo Item... para criar um arquivo lightbox.css. Cole o conteúdo do arquivo de exemplo no repositório GitHub de códigos.

  4. Baixe e descompacte o arquivo buttons.zip do repositório GitHub de arquivos de dados: https://github.com/Azure-Samples/cognitive-services-sample-data-files/tree/master/ComputerVision/storage-lab-tutorial. Quatro imagens de botão devem ser exibidas.

  5. Clique com o botão direito do mouse no projeto Intellipix no Gerenciador de Soluções e use o comando Adicionar -> Nova pasta para adicionar uma pasta chamada "Imagens" ao projeto.

  6. Clique com o botão direito do mouse na pasta Imagens e use o comando Adicionar -> Item existente... para importar as quatro imagens que você baixou.

  7. Abra BundleConfig.cs na pasta "App_Start" do projeto. Adicione a seguinte instrução ao método RegisterBundles no BundleConfig.cs:

    bundles.Add(new ScriptBundle("~/bundles/lightbox").Include(
              "~/Scripts/lightbox.js"));
    
  8. No mesmo método, encontre a instrução que cria um StyleBundle em "~/Content/css" e adicione lightbox.css à lista de folhas de estilos no pacote. Veja abaixo a instrução modificada:

    bundles.Add(new StyleBundle("~/Content/css").Include(
              "~/Content/bootstrap.css",
              "~/Content/site.css",
              "~/Content/lightbox.css"));
    
  9. Abra _Layout.cshtml na pasta Exibições/Compartilhado do projeto e adicione a seguinte instrução antes da instrução @RenderSection na parte inferior:

    @Scripts.Render("~/bundles/lightbox")
    
  10. A tarefa final é incorporar o visualizador lightbox na página inicial. Para isso, abra Index.cshtml (na pasta Exibições/Página inicial do projeto) e substitua o loop @foreach pelo seguinte:

    @foreach (BlobInfo blob in ViewBag.Blobs)
    {
        <a href="@blob.ImageUri" rel="lightbox" title="@blob.Caption">
            <img src="@blob.ThumbnailUri" width="192" title="@blob.Caption" style="padding-right: 16px; padding-bottom: 16px" />
        </a>
    }
    
  11. Salve as alterações e pressione Ctrl+F5 para iniciar o aplicativo no navegador. Em seguida, selecione uma das imagens que você carregou anteriormente. Confirme se você vê uma caixa de luz mostrando uma exibição ampliada da imagem.

    An enlarged image

  12. Selecione o X no canto inferior direito da caixa de luz para dispensá-la.

Agora é possível exibir as imagens carregadas. A próxima etapa é fazer mais coisas com essas imagens.

Usar a Visão de IA do Azure para gerar metadados

Criar um recurso de Visão

Você precisará criar um recurso da Pesquisa Visual Computacional para sua conta do Azure; esse recurso gerencia o seu acesso ao serviço Visão de IA do Azure.

  1. Siga as instruções em Criar um recurso de serviços de IA do Azure para criar um recurso de vários serviços ou um recurso de Visão.

  2. Em seguida, vá para o menu do seu grupo de recursos e selecione o recurso de Visão que você criou. Copie a URL em Ponto de extremidade para algum lugar em que poderá recuperá-la com facilidade em pouco tempo. Em seguida, selecione Mostrar chaves de acesso.

    Azure portal page with the endpoint URL and access keys link outlined

    Observação

    Os novos recursos criados após 1º de julho de 2019 usarão nomes de subdomínio personalizados. Para obter mais informações e uma lista completa de pontos de extremidade regionais, confira Nomes de subdomínio personalizados para os serviços de IA do Azure.

  3. Na próxima janela, copie o valor de KEY 1 para a área de transferência.

    Manage keys dialog, with the copy button outlined

Adicionar credenciais da Visão de IA do Azure

Em seguida, você adicionará as credenciais necessárias ao seu aplicativo para que ele possa acessar os recursos de Visão.

Acesse o arquivo Web.config na raiz do projeto. Adicione as instruções a seguir à seção <appSettings> do arquivo, substituindo VISION_KEY pela chave copiada na etapa anterior e VISION_ENDPOINT pela URL salva na etapa anterior.

<add key="SubscriptionKey" value="VISION_KEY" />
<add key="VisionEndpoint" value="VISION_ENDPOINT" />

No Gerenciador de Soluções. clique com o botão direito do mouse na solução do projeto e selecione Gerenciar Pacotes NuGet. No gerenciador de pacotes aberto, selecione Procurar, marque Incluir pré-lançamento e pesquise Azure.AI.Vision.ImageAnalysis. Selecione Instalar.

Adicionar o código de geração de metadados

Em seguida, você adicionará o código que realmente usa o serviço Visão de IA do Azure para criar metadados para imagens.

  1. Abra o arquivo HomeController.cs da pasta Controllers do projeto e adicione as seguintes instruções using na parte superior do arquivo:

    using Azure;
    using Azure.AI.Vision.ImageAnalysis;
    using System;
    
  2. Em seguida, acesse o método Upload; esse método converte e carrega imagens no armazenamento de blobs. Adicione o código a seguir imediatamente após o bloco que começa com // Generate a thumbnail (ou ao final do processo de criação do blob de imagem). Esse código pega o blob que contém a imagem (photo) e usa a Visão de IA do Azure para gerar uma descrição para essa imagem. A API da Visão de IA do Azure também gera uma lista de palavras-chave que se aplicam à imagem. A descrição e as palavras-chave geradas são armazenadas nos metadados do blob para que possam ser recuperadas posteriormente.

    // create a new ImageAnalysisClient
    ImageAnalysisClient client = new ImageAnalysisClient(
            new Uri(Environment.GetEnvironmentVariable(ConfigurationManager.AppSettings["VisionEndpoint"])),
            new AzureKeyCredential(ConfigurationManager.AppSettings["SubscriptionKey"]));
    
    VisualFeatures = visualFeatures = VisualFeatures.Caption | VisualFeatures.Tags;
    
    ImageAnalysisOptions analysisOptions = new ImageAnalysisOptions()
    {
        GenderNeutralCaption = true,
        Language = "en",
    };
    
    Uri imageURL = new Uri(photo.Uri.ToString());
    
    ImageAnalysisResult  result = client.Analyze(imageURL,visualFeatures,analysisOptions);
    
    // Record the image description and tags in blob metadata
    photo.Metadata.Add("Caption", result.Caption.Text);
    
    for (int i = 0; i < result.Tags.Values.Count; i++)
    {
        string key = String.Format("Tag{0}", i);
        photo.Metadata.Add(key, result.Tags.Values[i]);
    }
    
    await photo.SetMetadataAsync();
    
  3. Em seguida, vá para o método Index no mesmo arquivo. Esse método enumera os blobs de imagem armazenados no contêiner de blobs de destino (como instâncias IListBlobItem) e passa-os para a exibição do aplicativo. Substitua o bloco foreach nesse método pelo código a seguir. Esse código chama CloudBlockBlob.FetchAttributes para obter os metadados anexados de cada blob. Ele extrai a descrição gerada por computador (caption) dos metadados e adiciona-o ao objeto BlobInfo, que é passado para a exibição.

    foreach (IListBlobItem item in container.ListBlobs())
    {
        var blob = item as CloudBlockBlob;
    
        if (blob != null)
        {
            blob.FetchAttributes(); // Get blob metadata
            var caption = blob.Metadata.ContainsKey("Caption") ? blob.Metadata["Caption"] : blob.Name;
    
            blobs.Add(new BlobInfo()
            {
                ImageUri = blob.Uri.ToString(),
                ThumbnailUri = blob.Uri.ToString().Replace("/photos/", "/thumbnails/"),
                Caption = caption
            });
        }
    }
    

Testar o aplicativo

Salve as alterações no Visual Studio e pressione Ctrl+F5 para iniciar o aplicativo no navegador. Use o aplicativo para carregar mais algumas imagens, tanto do conjunto de fotos baixado quanto de sua própria pasta. Ao passar o cursor sobre uma das novas imagens na exibição, uma janela de dica de ferramenta aparecerá para exibir a legenda gerada por computador para a imagem.

The computer-generated caption

Para exibir todos os metadados anexados, use o Gerenciador de Armazenamento do Azure a fim de exibir o contêiner de armazenamento usado para as imagens. Clique com o botão direito do mouse em um dos blobs do contêiner e selecione Propriedades. Na caixa de diálogo, você verá uma lista de pares chave-valor. A descrição da imagem gerada por computador é armazenada no item Caption e as palavras-chave de pesquisa são armazenadas em Tag0, Tag1 e assim por diante. Ao terminar, selecione Cancelar para fechar a caixa de diálogo.

Image properties dialog window, with metadata tags listed

Adicionar uma pesquisa ao aplicativo

Nesta seção, você adicionará uma caixa de pesquisa à página inicial, permitindo que os usuários façam pesquisas de palavra-chave nas imagens carregadas. As palavras-chave são aquelas geradas pela API da Visão de IA do Azure e armazenadas em metadados de blob.

  1. Abra Index.cshtml na pasta Exibições/Página inicial do projeto e adicione as seguintes instruções ao elemento <div> vazio com o atributo class="col-sm-4 pull-right":

    @using (Html.BeginForm("Search", "Home", FormMethod.Post, new { enctype = "multipart/form-data", @class = "navbar-form" }))
    {
        <div class="input-group">
            <input type="text" class="form-control" placeholder="Search photos" name="term" value="@ViewBag.Search" style="max-width: 800px">
            <span class="input-group-btn">
                <button class="btn btn-primary" type="submit">
                    <i class="glyphicon glyphicon-search"></i>
                </button>
            </span>
        </div>
    }
    

    Esse código e essa marcação adicionam uma caixa de pesquisa e um botão de Pesquisa à pagina inicial.

  2. Abra HomeController.cs da pasta Controladores do projeto e adicione o seguinte método à classe HomeController:

    [HttpPost]
    public ActionResult Search(string term)
    {
        return RedirectToAction("Index", new { id = term });
    }
    

    Esse método é chamado quando o usuário seleciona o botão Pesquisar adicionado na etapa anterior. Ele atualiza a página e inclui um parâmetro de pesquisa na URL.

  3. Substitua o método Índice atual pela implementação a seguir:

    public ActionResult Index(string id)
    {
        // Pass a list of blob URIs and captions in ViewBag
        CloudStorageAccount account = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"]);
        CloudBlobClient client = account.CreateCloudBlobClient();
        CloudBlobContainer container = client.GetContainerReference("photos");
        List<BlobInfo> blobs = new List<BlobInfo>();
    
        foreach (IListBlobItem item in container.ListBlobs())
        {
            var blob = item as CloudBlockBlob;
    
            if (blob != null)
            {
                blob.FetchAttributes(); // Get blob metadata
    
                if (String.IsNullOrEmpty(id) || HasMatchingMetadata(blob, id))
                {
                    var caption = blob.Metadata.ContainsKey("Caption") ? blob.Metadata["Caption"] : blob.Name;
    
                    blobs.Add(new BlobInfo()
                    {
                        ImageUri = blob.Uri.ToString(),
                        ThumbnailUri = blob.Uri.ToString().Replace("/photos/", "/thumbnails/"),
                        Caption = caption
                    });
                }
            }
        }
    
        ViewBag.Blobs = blobs.ToArray();
        ViewBag.Search = id; // Prevent search box from losing its content
        return View();
    }
    

    Observe que o método Índice agora aceita um parâmetro id que contém o valor digitado pelo usuário na caixa de pesquisa. Um parâmetro id vazio ou ausente indica que todas as fotos devem ser exibidas.

  4. Adicione o seguinte método de ajuda à classe HomeController:

    private bool HasMatchingMetadata(CloudBlockBlob blob, string term)
    {
        foreach (var item in blob.Metadata)
        {
            if (item.Key.StartsWith("Tag") && item.Value.Equals(term, StringComparison.InvariantCultureIgnoreCase))
                return true;
        }
    
        return false;
    }
    

    Esse método é chamado pelo método índice para determinar se as palavras-chave de metadados anexadas a um determinado blob de imagem contêm o termo de pesquisa inserido pelo usuário.

  5. Inicie o aplicativo novamente e carregue diversas fotos. Sinta-se à vontade para usar suas próprias fotos, não somente aquelas fornecidas com o tutorial.

  6. Digite uma palavra-chave como "rio" na caixa de pesquisa. Em seguida, selecione o botão Pesquisar.

    Performing a search

  7. Os resultados da pesquisa variam de acordo com o conteúdo digitado e as imagens carregadas. No entanto, o resultado deve ser uma lista filtrada de imagens cujas palavras-chave de metadados incluam toda ou parte da palavra-chave digitada.

    Search results

  8. Selecione o botão Voltar do navegador para exibir todas as imagens novamente.

Você está quase terminando. É hora de implantar o aplicativo na nuvem.

Implantar o aplicativo no Azure

Nesta seção, você implantará o aplicativo no Azure com o Visual Studio. Você permitirá que o Visual Studio crie um aplicativo Web do Azure para você, o que evita que você precise entrar no portal do Azure para criá-lo separadamente.

  1. Clique com o botão direito no projeto no Gerenciador de Soluções e selecione Publicar... no menu de contexto. Verifique se Serviço de Aplicativo do Microsoft Azure e Criar Novo estão selecionados e, em seguida, selecione o botão Publicar.

    Publishing the app

  2. Na caixa de diálogo a seguir, selecione o grupo de recursos "IntellipixResources" em Grupo de recursos. Selecione o botão Novo... ao lado de "Plano de Serviço de Aplicativo" e crie um novo plano do Serviço de Aplicativo no mesmo local que você selecionou para a conta de armazenamento em Criar uma conta de armazenamento, aceitando os padrões em todos os outros locais. Conclua selecionando o botão Criar.

    Creating an Azure Web App

  3. Após alguns instantes, o aplicativo será exibido em uma janela do navegador. Anote a URL na barra de endereços. O aplicativo não está mais sendo executado localmente; ele está na Web, onde pode ser acessado publicamente.

    The finished product!

Se você alterar o aplicativo, para enviar as alterações por push para a Web, passe novamente pelo processo de publicação. Ainda é possível testar suas alterações localmente antes de publicar na Web.

Limpar os recursos

Caso deseje continuar trabalhando em seu aplicativo Web, confira a seção Próximas etapas. Se você não pretende continuar usando esse aplicativo, exclua todos os recursos específicos do aplicativo. Para excluir recursos, você pode excluir o grupo de recursos que contém sua assinatura do Azure Storage e o recurso de Vision. Isso removerá a conta de armazenamento, os blobs carregados nela e o recurso do Serviço de Aplicativo necessário para se conectar ao aplicativo Web ASP.NET.

Para excluir o grupo de recursos, abra a guia Grupos de recursos no portal, navegue até o grupo de recursos usado para esse projeto e selecione Excluir grupo de recursos na parte superior da exibição. Será necessário digitar o nome do grupo de recursos para confirmar a exclusão. Depois de excluído, um grupo de recursos não pode ser recuperado.

Próximas etapas

Há muito mais a ser feito para usar o Azure e aprimorar ainda mais seu aplicativo Intellipix. Por exemplo, você pode adicionar suporte para autenticar usuários e excluir fotos e, em vez de forçar o usuário a esperar que os serviços de IA do Azure processem uma foto após um upload, você pode usar o Azure Functions para chamar a API da Visão de IA do Azure de forma assíncrona sempre que uma imagem for adicionada ao armazenamento de blobs. Você também pode fazer diversas outras operações de análise na imagem, descritas na visão geral.