Tutoriel : Analyser une table d'objets à l'aide d'une fonction distante

Ce tutoriel vous montre comment créer une table d'objets basée sur les images de l'ensemble de données sur les fleurs, créer une fonction distante qui attribue des étiquettes aux images à l'aide de l'API Cloud Vision, puis analyser les images dans la table d'objets à l'aide de la fonction distante.

Autorisations requises

  • Pour créer l'ensemble de données, vous devez disposer de l'autorisation bigquery.datasets.create.
  • Pour créer la ressource de connexion, vous devez disposer des autorisations suivantes :

    • bigquery.connections.create
    • bigquery.connections.get
  • Pour accorder des autorisations au compte de service de la connexion, vous devez disposer de l'autorisation suivante :

    • resourcemanager.projects.setIamPolicy
  • Pour créer la table d'objets, vous devez disposer des autorisations suivantes :

    • bigquery.tables.create
    • bigquery.tables.update
    • bigquery.connections.delegate
  • Pour créer la fonction distante, vous devez disposer des autorisations associées au rôle Développeur Cloud Functions.

  • Pour appeler la fonction distante, vous devez disposer du rôle Demandeur Cloud Run.

  • Pour analyser la table d'objets avec la fonction distante, vous devez disposer de l'autorisation bigquery.tables.getData sur la table d'objets.

Coûts

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

  • BigQuery : vous payez des frais de stockage pour la table d'objets que vous créez dans BigQuery.
  • Cloud Functions : vous payez des frais pour appeler la fonction distante et les ressources de calcul qu'elle utilise, y compris les appels à l'API Cloud Vision.

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Pour en savoir plus sur les tarifs de Cloud Storage, consultez la page Tarifs de Cloud Storage.

Pour plus d'informations sur la tarification de stockage BigQuery, consultez les tarifs de stockage dans la documentation BigQuery.

Pour en savoir plus sur les tarifs de Cloud Functions, consultez la page Tarifs de Cloud Functions.

Pour plus d'informations sur la tarification de l'API Vision, consultez la page Tarifs de Cloud Vision dans la documentation de Vision.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits gratuits pour exécuter, tester et déployer des charges de travail.
  2. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  4. Activer les API BigQuery, BigQuery Connection API, and Cloud Functions.

    Activer les API

  5. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  6. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  7. Activer les API BigQuery, BigQuery Connection API, and Cloud Functions.

    Activer les API

Créer une fonction Cloud Functions

Pour créer une fonction, procédez comme suit :

  1. Accédez à la page Cloud Functions.

    Accéder à Cloud Functions

  2. Cliquez sur Create function (Créer une fonction).

  3. Pour Environnement, sélectionnez 2e génération.

  4. Dans le champ Nom de la fonction, saisissez vision-ai.

  5. Cliquez sur Suivant.

  6. Dans le champ Environnement d'exécution, sélectionnez Python 3.9.

  7. Dans le champ Point d'entrée, saisissez label_detection.

  8. Sélectionnez main.py. Copiez et collez le code suivant :

    Python

    import urllib.request
    
    import flask
    import functions_framework
    from google.cloud import vision
    
    @functions_framework.http
    def label_detection(request: flask.Request) -> flask.Response:
        """BigQuery remote function to label input images.
        Args:
            request: HTTP request from BigQuery
            https://cloud.google.com/bigquery/docs/reference/standard-sql/remote-functions#input_format
        Returns:
            HTTP response to BigQuery
            https://cloud.google.com/bigquery/docs/reference/standard-sql/remote-functions#output_format
        """
        try:
            client = vision.ImageAnnotatorClient()
            calls = request.get_json()["calls"]
            replies = []
            for call in calls:
                content = urllib.request.urlopen(call[0]).read()
                results = client.label_detection({"content": content})
                replies.append(vision.AnnotateImageResponse.to_dict(results))
            return flask.make_response(flask.jsonify({"replies": replies}))
        except Exception as e:
            return flask.make_response(flask.jsonify({"errorMessage": str(e)}), 400)
    
    

  9. Sélectionnez requirements.txt. Copiez et collez le texte suivant :

    Flask==2.2.2
    functions-framework==3.5.0
    google-cloud-vision==3.4.2
    Werkzeug==2.3.7
    

  10. Cliquez sur Déployer.

  11. Une fois le déploiement de la fonction terminé, cliquez sur l'onglet Déclencheur.

  12. Copiez la valeur du champ URL du déclencheur, puis enregistrez-la. Vous aurez besoin de ces informations pour créer la fonction distante.

Créer un ensemble de données

Créez un ensemble de données nommé remote_function_test :

SQL

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans le volet Éditeur, exécutez l'instruction SQL suivante :

    CREATE SCHEMA `PROJECT_ID.remote_function_test`;
    

    en remplaçant PROJECT_ID par l'ID de votre projet :

