Menganalisis pengayaan objek di BigQuery

Dengan mengkueri pengayaan objek menggunakan SQL di BigQuery, Anda dapat menelusuri, memfilter, dan menganalisis metadata di jutaan objek yang tersimpan tanpa memeriksa setiap objek satu per satu.

Saat Anda mengonfigurasi set data Insight Penyimpanan, Cloud Storage akan otomatis mengekspor inventaris dan metadata objek Anda, termasuk pengayaan objek yang dihasilkan oleh model AI, langsung ke BigQuery. Halaman ini menjelaskan cara Cloud Storage menyusun pengayaan objek di BigQuery. Model ini juga menyediakan resep SQL untuk menemukan label, mendeteksi wajah, mengidentifikasi konten vulgar, mengekstrak kotak pembatas, dan mengategorikan dokumen PDF.

Mendapatkan peran yang diperlukan

Untuk mendapatkan izin yang diperlukan untuk mengkueri pengayaan objek di BigQuery, minta administrator untuk memberi Anda peran IAM berikut pada project Anda:

Untuk mengetahui informasi selengkapnya tentang pemberian peran, lihat Mengelola akses ke project, folder, dan organisasi.

Peran yang telah ditetapkan ini berisi izin yang diperlukan untuk mengkueri pengayaan objek di BigQuery. Untuk melihat izin yang benar-benar diperlukan, perluas bagian Izin yang diperlukan:

Izin yang diperlukan

Izin berikut diperlukan untuk mengkueri pengayaan objek di BigQuery:

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

Anda mungkin juga bisa mendapatkan izin ini dengan peran khusus atau peran bawaan lainnya.

Cara pengayaan objek terintegrasi dengan Insight Penyimpanan

Saat Anda mengonfigurasi set data Insight Penyimpanan untuk project Anda, Cloud Storage akan mengekspor inventaris bucket dan konteks objek Anda secara berkala ke set data BigQuery.

Di BigQuery, data Anda akan muncul di tampilan object_contexts_catalog_view. Tampilan ini menyediakan katalog terpadu untuk objek yang Anda simpan. Setiap baris berisi atribut objek (project, bucket, name, generation) dan array data contexts berulang:

  • contexts.key: ID konteks unik. Pengayaan machine learning yang dihasilkan oleh Cloud Storage selalu dimulai dengan awalan google:annotation: (misalnya, google:annotation:label-detector-v1 atau google:annotation:face-detector-v1).
  • contexts.value: Status eksekusi model untuk pengayaan (seperti SUCCESS atau FAILURE).
  • contexts.extendedData: Kolom JSON yang berisi payload pengayaan model, seperti label yang terdeteksi, tempat terkenal wajah, verteks poligon, dan jalur kategori.

Untuk mengetahui struktur tabel dan deskripsi kolom yang lengkap, lihat Skema katalog konteks objek.

Memahami pola kueri: UNNEST versus EXISTS

Objek dapat memiliki beberapa konteks, dan setiap model dapat menghasilkan beberapa deteksi (seperti beberapa label atau wajah yang terdeteksi). Saat membuat kueri tabel virtual object_contexts_catalog_view, Anda biasanya menggunakan salah satu pola SQL berikut:

  • Baris per deteksi (UNNEST): Gunakan operator UNNEST pada array data contexts berulang dan array JSON dalam model (dengan menggunakan fungsi JSON_QUERY_ARRAY). Unnesting meratakan pengayaan berulang sehingga setiap fitur yang terdeteksi menghasilkan barisnya sendiri. Gunakan pendekatan ini saat Anda perlu memeriksa label individual, mengekstrak koordinat kotak pembatas, atau menghitung statistik di seluruh deteksi.
  • Baris per objek (EXISTS): Gunakan subkueri EXISTS yang berkorelasi untuk menguji apakah objek berisi label, output model, atau nilai minimum tertentu. Pendekatan ini mengevaluasi konteks berulang tanpa membatalkan penyarangannya dalam kueri luar. Fitur ini menampilkan tepat satu baris per objek, terlepas dari berapa banyak deteksi yang cocok.

Contoh kueri

Contoh SQL berikut menunjukkan cara membuat kueri dan memfilter pengayaan objek untuk alur kerja analisis dan seleksi data umum.

Di setiap kueri, ganti hal berikut:

  • PROJECT_ID: ID project Google Cloud Anda.
  • DATASET_ID: Nama set data BigQuery tempat Insight Penyimpanan mengekspor data Anda.

Menemukan gambar yang berisi label tertentu

Untuk menelusuri gambar yang dievaluasi oleh model label-detector, Anda dapat menampilkan setiap label yang cocok sebagai baris individual atau menampilkan gambar unik yang berisi label tersebut.

Menampilkan label yang cocok (meratakan baris)

Kueri berikut meratakan array contexts dan labelAnnotations untuk menampilkan baris terpisah untuk setiap label yang cocok yang ditemukan dalam gambar:

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;

Menampilkan gambar unik (menghindari baris duplikat)

Jika gambar berisi beberapa label yang cocok, unnesting akan menghasilkan beberapa baris untuk objek tersebut. Untuk menampilkan tepat satu baris per gambar, periksa keberadaan label dalam subkueri 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;

