教程:使用远程函数分析对象表

本教程介绍如何基于花卉数据集中的图片创建对象表,创建使用 Cloud Vision API 为图片添加标签的远程函数,然后使用远程函数分析对象表中的图片。

所需权限

  • 如需创建数据集,您需要拥有 bigquery.datasets.create 权限。
  • 如需创建连接资源,您需要以下权限:

    • bigquery.connections.create
    • bigquery.connections.get
  • 如需向连接的服务账号授予权限,您需要以下权限:

    • resourcemanager.projects.setIamPolicy
  • 如需创建对象表,您需要以下权限:

    • bigquery.tables.create
    • bigquery.tables.update
    • bigquery.connections.delegate
  • 如需创建远程函数,您需要与 Cloud Functions Developer 角色关联的权限。

  • 如需调用远程函数,您需要 Cloud Run Invoker 角色。

  • 如需使用远程函数分析对象表,您需要拥有对象表的 bigquery.tables.getData 权限。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

  • BigQuery:您在 BigQuery 中创建对象表时会产生存储费用。
  • Cloud Functions:调用远程函数会产生费用,远程函数使用的任何计算资源(包括调用 Cloud Vision API)也会产生费用。

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

如需详细了解 Cloud Storage 价格,请参阅 Cloud Storage 价格页面。

如需详细了解 BigQuery 存储价格,请参阅 BigQuery 文档中的存储价格

如需详细了解 Cloud Functions 价格,请参阅 Cloud Functions 价格页面。

如需详细了解 Vision API 价格,请参阅 Vision 文档中的 Cloud Vision 价格

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  2. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  3. 确保您的 Google Cloud 项目已启用结算功能

  4. 启用 BigQuery, BigQuery Connection API, and Cloud Functions API。

    启用 API

  5. 在 Google Cloud Console 中的项目选择器页面上,选择或创建一个 Google Cloud 项目

    转到“项目选择器”

  6. 确保您的 Google Cloud 项目已启用结算功能

  7. 启用 BigQuery, BigQuery Connection API, and Cloud Functions API。

    启用 API

创建 Cloud Functions 函数

如需创建函数,请按照以下步骤操作:

  1. 转到 Cloud Functions 页面。

    转到 Cloud Functions

  2. 点击创建函数

  3. 对于环境,选择第 2 代

  4. 对于函数名称,输入 vision-ai

  5. 点击下一步

  6. 对于运行时,选择 Python 3.9

  7. 对于入口点,输入 label_detection

  8. 选择 main.py。复制并粘贴以下代码:

    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. 选择 requirements.txt。复制并粘贴以下文本:

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

  10. 点击部署

  11. 函数部署完成后,点击触发器标签页。

  12. 复制触发器网址的值并将其保存到某个位置。您在创建远程函数时需要用到此信息。

创建数据集

创建名为 remote_function_test 的数据集:

SQL

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 编辑器窗格中,运行以下 SQL 语句:

    CREATE SCHEMA `PROJECT_ID.remote_function_test`;
    

    PROJECT_ID 替换为您的项目 ID。

bq

  1. 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

  2. 运行 bq mk 命令以创建数据集:

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

    PROJECT_ID 替换为您的项目 ID。

创建连接

创建名为 lake-connection 的连接:

控制台

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 点击 添加数据,然后点击外部数据源

  3. 连接类型列表中,选择 BigLake 和远程函数(Cloud 资源)

  4. 连接 ID 字段中,输入 lake-connection

  5. 点击创建连接

  6. 连接信息窗格中,复制服务账号 ID 字段中的值并将其保存到某个位置。您需要此信息才能向连接的服务账号授予权限

bq

  1. 在 Cloud Shell 中,运行 bq mk 命令以创建连接:

    bq mk --connection --location=us --connection_type=CLOUD_RESOURCE \
    lake-connection
    
  2. 运行 bq show 命令以检索有关连接的信息:

    bq show --connection us.lake-connection
    
  3. properties 列中,复制 serviceAccountId 属性的值并将其保存到某个位置。您需要此信息才能向连接的服务账号授予权限

创建 Cloud Storage 存储桶

创建 Cloud Storage 存储桶以存储花卉数据集。

向连接的服务账号授予权限

如需向服务账号授予权限,请按以下步骤操作:

  1. 前往 IAM 和管理页面。

    转到“IAM 和管理”

  2. 点击授予访问权限

    系统随即会打开添加主账号对话框。

  3. 新的主账号字段中,输入您之前复制的服务账号 ID。

  4. 选择角色字段中,选择 Cloud Run,然后选择 Cloud Run Invoker

  5. 点击添加其他角色

  6. 选择角色字段中,选择 Cloud Storage,然后选择 Storage Object Viewer

  7. 点击保存

将数据集上传到 Cloud Storage

获取数据集文件并将其提供给 Cloud Storage:

  1. 将花卉数据集下载到本地机器。
  2. 将数据集上传到之前创建的存储桶。

创建对象表

基于您上传的花卉数据集创建名为 sample_images 的对象表:

SQL

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 编辑器窗格中,运行以下 SQL 语句:

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

    BUCKET_NAME 替换为您之前创建的存储桶的名称。

bq

在 Cloud Shell 中,运行 bq mk 命令以创建连接:

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

BUCKET_NAME 替换为您之前创建的存储桶的名称。

创建 BigQuery 远程函数

创建一个名为 label_detection 的远程函数:

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 编辑器窗格中,运行以下 SQL 语句:

    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
    );
    

    TRIGGER_URL 替换为您之前保存的触发器网址。网址应类似于 https://vision-ai-1abcd2efgh-uc.a.run.app

调用远程函数

sample_images 对象表调用 label_detection 远程函数:

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 编辑器窗格中,运行以下 SQL 语句:

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

    结果应如下所示:

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | 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":[]}                                                                  |
    —------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------
    
    

清理

  1. 在 Google Cloud 控制台中,进入管理资源页面。

    转到“管理资源”

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。