bq

  1. Dans la console Google Cloud, activez Cloud Shell.

    Activer Cloud Shell

  2. Exécutez la commande bq mk pour créer l'ensemble de données :

      bq mk --dataset --location=us PROJECT_ID:remote_function_test
      

    Remplacez PROJECT_ID par l'ID du projet.

Créer une connexion

Créez une connexion nommée lake-connection :

Console

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Cliquez sur  Ajouter des données, puis sur Source de données externe.

  3. Dans la liste Type de connexion, sélectionnez BigLake et fonctions distantes (ressource Cloud).

  4. Dans le champ ID de connexion, saisissez lake-connection.

  5. Cliquez sur Créer une connexion.

  6. Dans le volet Informations de connexion, copiez la valeur du champ ID du compte de service, puis enregistrez-la quelque part. Vous avez besoin de ces informations pour accorder des autorisations au compte de service de la connexion.

bq

  1. Dans Cloud Shell, exécutez la commande bq mk pour créer la connexion :

    bq mk --connection --location=us --connection_type=CLOUD_RESOURCE \
    lake-connection
    
  2. Exécutez la commande bq show pour récupérer les informations concernant la connexion :

    bq show --connection us.lake-connection
    
  3. Dans la colonne properties, copiez la valeur de la propriété serviceAccountId et enregistrez-la. Vous avez besoin de ces informations pour accorder des autorisations au compte de service de la connexion.

Créer un bucket Cloud Storage

Créez un bucket Cloud Storage pour contenir l'ensemble de données sur les fleurs.

Accorder des autorisations au compte de service de la connexion

Pour accorder des autorisations au compte de service, procédez comme suit :

  1. Accédez à la page IAM et administration.

    Accéder à IAM et administration

  2. Cliquez sur Accorder l'accès.

    La boîte de dialogue Ajouter des comptes principaux s'ouvre.

  3. Dans le champ Nouveaux comptes principaux, saisissez l'ID du compte de service que vous avez copié précédemment.

  4. Dans le champ Sélectionner un rôle, sélectionnez Cloud Run, puis Demandeur Cloud Run.

  5. Cliquez sur Ajouter un autre rôle.

  6. Dans le champ Sélectionner un rôle, sélectionnez Cloud Storage, puis Lecteur des objets Storage.

  7. Cliquez sur Enregistrer.

Importer l'ensemble de données dans Cloud Storage

Récupérez les fichiers de l'ensemble de données et rendez-les disponibles dans Cloud Storage :

  1. Téléchargez l'ensemble de données sur les fleurs sur votre ordinateur local.
  2. Importez l'ensemble de données dans le bucket que vous avez créé précédemment.

Créer une table d'objets

Créez une table d'objets nommée sample_images basée sur l'ensemble de données sur les fleurs que vous avez importé :

SQL

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans le volet Éditeur, exécutez l'instruction SQL suivante :

    CREATE EXTERNAL TABLE remote_function_test.sample_images
    WITH CONNECTION `us.lake-connection`
    OPTIONS(
      object_metadata = 'SIMPLE',
      uris = ['gs://BUCKET_NAME/*']);
    

    Remplacez BUCKET_NAME par le nom du bucket que vous avez créé précédemment.

bq

Dans Cloud Shell, exécutez la commande bq mk pour créer la connexion :

bq mk --table \
--external_table_definition=gs:"//BUCKET_NAME/*@us.lake-connection" \
--object_metadata=SIMPLE \
remote_function_test.sample_images

Remplacez BUCKET_NAME par le nom du bucket que vous avez créé précédemment.

Créer la fonction distante BigQuery

Créez une fonction distante nommée label_detection :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans le volet Éditeur, exécutez l'instruction SQL suivante :

    CREATE OR REPLACE FUNCTION `remote_function_test.label_detection` (signed_url_ STRING) RETURNS JSON
    REMOTE WITH CONNECTION `us.lake-connection`
    OPTIONS(
    endpoint = 'TRIGGER_URL',
    max_batching_rows = 1
    );
    

    Remplacez TRIGGER_URL par l'URL du déclencheur que vous avez enregistrée précédemment. L'URL doit ressembler à ceci : https://vision-ai-1abcd2efgh-uc.a.run.app.

Appeler la fonction distante

Appelez la fonction distante label_detection sur la table d'objets sample_images :

  1. Accédez à la page BigQuery.

    Accéder à BigQuery

  2. Dans le volet Éditeur, exécutez l'instruction SQL suivante :

    SELECT uri, remote_function_test.label_detection(signed_url)
    FROM EXTERNAL_OBJECT_TRANSFORM(
    TABLE remote_function_test.sample_images,
    ["SIGNED_URL"]
    )
    LIMIT 100;
    

    Le résultat doit ressembler à ce qui suit :

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | uri                                                           | f0_                                                                                                            |
    —---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    |  gs://bq_huron_demo/flowers/daisy/100080576_f52e8ee070_n.jpg  |  {"face_annotations":[],"label_annotations":[{"confidence":0.0,"description":"Flower",                         |
    |                                                               |  "locale":"","locations":[],"mid":"/m/0c9ph5","properties":[],"score":0.9785631,"topicality":0.9785631},       |
    |                                                               |  {"confidence":0.0,"description":"Plant","locale":"","locations":[],"mid":"/m/05s2s","properties":[],          |
    |                                                               |  "Score":0.9635679,"topicality":0.9635679},{"confidence":0.0,"description":"camomile","locale":"",             |
    |                                                               |  "locations":[],"mid":"/m/011bc8hg","properties":[],"score":0.9110366,"topicality":0.9110366},                 |
    |                                                               |  {"confidence":0.0,"description":"Petal","locale":"","locations":[],"mid":"/m/016q19","properties":[],         |
    |                                                               |  "score":0.8927441,"topicality":0.8927441},{"confidence":0.0,"description":"Chamaemelum nobile","locale":"",   |
    |                                                               |  "locations":[],"mid":"/m/05cmcg","properties":[],"score":0.8460995,"topicality":0.8460995},                   |
    |                                                               |   {"confidence":0.0,"description":"Flowering plant","locale":"","locations":[],"mid":"/m/04sjm",               |
    |                                                               |  "properties":[],"score":0.7642974,"topicality":0.7642974},{"confidence":0.0,"description":"Annual plant",     |
    |                                                               |  "locale":"","locations":[],"mid":"/m/0jqb","properties":[],"score":0.7478164,                                 |
    |                                                               |  "topicality":0.7478164},{"confidence":0.0,"description":"Close-up","locale":"","locations":[],                |
    |                                                               |  "mid":"/m/02cqfm","properties":[],"score":0.7207553,"topicality":0.7207553},{"confidence":0.0,                |
    |                                                               |  "description":"Oxeye daisy","locale":"","locations":[],"mid":"/m/02qvnf","properties":[],                     |
    |                                                               |  "score":0.71786934,"topicality":0.71786934},{"confidence":0.0,"description":"Daisy family","locale":"",       |
    |                                                               |  "locations":[],"mid":"/m/0l5r","properties":[],"score":0.7164383,"topicality":0.7164383}],                    |
    |                                                               |  "landmark_annotations":[],"localized_object_annotations":[],"logo_annotations":[],"text_annotations":[]}      |
    —---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | gs://bq_huron_demo/flowers/daisy/10140303196_b88d3d6cec.jpg   |  {"face_annotations":[],"label_annotations":[{"confidence":0.0,"description":"Flower","locale":"",             |
    |                                                               |  "locations":[],"mid":"/m/0c9ph5","properties":[],"score":0.9770426,"topicality":0.9770426},                   |
    |                                                               |  {"confidence":0.0,"description":"Plant","locale":"","locations":[],"mid":"/m/05s2s",                          |
    |                                                               |  "Properties":[],"score":0.95798975,"topicality":0.95798975},{"confidence":0.0,                                |
    |                                                               |  "description":"Petal","locale":"","locations":[],"mid":"/m/016q19","properties":[],                           |
    |                                                               |  "score":0.88984144,"topicality":0.88984144},{"confidence":0.0,"description":"Yellow",                         |
    |                                                               |  "locale":"","locations":[],"mid":"/m/088fh","properties":[],"score":0.84456813,                               |
    |                                                               |  "Topicality":0.84456813},{"confidence":0.0,"description":"camomile","locale":"",                              |
    |                                                               |  "locations":[],"mid":"/m/011bc8hg","properties":[],"score":0.7926449, "topicality":0.7926449},                |
    |                                                               |  {"confidence":0.0,"description":"Annual plant","locale":"","locations":[],"mid":"/m/0jqb",                    |
    |                                                               |  "Properties":[],"score":0.75020844, "topicality":0.75020844},{"confidence":0.0,                               |
    |                                                               |  "description":"Flowering plant","locale":"","locations":[],"mid":"/m/04sjm",                                  |
    |                                                               |  "Properties":[],"score":0.7403478,"topicality":0.7403478},{"confidence":0.0,                                  |
    |                                                               |  "description":"Chamaemelum nobile","locale":"","locations":[],"mid":"/m/05cmcg",                              |
    |                                                               |  "Properties":[],"score":0.7264577,"topicality":0.7264577},{"confidence":0.0,                                  |
    |                                                               |  "description":"Close-up","locale":"","locations":[],"mid":"/m/02cqfm","properties":[],                        |
    |                                                               |  "score":0.721242,"topicality":0.721242},{"confidence":0.0,"description":"Daisy family",                       |
    |                                                               |  "locale":"","locations":[],"mid":"/m/0l5r","properties":[],"score":0.7012979,                                 |
    |                                                               |  "Topicality":0.7012979}],"landmark_annotations":[],"localized_object_annotations":[],                         |
    |                                                               |  "logo_annotations":[],"text_annotations":[]}                                                                  |
    —------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------
    
    

Effectuer un nettoyage

  1. Dans la console Google Cloud, 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 sur Arrêter pour supprimer le projet.