Déployer une solution d'analyse ML Vision avec Dataflow et l'API Cloud Vision

Last reviewed 2024-05-16 UTC

Ce document de déploiement explique comment déployer un pipeline Dataflow pour traiter des fichiers image à grande échelle avec l'API Cloud Vision. Ce pipeline stocke les résultats des fichiers traités dans BigQuery. Vous pouvez utiliser les fichiers à des fins d'analyse ou pour entraîner des modèles BigQuery ML.

Le pipeline Dataflow que vous créez dans ce déploiement peut traiter des millions d'images par jour. Votre quota d'API Vision est la seule limite. Vous pouvez augmenter votre quota d'API Vision en fonction de vos exigences d'évolutivité.

Ces instructions sont destinées aux ingénieurs de données et aux data scientists. Dans ce document, nous partons du principe que vous possédez des connaissances de base sur la création de pipelines Dataflow à l'aide du SDK Java d'Apache Beam, de GoogleSQL pour BigQuery et de scripts shell de base. Nous supposons également que vous connaissez l'API Vision.

Architecture

Le schéma suivant illustre le flux système pour la création d'une solution d'analyse de la vision basée sur le ML.

Architecture montrant le flux d'informations pour l'ingestion, le déclenchement, le traitement, le stockage et l'analyse des processus.

Dans le schéma précédent, les informations circulent dans l'architecture comme suit :

  1. Un client importe des fichiers image dans un bucket Cloud Storage.
  2. Cloud Storage envoie un message concernant l'importation de données à Pub/Sub.
  3. Pub/Sub informe Dataflow de l'importation.
  4. Le pipeline Dataflow envoie les images à l'API Vision.
  5. L'API Vision traite les images, puis renvoie les annotations.
  6. Le pipeline envoie les fichiers annotés à BigQuery pour que vous puissiez les analyser.

Objectifs

  • Créer un pipeline Apache Beam pour l'analyse d'images chargées dans Cloud Storage.
  • Utiliser l'exécuteur Dataflow v2 pour exécuter le pipeline Apache Beam en mode de streaming afin d'analyser les images dès qu' elles sont importées.
  • Utiliser l'API Vision pour analyser des images pour un ensemble de types de fonctionnalités.
  • Analyser les annotations avec BigQuery.

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud:

Obtenez une estimation des coûts en fonction de votre utilisation prévue, utilisez le simulateur de coût.

Les nouveaux utilisateurs de peuvent bénéficier d'un essai sans frais. Google Cloud

