Implemente uma solução de estatísticas de visão de ML com o Dataflow e a Cloud Vision API

Last reviewed 2024-05-16 UTC

Este documento de implementação descreve como implementar um pipeline do Dataflow para processar ficheiros de imagem em grande escala com a Cloud Vision API. Este pipeline armazena os resultados dos ficheiros processados no BigQuery. Pode usar os ficheiros para fins de análise ou para formar modelos do BigQuery ML.

O pipeline do Dataflow que criar nesta implementação pode processar milhões de imagens por dia. O único limite é a sua quota da API Vision. Pode aumentar a quota da API Vision com base nos seus requisitos de escala.

Estas instruções destinam-se a engenheiros de dados e cientistas de dados. Este documento pressupõe que tem conhecimentos básicos sobre a criação de pipelines do Dataflow com o SDK Java do Apache Beam, o GoogleSQL para BigQuery e scripts de shell básicos. Também pressupõe que tem familiaridade com a Vision API.

Arquitetura

O diagrama seguinte ilustra o fluxo do sistema para criar uma solução de estatísticas de visão de ML.

Uma arquitetura que mostra o fluxo de informações para os processos de carregamento e acionamento, processamento, armazenamento e análise.

No diagrama anterior, as informações fluem através da arquitetura da seguinte forma:

  1. Um cliente carrega ficheiros de imagem para um contentor do Cloud Storage.
  2. O Cloud Storage envia uma mensagem sobre o carregamento de dados para o Pub/Sub.
  3. O Pub/Sub notifica o Dataflow acerca do carregamento.
  4. O pipeline do Dataflow envia as imagens para a Vision API.
  5. A API Vision processa as imagens e, em seguida, devolve as anotações.
  6. O pipeline envia os ficheiros anotados para o BigQuery para que os possa analisar.

Objetivos

  • Crie um pipeline do Apache Beam para a análise de imagens carregadas no Cloud Storage.
  • Use o Dataflow Runner v2 para executar o pipeline do Apache Beam num modo de streaming para analisar as imagens assim que forem carregadas.
  • Use a Vision API para analisar imagens para um conjunto de tipos de funcionalidades.
  • Analise as anotações com o BigQuery.

Custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Quando terminar de criar a aplicação de exemplo, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  5. Verify that billing is enabled for your Google Cloud project.

  6. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  7. Clone o repositório do GitHub que contém o código fonte do pipeline do Dataflow:
        git clone
        https://github.com/GoogleCloudPlatform/dataflow-vision-analytics.git
        
  8. Aceda à pasta de raiz do repositório:
        cd dataflow-vision-analytics
        
  9. Siga as instruções na secção Introdução do repositório dataflow-vision-analytics no GitHub para realizar as seguintes tarefas:
    • Ative várias APIs.
    • Crie um contentor do Cloud Storage.
    • Crie um tópico e uma subscrição do Pub/Sub.
    • Crie um conjunto de dados do BigQuery.
    • Configurar várias variáveis de ambiente para esta implementação.
  10. Executar o pipeline do Dataflow para todas as funcionalidades da API Vision implementadas

    O pipeline do Dataflow pede e processa um conjunto específico de funcionalidades e atributos da API Vision nos ficheiros anotados.

    Os parâmetros indicados na tabela seguinte são específicos do pipeline do Dataflow nesta implementação. Para ver a lista completa de parâmetros de execução do Dataflow padrão, consulte o artigo Defina opções de pipeline do Dataflow.

    Nome do parâmetro Descrição

    batchSize

    O número de imagens a incluir num pedido à API Vision. A predefinição é 1. Pode aumentar este valor até um máximo de 16.

    datasetName

    O nome do conjunto de dados do BigQuery de saída.

    features

    Uma lista de funcionalidades de processamento de imagens. O pipeline suporta as funcionalidades de etiqueta, ponto de referência, logótipo, rosto, sugestão de recorte e propriedades da imagem.

    keyRange

    O parâmetro que define o número máximo de chamadas paralelas para a API Vision. A predefinição é 1.

    labelAnnottationTable,
    landmarkAnnotationTable,
    logoAnnotationTable,
    faceAnnotationTable,
    imagePropertiesTable,
    cropHintAnnotationTable,
    errorLogTable

    Parâmetros de string com nomes de tabelas para várias anotações. Os valores predefinidos são fornecidos para cada tabela. Por exemplo, label_annotation.

    maxBatchCompletionDurationInSecs

    O tempo de espera antes de processar imagens quando existe um lote de imagens incompleto. A predefinição são 30 segundos.

    subscriberId

    O ID da subscrição do Pub/Sub que recebe notificações do Cloud Storage de entrada.

    visionApiProjectId

    O ID do projeto a usar para a API Vision.
    1. No Cloud Shell, execute o seguinte comando para processar imagens para todos os tipos de funcionalidades suportados pelo pipeline do Dataflow:

      ./gradlew run --args=" \
      --jobName=test-vision-analytics \
        --streaming \
        --runner=DataflowRunner \
        --enableStreamingEngine \
        --diskSizeGb=30 \
        --project=${PROJECT} \
        --datasetName=${BIGQUERY_DATASET} \
        --subscriberId=projects/${PROJECT}/subscriptions/${GCS_NOTIFICATION_SUBSCRIPTION} \
        --visionApiProjectId=${PROJECT} \
        --features=IMAGE_PROPERTIES,LABEL_DETECTION,LANDMARK_DETECTION,LOGO_DETECTION,CROP_HINTS,FACE_DETECTION"
      

      A conta de serviço dedicada tem de ter acesso de leitura ao contentor que contém as imagens. Por outras palavras, essa conta tem de ter a função roles/storage.objectViewer concedida nesse contentor.

      Para mais informações sobre a utilização de uma conta de serviço dedicada, consulte o artigo Segurança e autorizações do Dataflow.

    2. Abra o URL apresentado num novo separador do navegador ou aceda à página Dataflow Jobs e selecione o pipeline test-vision-analytics.

      Após alguns segundos, é apresentado o gráfico da tarefa do Dataflow:

      Diagrama do fluxo de trabalho para a tarefa do Dataflow.

      O pipeline do Dataflow está agora em execução e a aguardar a receção de notificações de entrada da subscrição do Pub/Sub.

    3. Acione o processamento de imagens do Dataflow carregando os seis ficheiros de exemplo para o contentor de entrada:

      gcloud storage cp data-sample/* gs://${IMAGE_BUCKET}
      
    4. Na Google Cloud consola, localize o painel Contadores personalizados e use-o para rever os contadores personalizados no Dataflow e verificar se o Dataflow processou todas as seis imagens. Pode usar a funcionalidade de filtro do painel para navegar para as métricas corretas. Para apenas apresentar os contadores que começam com o prefixo numberOf, escreva numberOf no filtro.

      Lista de contadores filtrada para mostrar apenas os contadores que começam por "numberof".

    5. No Cloud Shell, valide se as tabelas foram criadas automaticamente:

      bq query --nouse_legacy_sql "SELECT table_name FROM ${BIGQUERY_DATASET}.INFORMATION_SCHEMA.TABLES ORDER BY table_name"
      

      O resultado é o seguinte:

      +----------------------+
      |      table_name      |
      +----------------------+
      | crop_hint_annotation |
      | face_annotation      |
      | image_properties     |
      | label_annotation     |
      | landmark_annotation  |
      | logo_annotation      |
      +----------------------+
      
    6. Veja o esquema da tabela landmark_annotation. A funcionalidade LANDMARK_DETECTIONcapturaos atributos devolvidos pela chamada API.

      bq show --schema --format=prettyjson ${BIGQUERY_DATASET}.landmark_annotation
      

      O resultado é o seguinte:

      [
         {
            "name":"gcs_uri",
            "type":"STRING"
         },
         {
            "name":"feature_type",
            "type":"STRING"
         },
         {
            "name":"transaction_timestamp",
            "type":"STRING"
         },
         {
            "name":"mid",
            "type":"STRING"
         },
         {
            "name":"description",
            "type":"STRING"
         },
         {
            "name":"score",
            "type":"FLOAT"
         },
         {
            "fields":[
               {
                  "fields":[
                     {
                        "name":"x",
                        "type":"INTEGER"
                     },
                     {
                    "name":"y",
                    "type":"INTEGER"
                 }
              ],
              "mode":"REPEATED",
              "name":"vertices",
              "type":"RECORD"
           }
        ],
        "name":"boundingPoly",
        "type":"RECORD"
      },
      {
        "fields":[
           {
              "fields":[
                 {
                    "name":"latitude",
                    "type":"FLOAT"
                 },
                 {
                    "name":"longitude",
                    "type":"FLOAT"
                 }
              ],
                  "name":"latLon",
                  "type":"RECORD"
                }
              ],
            "mode":"REPEATED",
            "name":"locations",
            "type":"RECORD"
         }
      ]
      
    7. Veja os dados de anotação produzidos pela API executando os seguintes comandos bq query para ver todos os pontos de referência encontrados nestas seis imagens, ordenados pela pontuação mais provável:

      bq query --nouse_legacy_sql "SELECT SPLIT(gcs_uri, '/')[OFFSET(3)] file_name, description, score, locations FROM ${BIGQUERY_DATASET}.landmark_annotation ORDER BY score DESC"
      

      O resultado é semelhante ao seguinte:

      +------------------+-------------------+------------+---------------------------------+
      |    file_name     |    description    |   score    |            locations            |
      +------------------+-------------------+------------+---------------------------------+
      | eiffel_tower.jpg | Eiffel Tower      |  0.7251996 | ["POINT(2.2944813 48.8583701)"] |
      | eiffel_tower.jpg | Trocadéro Gardens | 0.69601923 | ["POINT(2.2892823 48.8615963)"] |
      | eiffel_tower.jpg | Champ De Mars     |  0.6800974 | ["POINT(2.2986304 48.8556475)"] |
      +------------------+-------------------+------------+---------------------------------+
      

      Para ver descrições detalhadas de todas as colunas específicas das anotações, consulte AnnotateImageResponse.

    8. Para parar o pipeline de streaming, execute o seguinte comando. O pipeline continua a ser executado, mesmo que não existam mais notificações do Pub/Sub para processar.

        gcloud dataflow jobs cancel
          --region ${REGION} $(gcloud dataflow jobs list
          --region ${REGION} --filter="NAME:test-vision-analytics AND STATE:Running"
          --format="get(JOB_ID)")
      

      A secção seguinte contém mais consultas de exemplo que analisam diferentes características de imagem das imagens.

    Analisar um conjunto de dados Flickr30K

    Nesta secção, deteta etiquetas e pontos de referência no conjunto de dados de imagens Flickr30k público alojado no Kaggle.

    1. No Cloud Shell, altere os parâmetros do pipeline do Dataflow para que seja otimizado para um conjunto de dados grande. Para permitir um débito mais elevado, também deve aumentar os valores batchSize e keyRange. O Dataflow dimensiona o número de trabalhadores conforme necessário:

      ./gradlew run --args=" \
        --runner=DataflowRunner \
        --jobName=vision-analytics-flickr \
        --streaming \
        --enableStreamingEngine \
        --diskSizeGb=30 \
        --autoscalingAlgorithm=THROUGHPUT_BASED \
        --maxNumWorkers=5 \
        --project=${PROJECT} \
        --region=${REGION} \
        --subscriberId=projects/${PROJECT}/subscriptions/${GCS_NOTIFICATION_SUBSCRIPTION} \
        --visionApiProjectId=${PROJECT} \
        --features=LABEL_DETECTION,LANDMARK_DETECTION \
        --datasetName=${BIGQUERY_DATASET} \
        --batchSize=16 \
        --keyRange=5"
      

      Como o conjunto de dados é grande, não pode usar o Cloud Shell para obter as imagens do Kaggle e enviá-las para o contentor do Cloud Storage. Tem de usar uma VM com um tamanho do disco maior para o fazer.

    2. Para obter imagens baseadas no Kaggle e enviá-las para o contentor do Cloud Storage, siga as instruções na secção Simule o carregamento das imagens para o contentor de armazenamento no repositório do GitHub.

    3. Para observar o progresso do processo de cópia através das métricas personalizadas disponíveis na IU do Dataflow, navegue para a página Tarefas do Dataflow e selecione o pipeline vision-analytics-flickr. Os contadores de clientes devem mudar periodicamente até que o pipeline do Dataflow processe todos os ficheiros.

      A saída é semelhante à seguinte captura de ecrã do painel Contadores personalizados. Um dos ficheiros no conjunto de dados é do tipo errado e o contador rejectedFiles reflete isso. Estes valores do contador são aproximados. Pode ver números mais elevados. Além disso, o número de anotações vai provavelmente mudar devido à maior precisão do processamento pela API Vision.

      Lista de contadores associados ao processamento das imagens baseadas no Kaggle.

      Para determinar se está a aproximar-se ou a exceder os recursos disponíveis, consulte a página de quotas da API Vision.

      No nosso exemplo, o pipeline do Dataflow usou apenas cerca de 50% da respetiva quota. Com base na percentagem da quota que usa, pode decidir aumentar o paralelismo do pipeline aumentando o valor do parâmetro keyRange.

    4. Encerre o pipeline:

      gcloud dataflow jobs list --region $REGION --filter="NAME:vision-analytics-flickr AND STATE:Running" --format="get(JOB_ID)"
      

    Analise anotações no BigQuery

    Nesta implementação, processou mais de 30 000 imagens para anotação de etiquetas e pontos de referência. Nesta secção, recolhe estatísticas sobre esses ficheiros. Pode executar estas consultas no espaço de trabalho do GoogleSQL para o BigQuery ou usar a ferramenta de linha de comandos bq.

    Tenha em atenção que os números que vê podem variar em relação aos resultados da consulta de exemplo nesta implementação. A API Vision melhora constantemente a precisão da respetiva análise. Pode produzir resultados mais detalhados analisando a mesma imagem depois de testar inicialmente a solução.

    1. Na Google Cloud consola, aceda à página do BigQuery Editor de consultas e execute o seguinte comando para ver as 20 principais etiquetas no conjunto de dados:

      Aceder ao editor de consultas

      SELECT  description, count(*)ascount \
        FROM vision_analytics.label_annotation
        GROUP BY description ORDER BY count DESC LIMIT 20
      

      O resultado é semelhante ao seguinte:

      +------------------+-------+
      |   description    | count |
      +------------------+-------+
      | Leisure          |  7663 |
      | Plant            |  6858 |
      | Event            |  6044 |
      | Sky              |  6016 |
      | Tree             |  5610 |
      | Fun              |  5008 |
      | Grass            |  4279 |
      | Recreation       |  4176 |
      | Shorts           |  3765 |
      | Happy            |  3494 |
      | Wheel            |  3372 |
      | Tire             |  3371 |
      | Water            |  3344 |
      | Vehicle          |  3068 |
      | People in nature |  2962 |
      | Gesture          |  2909 |
      | Sports equipment |  2861 |
      | Building         |  2824 |
      | T-shirt          |  2728 |
      | Wood             |  2606 |
      +------------------+-------+
      
    2. Determine que outras etiquetas estão presentes numa imagem com uma etiqueta específica, classificadas por frequência:

      DECLARE label STRING DEFAULT 'Plucked string instruments';
      
      WITH other_labels AS (
         SELECT description, COUNT(*) count
      FROM vision_analytics.label_annotation
      WHERE gcs_uri IN (
          SELECT gcs_uri FROM vision_analytics.label_annotation WHERE description = label )
        AND description != label
      GROUP BY description)
      SELECT description, count, RANK() OVER (ORDER BY count DESC) rank
      FROM other_labels ORDER BY rank LIMIT 20;
      

      O resultado é o seguinte. Para a etiqueta Instrumentos de cordas dedilhadas usada no comando anterior, deve ver:

      +------------------------------+-------+------+
      |         description          | count | rank |
      +------------------------------+-------+------+
      | String instrument            |   397 |    1 |
      | Musical instrument           |   236 |    2 |
      | Musician                     |   207 |    3 |
      | Guitar                       |   168 |    4 |
      | Guitar accessory             |   135 |    5 |
      | String instrument accessory  |    99 |    6 |
      | Music                        |    88 |    7 |
      | Musical instrument accessory |    72 |    8 |
      | Guitarist                    |    72 |    8 |
      | Microphone                   |    52 |   10 |
      | Folk instrument              |    44 |   11 |
      | Violin family                |    28 |   12 |
      | Hat                          |    23 |   13 |
      | Entertainment                |    22 |   14 |
      | Band plays                   |    21 |   15 |
      | Jeans                        |    17 |   16 |
      | Plant                        |    16 |   17 |
      | Public address system        |    16 |   17 |
      | Artist                       |    16 |   17 |
      | Leisure                      |    14 |   20 |
      +------------------------------+-------+------+
      
    3. Veja os 10 principais pontos de referência detetados:

        SELECT description, COUNT(description) AS count
        FROM vision_analytics.landmark_annotation
        GROUP BY description ORDER BY count DESC LIMIT 10
      

      O resultado é o seguinte:

        +--------------------+-------+
        |    description     | count |
        +--------------------+-------+
        | Times Square       |    55 |
        | Rockefeller Center |    21 |
        | St. Mark's Square  |    16 |
        | Bryant Park        |    13 |
        | Millennium Park    |    13 |
        | Ponte Vecchio      |    13 |
        | Tuileries Garden   |    13 |
        | Central Park       |    12 |
        | Starbucks          |    12 |
        | National Mall      |    11 |
        +--------------------+-------+
        

    4. Determine as imagens que contêm mais provavelmente cataratas:

      SELECT SPLIT(gcs_uri, '/')[OFFSET(3)] file_name, description, score
      FROM vision_analytics.landmark_annotation
      WHERE LOWER(description) LIKE '%fall%'
      ORDER BY score DESC LIMIT 10
      

      O resultado é o seguinte:

      +----------------+----------------------------+-----------+
      |   file_name    |        description         |   score    |
      +----------------+----------------------------+-----------+
      | 895502702.jpg  | Waterfall Carispaccha      |  0.6181358 |
      | 3639105305.jpg | Sahalie Falls Viewpoint    | 0.44379658 |
      | 3672309620.jpg | Gullfoss Falls             | 0.41680416 |
      | 2452686995.jpg | Wahclella Falls            | 0.39005348 |
      | 2452686995.jpg | Wahclella Falls            |  0.3792498 |
      | 3484649669.jpg | Kodiveri Waterfalls        | 0.35024035 |
      | 539801139.jpg  | Mallela Thirtham Waterfall | 0.29260656 |
      | 3639105305.jpg | Sahalie Falls              |  0.2807213 |
      | 3050114829.jpg | Kawasan Falls              | 0.27511594 |
      | 4707103760.jpg | Niagara Falls              | 0.18691841 |
      +----------------+----------------------------+-----------+
      
    5. Encontrar imagens de pontos de referência a 3 quilómetros do Coliseu em Roma (a função ST_GEOPOINT usa a longitude e a latitude do Coliseu):

      WITH
        landmarksWithDistances AS (
        SELECT
          gcs_uri,
          description,
          location,
          ST_DISTANCE(location,
            ST_GEOGPOINT(12.492231,
              41.890222)) distance_in_meters,
        FROM
          `vision_analytics.landmark_annotation` landmarks
        CROSS JOIN
          UNNEST(landmarks.locations) AS location )
      SELECT
        SPLIT(gcs_uri,"/")[OFFSET(3)] file,
        description,
          ROUND(distance_in_meters) distance_in_meters,
        location,
        CONCAT("https://storage.cloud.google.com/", SUBSTR(gcs_uri, 6)) AS image_url
      FROM
        landmarksWithDistances
      WHERE
        distance_in_meters < 3000
      ORDER BY
        distance_in_meters
      LIMIT
        100
      

      Quando executar a consulta, vai ver que existem várias imagens do Coliseu, mas também imagens do Arco de Constantino, do Palatino e de vários outros locais frequentemente fotografados.

      Pode visualizar os dados no BigQuery Geo Viz colando a consulta anterior. Selecione um ponto no mapa para ver os respetivos detalhes. O atributo Image_url contém um link para o ficheiro de imagem.

      Mapa das localizações e respetiva distância do Coliseu.

    Uma nota sobre os resultados da consulta. Normalmente, as informações de localização estão presentes para pontos de referência. A mesma imagem pode conter várias localizações do mesmo ponto de referência. Esta funcionalidade está descrita no tipo AnnotateImageResponse.

    Uma vez que uma localização pode indicar a localização da cena na imagem, podem estar presentes LocationInfo vários elementos. Outra localização pode indicar onde a imagem foi capturada.

    Limpar

    Para evitar incorrer em custos na sua Google Cloud conta pelos recursos usados neste guia, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

    Elimine o Google Cloud projeto

    A forma mais fácil de eliminar a faturação é eliminar o Google Cloud projeto que criou para o tutorial.

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Se decidir eliminar recursos individualmente, siga os passos na secção Limpar do repositório do GitHub.

    O que se segue?

    Colaboradores

    Autores:

    Outros colaboradores: