Analisar enriquecimentos de objetos no BigQuery

Consultar enriquecimentos de objetos com SQL no BigQuery permite pesquisar, filtrar e analisar metadados em milhões de objetos armazenados sem inspecionar cada objeto individualmente.

Quando você configura conjuntos de dados do Storage Insights, o Cloud Storage exporta automaticamente o inventário e os metadados de objetos, incluindo enriquecimentos de objetos gerados por modelos de IA, diretamente para o BigQuery. Nesta página, explicamos como o Cloud Storage estrutura os enriquecimentos de objetos no BigQuery. Ele também fornece receitas SQL para encontrar rótulos, detectar rostos, identificar conteúdo explícito, extrair caixas delimitadoras e categorizar documentos PDF.

Ter os papéis necessários

Para receber as permissões necessárias para consultar enriquecimentos de objetos no BigQuery, peça ao administrador para conceder a você os seguintes papéis do IAM no projeto:

Para mais informações sobre a concessão de papéis, consulte Gerenciar o acesso a projetos, pastas e organizações.

Esses papéis predefinidos contêm as permissões necessárias para consultar enriquecimentos de objetos no BigQuery. Para acessar as permissões exatas necessárias, expanda a seção Permissões necessárias:

Permissões necessárias

As seguintes permissões são necessárias para consultar enriquecimentos de objetos no BigQuery:

  • bigquery.jobs.create
  • bigquery.tables.getData

Essas permissões também podem ser concedidas com funções personalizadas ou outros papéis predefinidos.

Como os enriquecimentos de objetos se integram ao Storage Insights

Quando você configura um conjunto de dados do Storage Insights para seu projeto, o Cloud Storage exporta periodicamente o inventário de buckets e os contextos de objetos para um conjunto de dados do BigQuery.

No BigQuery, seus dados aparecem na visualização object_contexts_catalog_view. Essa visualização oferece um catálogo unificado dos objetos armazenados. Cada linha contém atributos de objeto (project, bucket, name, generation) e uma matriz de registro contexts repetida:

  • contexts.key: o identificador de contexto exclusivo. As melhorias de machine learning geradas pelo Cloud Storage sempre começam com o prefixo google:annotation: (por exemplo, google:annotation:label-detector-v1 ou google:annotation:face-detector-v1).
  • contexts.value: o status de execução do modelo para o enriquecimento (como SUCCESS ou FAILURE).
  • contexts.extendedData: uma coluna JSON que contém o payload de enriquecimento do modelo, como rótulos detectados, pontos de referência faciais, vértices de polígono e caminhos de categoria.

Para ver a estrutura completa da tabela e as descrições das colunas, consulte o esquema do catálogo de contextos de objetos.

Entender os padrões de consulta: UNNEST x EXISTS

Um objeto pode ter vários contextos, e cada modelo pode gerar várias detecções (como vários rótulos ou rostos detectados). Ao consultar a visualização object_contexts_catalog_view, normalmente você usa um dos seguintes padrões SQL:

  • Linha por detecção (UNNEST): use o operador UNNEST na matriz de registros contexts repetida e na matriz JSON interna do modelo (usando a função JSON_QUERY_ARRAY). O desaninhar nivela as melhorias repetidas para que cada recurso detectado produza a própria linha. Use essa abordagem quando precisar inspecionar rótulos individuais, extrair coordenadas de caixas delimitadoras ou calcular estatísticas em todas as detecções.
  • Linha por objeto (EXISTS): use uma subconsulta EXISTS correlacionada para testar se um objeto contém um rótulo, uma saída do modelo ou um limite específico. Essa abordagem avalia contextos repetidos sem desaninhar na consulta externa. Ele retorna exatamente uma linha por objeto, independentemente de quantas detecções correspondem.

Exemplos de consultas

Os exemplos de SQL a seguir mostram como consultar e filtrar enriquecimentos de objetos para fluxos de trabalho comuns de curadoria e análise de dados.

Em cada consulta, substitua o seguinte:

  • PROJECT_ID: ID do seu projeto do Cloud de Confiance .
  • DATASET_ID: o nome do conjunto de dados do BigQuery em que o Storage Insights exporta seus dados.

Encontrar imagens que contêm um rótulo específico

Para pesquisar imagens avaliadas pelo modelo label-detector, é possível retornar cada rótulo correspondente como uma linha individual ou retornar imagens exclusivas que contêm o rótulo.

Retornar rótulos correspondentes (mescla linhas)

A consulta a seguir nivela as matrizes contexts e labelAnnotations para retornar uma linha separada para cada rótulo correspondente encontrado em uma imagem:

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;

Retornar imagens exclusivas (evita linhas duplicadas)

Se uma imagem tiver vários rótulos correspondentes, o desaninhar vai produzir várias linhas para esse objeto. Para retornar exatamente uma linha por imagem, verifique se o rótulo existe em uma subconsulta 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;

Encontrar fotos de retrato e selfie com um elemento principal sorrindo (detecção facial)

É possível combinar vários atributos faciais, como expressões emocionais, ângulos de orientação da cabeça e dimensões da caixa delimitadora, para encontrar tipos específicos de fotos.

A consulta a seguir usa uma expressão de tabela comum (CTE, na sigla em inglês) para calcular a cobertura da caixa delimitadora de rostos. Ele filtra retratos de pessoas sorrindo e olhando para frente, em que o sujeito ocupa pelo menos 60% da imagem:

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;

Essa consulta aplica os seguintes filtros:

  • joy_probability > 0.5: seleciona rostos avaliados como expressando felicidade ou sorrindo.
  • BETWEEN -10 AND 10: restringe os ângulos roll, pan e tilt para que o rosto fique orientado diretamente para a câmera.
  • face_coverage_percentage >= 0.60: usa vértices de polígono normalizados (0.0 a 1.0) para filtrar rostos que ocupam 60% ou mais do frame.

Encontrar imagens com sinalizações de segurança de conteúdo

O modelo content-safety avalia imagens em busca de conteúdo adulto e violento. O modelo atribui a cada categoria uma classificação de probabilidade, como VERY_UNLIKELY, UNLIKELY, POSSIBLE, LIKELY ou VERY_LIKELY.

A consulta a seguir retorna imagens exclusivas que o modelo sinaliza com alta confiança como conteúdo adulto:

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;

Para filtrar conteúdo violento ou diferentes sensibilidades, substitua o campo adultContentLikelihood pelo campo violentContentLikelihood ou verifique a classificação 'LIKELY'.

Contar imagens que contêm um rótulo específico

Para contar o número total de imagens exclusivas que contêm um rótulo específico sem contagem duplicada de imagens que correspondem a vários rótulos, use COUNT(*) com uma subconsulta 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
  );

Extrair coordenadas da caixa delimitadora para objetos detectados

O modelo object-detector detecta objetos físicos em uma imagem e fornece polígonos delimitadores normalizados (boundingPoly) que indicam onde o objeto aparece no frame.

A consulta a seguir extrai objetos detectados chamados Drink e cria colunas de coordenadas de caixa delimitadora de nível superior (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;

A subconsulta calcula as coordenadas normalizadas mínimas e máximas de cada polígono, e a expressão .* descompacta os campos de coordenadas x_min, y_min, x_max e y_max diretamente no conjunto de resultados.

Combinar objetos em vários modelos

Como o Cloud Storage anexa as melhorias de cada modelo como contextos independentes no mesmo objeto, é possível mesclar vários resultados de modelos para encontrar conteúdo altamente específico.

A consulta a seguir desfaz o aninhamento de contexts duas vezes para encontrar imagens que o modelo label-detector classifica como Ristretto e que contêm um objeto Drink localizado identificado pelo modelo object-detector:

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;

Filtrar documentos PDF por categoria de classificação

O modelo pdf-classification atribui categorias hierárquicas (como /Finance/Accounting & Auditing ou /Law & Government/Legal Services) a documentos PDF armazenados.

A consulta a seguir encontra objetos PDF categorizados na ramificação /Finance com pontuações de confiança maiores que 0,5:

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;

Para ver a lista completa de categorias de taxonomia compatíveis, consulte Categorias de classificação de PDF.

Agrupar documentos PDF por categoria de classificação

Para analisar a distribuição de documentos no seu arquivo, agregue e conte os objetos PDF por categoria:

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;

Entre em ação nos resultados da consulta

Consultar seus metadados geralmente é a primeira etapa na curadoria automatizada de dados, auditoria de conformidade ou aplicação de políticas. Depois de identificar conjuntos específicos de objetos no BigQuery, é possível alimentar esses resultados em fluxos de trabalho downstream, da seguinte maneira:

  • Organizar conjuntos de dados de machine learning: exporte os resultados da consulta para uma nova tabela do BigQuery ou um arquivo CSV para criar conjuntos de treinamento e validação direcionados para modelos personalizados.
  • Colocar em quarentena ou remover objetos que violam a política: insira os nomes dos objetos e os locais dos buckets identificados pelas consultas de segurança nas operações em lote do Storage para movê-los para buckets de quarentena restritos ou excluí-los em massa.
  • Auditar a distribuição de conteúdo e otimizar os custos: agregue classificações, dimensões e categorias de objetos para entender a distribuição de armazenamento na organização e criar regras de gerenciamento de ciclo de vida segmentadas.

A seguir