通过在 BigQuery 中使用 SQL 查询对象丰富化,您可以搜索、过滤和分析数百万个存储对象中的元数据,而无需单独检查每个对象。
配置 Storage Insights 数据集后,Cloud Storage 会自动将您的对象清单和元数据(包括 AI 模型生成的对象丰富化)直接导出到 BigQuery 中。本页面介绍了 Cloud Storage 如何在 BigQuery 中构建对象丰富化。此外,本页面还提供了 SQL 配方,用于查找标签、检测人脸、识别露骨内容、提取边界框以及对 PDF 文档进行分类。
获取所需的角色
如需获得在 BigQuery 中查询对象丰富化所需的权限,请让您的管理员向您授予项目的以下 IAM 角色:
- BigQuery Job User (
roles/bigquery.jobUser) - BigQuery Data Viewer (
roles/bigquery.dataViewer)
如需详细了解如何授予角色,请参阅管理对项目、文件夹和组织的访问权限。
这些预定义角色可提供 在 BigQuery 中查询对象丰富化所需的权限。如需查看所需的确切权限,请展开所需权限部分:
所需权限
在 BigQuery 中查询对象丰富化需要以下权限:
-
bigquery.jobs.create -
bigquery.tables.getData
对象丰富化与存储空间分析的集成方式
为项目配置 Storage Insights 数据集 后, Cloud Storage 会定期将存储桶清单和对象 上下文导出到 BigQuery 数据集中。
在 BigQuery 中,您的数据会显示在
object_contexts_catalog_view 视图中。此视图提供了一个统一的存储对象目录。每行都包含对象属性(project、bucket、name、generation)和一个重复的 contexts 记录数组:
contexts.key:唯一的上下文标识符。Cloud Storage 生成的机器学习 丰富化始终以google:annotation:前缀开头(例如google:annotation:label-detector-v1或google:annotation:face-detector-v1)。contexts.value:丰富化的模型执行状态(例如SUCCESS或FAILURE)。contexts.extendedData:一个JSON列,其中包含模型的丰富化载荷,例如检测到的标签、人脸地标、多边形顶点和类别路径。
如需查看完整的表结构和列说明,请参阅 对象上下文目录架构。
了解查询句式:UNNEST 与 EXISTS
一个对象可以有多个上下文,每个模型可以输出多个检测结果(例如多个标签或检测到的人脸)。查询 object_contexts_catalog_view 视图时,您通常会使用以下 SQL 模式之一:
- 每个检测结果一行 (
UNNEST) :对重复的contexts记录数组和模型的内部 JSON 数组使用UNNEST运算符(通过使用JSON_QUERY_ARRAY函数)。取消嵌套会展平重复的丰富化,以便每个检测到的特征都生成自己的行。当您需要检查单个标签、提取边界框坐标或计算检测结果的统计信息时,请使用此方法。 - 每个对象一行 (
EXISTS) :使用关联的EXISTS子查询来测试对象是否包含特定标签、模型输出或阈值。 此方法会评估重复的上下文,而无需在外部查询中取消嵌套。无论有多少检测结果匹配,它都会为每个对象返回一行。
查询示例
以下 SQL 示例展示了如何查询和过滤对象丰富化,以用于常见的数据整理和分析工作流。
在每个查询中,替换以下内容:
PROJECT_ID:您的 Google Cloud 项目的 ID。DATASET_ID:存储空间分析将数据导出到的 BigQuery 数据集的名称。
查找包含特定标签的图片
如需搜索由 label-detector 模型评估的图片,您可以将每个匹配的标签作为单独一行返回,也可以返回包含该标签的唯一图片。
返回匹配的标签(展平行)
以下查询会展平 contexts 和 labelAnnotations 数组,以便为图片中找到的每个匹配标签返回单独一行:
SELECT
t.project,
t.bucket,
t.name,
t.generation,
STRING(label.description) AS label_description,
FLOAT64(label.score) AS confidence_score
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t,
UNNEST(t.contexts) AS context,
UNNEST(JSON_QUERY_ARRAY(context.extendedData.labelAnnotationGroup.labelAnnotations)) AS label
WHERE
context.key = 'google:annotation:label-detector-v1'
AND LOWER(STRING(label.description)) = 'car'
AND FLOAT64(label.score) > 0.75
LIMIT 10;
返回唯一图片(避免重复行)
如果图片包含多个匹配的标签,则取消嵌套会为该对象生成多行。如需为每张图片返回一行,请在 EXISTS 子查询中检查标签是否存在:
SELECT
project,
bucket,
name,
generation
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t
WHERE
EXISTS(
SELECT 1
FROM
UNNEST(t.contexts) AS context,
UNNEST(JSON_QUERY_ARRAY(context.extendedData.labelAnnotationGroup.labelAnnotations)) AS label
WHERE
context.key = 'google:annotation:label-detector-v1'
AND LOWER(STRING(label.description)) = 'car'
AND FLOAT64(label.score) > 0.75
)
LIMIT 10;
查找包含微笑主题的肖像照和自拍照(人脸检测)
您可以组合使用多个人脸属性(例如情绪表达、头部朝向角度和边界框尺寸)来查找特定类型的照片。
以下查询使用通用表表达式 (CTE) 来计算人脸边界框覆盖率。它会过滤出微笑的正面肖像照,其中主题至少占据图片的 60%:
WITH
face_stats AS (
SELECT
t.project,
t.bucket,
t.name,
t.generation,
-- Extract the joy likelihood score (0.0 to 1.0)
FLOAT64(face.joyProbability) AS joy_probability,
-- Extract head pose orientation angles (degrees)
FLOAT64(face.rollAngle) AS roll_angle,
FLOAT64(face.panAngle) AS pan_angle,
FLOAT64(face.tiltAngle) AS tilt_angle,
-- Calculate the bounding box area relative to total image area (0.0 to 1.0)
(
SELECT AS STRUCT
(MAX(FLOAT64(v.x)) - MIN(FLOAT64(v.x)))
* (MAX(FLOAT64(v.y)) - MIN(FLOAT64(v.y))) AS coverage
FROM
UNNEST(JSON_QUERY_ARRAY(face.boundingPoly.normalizedVertices)) AS v
).coverage AS face_coverage_percentage
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t,
UNNEST(t.contexts) AS context,
UNNEST(
JSON_QUERY_ARRAY(
context.extendedData.faceAnnotationGroup.faceAnnotations)) AS face
WHERE
context.key = 'google:annotation:face-detector-v1'
)
SELECT
project,
bucket,
name,
generation,
joy_probability,
face_coverage_percentage
FROM
face_stats
WHERE
joy_probability > 0.5
AND roll_angle BETWEEN -10 AND 10
AND pan_angle BETWEEN -10 AND 10
AND tilt_angle BETWEEN -10 AND 10
AND face_coverage_percentage >= 0.60
LIMIT 10;
此查询应用了以下过滤器:
joy_probability > 0.5:选择被评估为表达快乐或 微笑的人脸。BETWEEN -10 AND 10:限制roll、pan和tilt角度,使人脸直接面向相机。face_coverage_percentage >= 0.60:使用归一化多边形顶点 (0.0到1.0)来过滤出占据帧 60% 或更多的人脸。
查找具有内容安全标志的图片
content-safety 模型会评估图片中的成人内容和暴力内容。该
模型会为每个类别分配一个似然度评分,例如 VERY_UNLIKELY、UNLIKELY、
POSSIBLE、LIKELY 或 VERY_LIKELY。
以下查询会返回模型以高置信度标记为成人内容的唯一图片:
SELECT
project,
bucket,
name,
generation
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t
WHERE
EXISTS(
SELECT 1
FROM
UNNEST(t.contexts) AS context
WHERE
context.key = 'google:annotation:content-safety-v1'
AND STRING(context.extendedData.contentSafetyAnnotation.adultContentLikelihood) = 'VERY_LIKELY'
)
LIMIT 10;
如需过滤暴力内容或不同的敏感度,请将
adultContentLikelihood字段替换为violentContentLikelihood字段,或
检查'LIKELY'评分。
统计包含特定标签的图片数量
如需统计包含特定标签的唯一图片总数,而不会重复统计与多个标签匹配的图片,请将 COUNT(*) 与 EXISTS 子查询搭配使用:
SELECT
COUNT(*) AS image_count
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t
WHERE
EXISTS(
SELECT 1
FROM
UNNEST(t.contexts) AS context,
UNNEST(
JSON_QUERY_ARRAY(
context.extendedData.labelAnnotationGroup.labelAnnotations)) AS label
WHERE
context.key = 'google:annotation:label-detector-v1'
AND LOWER(STRING(label.description)) = 'ristretto'
AND FLOAT64(label.score) > 0.5
);
提取检测到的对象的边界框坐标
object-detector 模型会检测图片中的实物对象,并提供归一化边界多边形 (boundingPoly),指明对象在帧中的显示位置。
以下查询会提取名为 Drink 的检测到的对象,并构建顶级边界框坐标列(x_min、y_min、x_max、y_max):
SELECT
t.project,
t.bucket,
t.name,
t.generation,
STRING(object.name) AS object_name,
FLOAT64(object.score) AS confidence_score,
-- Calculate bounding box boundaries from normalized vertices
(
SELECT AS STRUCT
MIN(FLOAT64(v.x)) AS x_min,
MIN(FLOAT64(v.y)) AS y_min,
MAX(FLOAT64(v.x)) AS x_max,
MAX(FLOAT64(v.y)) AS y_max
FROM
UNNEST(JSON_QUERY_ARRAY(object.boundingPoly.normalizedVertices)) AS v
).*
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t,
UNNEST(t.contexts) AS context,
UNNEST(
JSON_QUERY_ARRAY(
context.extendedData.objectAnnotationGroup.objectAnnotations)) AS object
WHERE
context.key = 'google:annotation:object-detector-v1'
AND LOWER(STRING(object.name)) = 'drink'
AND FLOAT64(object.score) > 0.5
LIMIT 10;
子查询会计算每个多边形的最小和最大归一化坐标,而 .* 表达式会将 x_min、y_min、x_max 和 y_max 坐标字段直接解压缩到结果集中。
跨多个模型匹配对象
由于 Cloud Storage 会将每个模型的丰富化作为同一对象上的独立上下文附加,因此您可以联接多个模型结果来查找高度特定的内容。
以下查询会取消嵌套 contexts 两次,以查找 label-detector 模型分类为 Ristretto 且包含 object-detector 模型识别的本地化 Drink 对象的图片:
SELECT
t.project,
t.bucket,
t.name,
t.generation,
STRING(object.name) AS object_name,
FLOAT64(object.score) AS object_score,
STRING(label.description) AS label_description,
FLOAT64(label.score) AS label_score,
(
SELECT AS STRUCT
MIN(FLOAT64(v.x)) AS x_min,
MIN(FLOAT64(v.y)) AS y_min,
MAX(FLOAT64(v.x)) AS x_max,
MAX(FLOAT64(v.y)) AS y_max
FROM
UNNEST(JSON_QUERY_ARRAY(object.boundingPoly.normalizedVertices)) AS v
).*
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t,
-- Match the label detection context
UNNEST(t.contexts) AS label_ctx,
UNNEST(
JSON_QUERY_ARRAY(
label_ctx.extendedData.labelAnnotationGroup.labelAnnotations)) AS label,
-- Match the object detection context on the same object
UNNEST(t.contexts) AS object_ctx,
UNNEST(
JSON_QUERY_ARRAY(
object_ctx.extendedData.objectAnnotationGroup.objectAnnotations)) AS object
WHERE
label_ctx.key = 'google:annotation:label-detector-v1'
AND LOWER(STRING(label.description)) = 'ristretto'
AND FLOAT64(label.score) > 0.5
AND object_ctx.key = 'google:annotation:object-detector-v1'
AND LOWER(STRING(object.name)) = 'drink'
AND FLOAT64(object.score) > 0.5
LIMIT 10;
按分类类别过滤 PDF 文档
pdf-classification 模型会将分层类别(例如
/Finance/Accounting & Auditing 或 /Law & Government/Legal Services)分配给
存储的 PDF 文档。
以下查询会查找在 /Finance 分支下分类且置信度分数大于 0.5 的 PDF 对象:
SELECT
t.project,
t.bucket,
t.name,
t.generation,
STRING(category.label) AS category_name,
FLOAT64(category.score) AS confidence_score
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t,
UNNEST(t.contexts) AS context,
UNNEST(
JSON_QUERY_ARRAY(
context.extendedData.pdfClassificationCategoryList.categories)) AS category
WHERE
context.key = 'google:annotation:pdf-classification-v1'
AND STARTS_WITH(STRING(category.label), '/Finance')
AND FLOAT64(category.score) > 0.5
LIMIT 10;
如需查看受支持的分类类别的完整列表,请参阅 PDF 分类 类别。
按分类类别汇总 PDF 文档
如需分析文档在归档中的分布情况,请按类别汇总和统计 PDF 对象:
SELECT
STRING(category.label) AS category_name,
COUNT(*) AS document_count
FROM
`PROJECT_ID.DATASET_ID.object_contexts_catalog_view` AS t,
UNNEST(t.contexts) AS context,
UNNEST(
JSON_QUERY_ARRAY(
context.extendedData.pdfClassificationCategoryList.categories)) AS category
WHERE
context.key = 'google:annotation:pdf-classification-v1'
GROUP BY
category_name
ORDER BY
document_count DESC
LIMIT 10;
对查询结果采取行动
查询元数据通常是自动数据整理、合规性审核或政策执行的第一步。在 BigQuery 中识别出特定对象集后,您可以将这些结果馈送到下游工作流中,如下所示:
- 整理机器学习数据集:将查询结果导出到新的 BigQuery 表或 CSV 文件,以便为自定义模型构建有针对性的训练集和 验证集。
- 隔离或移除违反政策的对象:将安全查询识别出的对象名称和 存储桶位置馈送到存储批量操作 中,以便将它们移至受限的隔离存储桶或批量删除它们。
- 审核内容分发情况并优化费用:汇总对象 分类、尺寸和类别,以了解组织内的存储 分布情况并创建有针对性的生命周期 管理规则。
后续步骤
- 阅读对象丰富化概览。
- 配置对象丰富化。
- 管理对象丰富化。
- 查看受支持的模型和 JSON 架构。
- 查看
featureConfigsJSON API 资源。 - 排查对象丰富化问题。
- 查看和查询存储空间分析关联的数据集。