Menemukan foto potret dan selfie dengan subjek tersenyum (deteksi wajah)

Anda dapat menggabungkan beberapa atribut wajah, seperti ekspresi emosional, sudut orientasi kepala, dan dimensi kotak pembatas, untuk menemukan jenis foto tertentu.

Kueri berikut menggunakan ekspresi tabel umum (CTE) untuk menghitung cakupan kotak pembatas wajah. Kode ini memfilter potret tersenyum dan menghadap ke depan dengan subjek menempati setidaknya 60% gambar:

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;

Kueri ini menerapkan filter berikut:

  • joy_probability > 0.5: Memilih wajah yang dievaluasi sebagai ekspresi kebahagiaan atau tersenyum.
  • BETWEEN -10 AND 10: Membatasi sudut roll, pan, dan tilt sehingga wajah mengarah langsung ke kamera.
  • face_coverage_percentage >= 0.60: Menggunakan verteks poligon yang dinormalisasi (0.0 hingga 1.0) untuk memfilter wajah yang menempati 60% atau lebih dari frame.

Menemukan gambar yang memiliki tanda keamanan konten

Model content-safety mengevaluasi gambar untuk konten khusus dewasa dan kekerasan. Model ini menetapkan rating kemungkinan untuk setiap kategori, seperti VERY_UNLIKELY, UNLIKELY, POSSIBLE, LIKELY, atau VERY_LIKELY.

Kueri berikut menampilkan gambar unik yang ditandai oleh model dengan keyakinan tinggi sebagai konten khusus dewasa:

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;

Untuk memfilter konten kekerasan atau sensitivitas yang berbeda, ganti kolom adultContentLikelihood dengan kolom violentContentLikelihood, atau periksa rating 'LIKELY'.

Menghitung gambar yang berisi label tertentu

Untuk menghitung jumlah total gambar unik yang berisi label tertentu tanpa menghitung dua kali gambar yang cocok dengan beberapa label, gunakan COUNT(*) dengan subkueri 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
  );

Mengekstrak koordinat kotak pembatas untuk objek yang terdeteksi

Model object-detector mendeteksi objek fisik dalam gambar dan memberikan poligon pembatas yang dinormalisasi (boundingPoly) yang menunjukkan tempat objek muncul dalam frame.

Kueri berikut mengekstrak objek yang terdeteksi bernama Drink dan membuat kolom koordinat kotak pembatas tingkat atas (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;

Subkueri menghitung koordinat minimum dan maksimum yang dinormalisasi untuk setiap poligon, dan ekspresi .* membongkar kolom koordinat x_min, y_min, x_max, dan y_max langsung ke dalam set hasil.

Mencocokkan objek di beberapa model

Karena Cloud Storage melampirkan pengayaan dari setiap model sebagai konteks independen pada objek yang sama, Anda dapat menggabungkan beberapa hasil model untuk menemukan konten yang sangat spesifik.

Kueri berikut membatalkan penggabungan contexts dua kali untuk menemukan gambar yang diklasifikasikan oleh model label-detector sebagai Ristretto dan yang berisi objek Drink yang dilokalkan yang diidentifikasi oleh model 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;

Memfilter dokumen PDF menurut kategori klasifikasi

Model pdf-classification menetapkan kategori hierarkis (seperti /Finance/Accounting & Auditing atau /Law & Government/Legal Services) ke dokumen PDF yang disimpan.

Kueri berikut menemukan objek PDF yang dikategorikan dalam cabang /Finance dengan skor keyakinan lebih besar dari 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;

Untuk mengetahui daftar lengkap kategori taksonomi yang didukung, lihat Kategori klasifikasi PDF.

Menggabungkan dokumen PDF berdasarkan kategori klasifikasi

Untuk menganalisis distribusi dokumen di seluruh arsip, gabungkan dan hitung objek PDF Anda berdasarkan kategori:

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;

Mengambil tindakan pada hasil kueri

Membuat kueri metadata sering kali menjadi langkah pertama dalam pengumpulan data otomatis, audit kepatuhan, atau penegakan kebijakan. Setelah mengidentifikasi set objek tertentu di BigQuery, Anda dapat memasukkan hasil tersebut ke dalam alur kerja downstream, sebagai berikut:

  • Menyeleksi set data machine learning: Ekspor hasil kueri Anda ke tabel BigQuery atau file CSV baru untuk membuat set pelatihan dan set validasi yang ditargetkan untuk model kustom.
  • Karantina atau hapus objek yang melanggar kebijakan: Masukkan nama objek dan lokasi bucket yang diidentifikasi oleh kueri keamanan ke dalam Storage batch operations untuk memindahkannya ke bucket karantina yang dibatasi atau menghapusnya secara massal.
  • Mengaudit distribusi konten dan mengoptimalkan biaya: Gabungkan klasifikasi, dimensi, dan kategori objek untuk memahami distribusi penyimpanan di seluruh organisasi Anda dan membuat aturan pengelolaan siklus proses yang ditargetkan.

Langkah berikutnya