Une fois que vous avez fini de créer l'exemple d'application, vous pouvez éviter de continuer à payer des frais en supprimant les ressources créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Connectez-vous à votre Google Cloud compte. Si vous n'avez jamais utilisé Google Cloud, créez un compte pour évaluer les performances de nos produits dans des scénarios réels. Les nouveaux clients bénéficient également de 300 $de crédits sans frais pour exécuter, tester et déployer des charges de travail.
  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 role (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 role (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. Dans la Google Cloud console, activez Cloud Shell.

    Activer Cloud Shell

    En bas de la fenêtre de la console, une session Cloud Shell démarre et affiche une invite de ligne de commande. Google Cloud Cloud Shell est un environnement shell dans lequel Google Cloud CLI est déjà installé, et dans lequel des valeurs sont déjà définies pour votre projet actuel. L'initialisation de la session peut prendre quelques secondes.

  7. Clonez le dépôt GitHub qui contient le code source du pipeline Dataflow :
        git clone
        https://github.com/GoogleCloudPlatform/dataflow-vision-analytics.git
        
  8. Accédez au dossier racine du dépôt :
        cd dataflow-vision-analytics
        
  9. Suivez les instructions de la section Premiers pas du dépôt dataflow-vision-analytics dans GitHub pour effectuer les tâches suivantes :
    • Activer plusieurs API.
    • Créer un bucket Cloud Storage.
    • Créer un sujet et un abonnement Pub/Sub.
    • Créer un ensemble de données BigQuery.
    • Configurer plusieurs variables d'environnement pour ce déploiement.

Exécuter le pipeline Dataflow pour toutes les fonctionnalités implémentées de l'API Vision

Le pipeline Dataflow demande et traite un ensemble spécifique de fonctionnalités et d'attributs de l'API Vision dans les fichiers annotés.

Les paramètres répertoriés dans le tableau suivant sont spécifiques au pipeline Dataflow de ce déploiement. Pour obtenir la liste complète des paramètres d'exécution Dataflow standards, consultez Définir les options de pipeline Dataflow.

Nom du paramètre Description

batchSize

Nombre d'images à inclure dans une requête adressée à l'API Vision. La valeur par défaut est 1. Vous pouvez augmenter cette valeur jusqu'à un maximum de 16.

datasetName

Nom de l'ensemble de données BigQuery de sortie.

features

Liste des fonctionnalités de traitement d'image features. Le pipeline est compatible avec les fonctionnalités de libellé, de point de repère, de logo, de visage, de suggestion de recadrage et de propriétés d'image.

keyRange

Paramètre qui définit le nombre maximal d'appels parallèles à l'API Vision. La valeur par défaut est 1.

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

Paramètres de chaîne avec des noms de table pour diverses annotations. Les valeurs par défaut sont fournies pour chaque table (par exemple, label_annotation).

maxBatchCompletionDurationInSecs

Durée d'attente avant le traitement des images lorsqu'un lot d'images est incomplet. La valeur par défaut est de 30 secondes.

subscriberId

ID de l'abonnement Pub/Sub qui reçoit les notifications Cloud Storage d'entrée.

visionApiProjectId

ID de projet à utiliser pour l'API Vision.
  1. Dans Cloud Shell, exécutez la commande suivante pour traiter les images pour tous les types de fonctionnalités compatibles avec le pipeline 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"
    

    Le compte de service dédié doit disposer d'un accès en lecture au bucket contenant les images. En d'autres termes, ce compte doit disposer du rôle roles/storage.objectViewer sur ce bucket.

    Pour en savoir plus sur l'utilisation d'un compte de service dédié, consultez Sécurité et autorisations pour Dataflow.

  2. Ouvrez l'URL affichée dans un nouvel onglet de navigateur ou accédez à la page Tâches Dataflow et sélectionnez le pipeline test-vision-analytics.

    Après quelques secondes, le graphique de la tâche Dataflow s'affiche :

    Schéma du workflow pour la tâche Dataflow.

    Le pipeline Dataflow est maintenant en cours d'exécution et attend de recevoir des notifications d'entrée de l'abonnement Pub/Sub.

  3. Déclenchez le traitement des images Dataflow en important les six exemples de fichiers dans le bucket d'entrée :

    gcloud storage cp data-sample/* gs://${IMAGE_BUCKET}
    
  4. Dans la Google Cloud console, recherchez le panneau "Custom Counters" (Compteurs personnalisés), puis utilisez le pour examiner les compteurs personnalisés dans Dataflow et vérifier que Dataflow a traité les six images. Vous pouvez utiliser la fonctionnalité de filtre du panneau pour accéder aux métriques appropriées. Pour n'afficher que les compteurs commençant par le préfixe numberOf, saisissez numberOf dans le filtre.

    Liste des compteurs filtrée pour n'afficher que ceux qui commencent par "numberof".

  5. Dans Cloud Shell, vérifiez que les tables ont été créées automatiquement :

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

    Voici le résultat :

    +----------------------+
    |      table_name      |
    +----------------------+
    | crop_hint_annotation |
    | face_annotation      |
    | image_properties     |
    | label_annotation     |
    | landmark_annotation  |
    | logo_annotation      |
    +----------------------+
    
  6. Affichez le schéma de la table landmark_annotation. La fonctionnalité LANDMARK_DETECTION capture les attributs renvoyés par l'appel d'API.

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

    Voici le résultat :

    [
       {
          "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. Affichez les données d'annotation générées par l'API en exécutant les commandes bq query suivantes pour afficher tous les points de repère trouvés dans ces six images, classés par score de probabilité :

    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"
    

    Le résultat ressemble à ce qui suit :

    +------------------+-------------------+------------+---------------------------------+
    |    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)"] |
    +------------------+-------------------+------------+---------------------------------+
    

    Pour obtenir des descriptions détaillées de toutes les colonnes spécifiques aux annotations, consultez AnnotateImageResponse.

  8. Pour arrêter le pipeline de streaming, exécutez la commande suivante. Le pipeline continue de s'exécuter même s'il n'y a plus de notifications Pub/Sub à traiter.

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

    La section suivante contient d'autres exemples de requêtes qui analysent différentes caractéristiques d'image.

Analyser un ensemble de données Flickr30K

Dans cette section, vous allez détecter des libellés et des points de repère dans l'ensemble de données d'images public Flickr30k hébergé sur Kaggle.

  1. Dans Cloud Shell, modifiez les paramètres du pipeline Dataflow afin qu'ils soient optimisés pour un grand ensemble de données. Pour permettre un débit plus élevé, augmentez également les valeurs batchSize et keyRange. Dataflow adapte le nombre de nœuds de calcul en fonction des besoins :

    ./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"
    

    Étant donné que l'ensemble de données est volumineux, vous ne pouvez pas utiliser Cloud Shell pour récupérer les images de Kaggle et les envoyer au bucket Cloud Storage. Pour ce faire, vous devez utiliser une VM avec une taille de disque plus importante.

  2. Pour récupérer des images basées sur Kaggle et les envoyer au bucket Cloud Storage, suivez les instructions de la section Simuler l'importation des images dans le bucket de stockage du dépôt GitHub.

  3. Pour observer la progression du processus de copie en examinant les métriques personnalisées disponibles dans l'interface utilisateur Dataflow, accédez à la page Tâches Dataflow et sélectionnez le pipeline vision-analytics-flickr. Les compteurs clients doivent changer périodiquement jusqu'à ce que le pipeline Dataflow traite tous les fichiers.

    Le résultat ressemble à la capture d'écran suivante du panneau "Custom Counters" (Compteurs personnalisés). L'un des fichiers de l'ensemble de données est du mauvais type, ce qui est indiqué par le compteur rejectedFiles. Ces valeurs de compteur sont approximatives. Vous pouvez voir des nombres plus élevés. De plus, le nombre d'annotations changera très probablement en raison de la précision accrue du traitement par l'API Vision.

    Liste des compteurs associés au traitement des images basées sur Kaggle.

    Pour déterminer si vous approchez ou dépassez les ressources disponibles, consultez la page Quota de l'API Vision.

    Dans notre exemple, le pipeline Dataflow n'a utilisé qu'environ 50 % de son quota. En fonction du pourcentage du quota que vous utilisez, vous pouvez décider d'augmenter le parallélisme du pipeline en augmentant la valeur du paramètre keyRange.

  4. Arrêtez le pipeline :

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

Analyser les annotations dans BigQuery

Dans ce déploiement, vous avez traité plus de 30 000 images pour l'annotation de libellés et de points de repère. Dans cette section, vous allez collecter des statistiques sur ces fichiers. Vous pouvez exécuter ces requêtes dans l'espace de travail GoogleSQL pour BigQuery ou utiliser l'outil de ligne de commande bq.

Sachez que les chiffres que vous voyez peuvent varier par rapport aux résultats de l'exemple de requête dans ce déploiement. L'API Vision améliore constamment la précision de son analyse. Elle peut produire des résultats plus riches en analysant la même image après avoir testé la solution initialement.

  1. Dans la Google Cloud console, accédez à la page BigQuery Éditeur de requête et exécutez la commande suivante pour afficher les 20 principaux libellés de l'ensemble de données :

    Accéder à l'éditeur de requête

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

    Le résultat ressemble à ce qui suit :

    +------------------+-------+
    |   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. Déterminez les autres libellés présents sur une image avec un libellé particulier, classés par fréquence :

    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;
    

    Voici le résultat : Pour le libellé Plucked string instruments (Instruments à cordes pincées) utilisé dans la commande précédente, vous devriez voir :

    +------------------------------+-------+------+
    |         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. Affichez les 10 principaux points de repère détectés :

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

    Voici le résultat :

      +--------------------+-------+
      |    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. Déterminez les images les plus susceptibles de contenir des cascades :

    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
    

    Voici le résultat :

    +----------------+----------------------------+-----------+
    |   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. Recherchez des images de points de repère dans un rayon de 3 kilomètres du Colisée à Rome (la fonction ST_GEOPOINT utilise la longitude et la latitude du Colisée) :

    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
    

    Lorsque vous exécutez la requête, vous voyez qu'il existe plusieurs images du Colisée, mais aussi des images de l'arc de Constantin, du mont Palatin et d'un certain nombre d'autres lieux fréquemment photographiés.

    Vous pouvez visualiser les données dans BigQuery Geo Viz en collant la requête précédente. Sélectionnez un point sur la carte pour afficher ses détails. L'attribut Image_url contient un lien vers le fichier image.

    Carte des lieux et distance depuis le Colisée.

Une remarque sur les résultats de la requête. Des informations concernant la localisation sont généralement disponibles pour les points de repère. La même image peut contenir plusieurs emplacements du même point de repère. Cette fonctionnalité est décrite dans le AnnotateImageResponse type.

Étant donné qu'un emplacement peut indiquer le lieu de la scène dans l'image, plusieurs LocationInfo éléments peuvent être présents. Un autre emplacement peut indiquer le lieu où l'image a été prise.

Effectuer un nettoyage

Pour éviter que les ressources utilisées dans ce guide ne soient facturées sur votre Google Cloud compte, supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

Supprimer le Google Cloud projet

Le moyen le plus simple d'empêcher la facturation est de supprimer le Google Cloud projet que vous avez créé pour ce tutoriel.

  1. Dans la Google Cloud console, accédez à la page Gérer les ressources.

    Accéder à la page "Gérer les ressources"

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez Arrêter pour supprimer le projet.

Si vous décidez de supprimer des ressources individuellement, suivez les étapes de la section Effectuer un nettoyage du dépôt GitHub.

Étape suivante

Contributeurs

Auteurs :

Autres contributeurs :