動画へのアノテーション付け

モデルをトレーニングしたら、動画を一覧表示する batchPredict メソッドに CSV ファイルを指定することで、予測をリクエストできます。batchPredict メソッドは、モデルによる予測に基づいてラベルを適用します。

カスタムモデルの最大寿命は 2 年です。それ以降は、新しいモデルをトレーニングする必要があります。

予測の例

AutoML Video Classification にバッチ予測をリクエストするには、アノテーションを付ける動画への Cloud Storage パスをリストした CSV ファイルを作成します。開始時間と終了時間を指定して、動画のセグメント(セグメントレベル)にのみアノテーションを付けるよう AutoML Video Classification に指示することもできます。開始時間はゼロ以上で、終了時間より前にする必要があります。終了時間は開始時間より後で、動画の長さ以下にする必要があります。inf を使用して動画の終わりを示すこともできます。

gs://my-videos-vcm/short_video_1.avi,0.0,5.566667
gs://my-videos-vcm/car_chase.avi,0.0,3.933333
gs://my-videos-vcm/northwest_wildlife_01.avi,0.0,3.7
gs://my-videos-vcm/northwest_wildlife_02.avi,0.0,1.666667
gs://my-videos-vcm/motorcycles_and_cars.avi,0.0,2.633333
gs://my-videos-vcm/drying_paint.avi,0.0,inf

AutoML Video Classification がモデルによる予測の結果を書き込む出力ファイルのパスも指定する必要があります。このパスは、書き込み権限がある Cloud Storage バケットとオブジェクトである必要があります。

各動画の長さは 3 時間までで、最大ファイルサイズは 50 GB です。AutoML Video Classification では、12 時間の処理時間で約 100 時間分の動画の予測を生成できます。

動画の予測をリクエストするときは、params セクションで次のオプションを設定できます。これらのオプションを指定しない場合、デフォルトのスコアしきい値が適用され、segment_classification が使用されます。

  • score_threshold - 0.0(信頼できない)から 1.0(信頼度が非常に高い)までの値。モデルが動画の予測を行う場合、指定した信頼スコア以上の結果のみが生成されます。API のデフォルト値は 0.5 です。

  • segment_classification - セグメント レベルの分類を有効にするには、true に設定します。その場合、リクエストの構成で指定した動画のセグメント全体のラベルとその信頼スコアが返されます。デフォルトは true です。

  • shot_classification - ショットレベルの分類を有効にするには、true に設定します。この場合、AutoML Video Classification により、リクエストの構成で指定した動画のセグメント全体で各カメラショットの境界が特定されます。そして、検出されたショットごとのラベルとその信頼スコアが、ショットの開始時間と終了時間とともに返されます。デフォルトは false です。

  • 1s_interval_classification - 1 秒間隔での動画の分類を有効にするには、true に設定します。この場合、AutoML Video Classification から、リクエストの構成で指定した動画のセグメント全体の 1 秒ごとにラベルとその信頼スコアが返されます。デフォルトは false です。

ウェブ UI

  1. AutoML Video Classification UI を開きます。
  2. 表示されたリストから、使用するカスタムモデルをクリックします。 Cloud Console でのカスタム AutoML Video Intelligence モデルのリスト
  3. モデルの [テストと使用] タブで次の操作を行います。
    • [モデルのテスト] で、予測に使用する CSV ファイルを選択します。この CSV ファイルには、アノテーションを付ける動画のリストが含まれている必要があります。
    • [Test your model] ではさらに、アノテーション結果を受け取る Cloud Storage バケット内のディレクトリを選択します。

      アノテーション結果を保持する特定の結果フォルダを Cloud Storage バケットに実際に作成してもかまいません。 そうすれば、結果ディレクトリに含まれている video_classification.csv ファイルを読み込むことで、以前の予測に簡単にアクセスできます。

    • [Get Predictions] をクリックします。
    AutoML Video Intelligence に対する予測リクエストを構成する

アノテーションを付ける動画の数によっては、予測を取得する処理に時間がかかることがあります。

処理が完了すると、モデルページの [Recent Predictions] の下に結果が表示されます。 結果を見るには、次の手順に従います。

  1. [Recent Predictions] の [Predictions] 列で、表示する予測の [View] をクリックします。
  2. [Video] で、結果を表示する動画の名前を選択します。

AutoML Video Intelligence による予測の結果

REST とコマンドライン

後述のリクエストのデータを使用する前に、次のように置き換えます。

  • input-uri: アノテーションを付けるファイルを含む Cloud Storage バケット(ファイル名を含む)。先頭は gs:// でなければなりません。例:
    "inputUris": ["gs://automl-video-demo-data/hmdb_split1_test_gs_predict.csv"]
  • output-bucket: Cloud Storage バケットの名前に置き換えます。例: my-project-vcm
  • object-id: データ インポート オペレーションのオペレーション ID に置き換えます。
  • 注:
    • project-number: プロジェクトの番号。
    • location-id: アノテーションを実行する Cloud リージョン。サポート対象のクラウド リージョンは us-east1us-west1europe-west1asia-east1 です。リージョンを指定しないと、動画ファイルの場所に基づいてリージョンが決まります。

HTTP メソッドと URL:

POST https://automl.googleapis.com/v1beta1/projects/project-number/locations/location-id/models/model-id:batchPredict

JSON 本文のリクエスト:

{
  "inputConfig": {
    "gcsSource": {
      "inputUris": [input-uri]
    }
  },
  "outputConfig": {
    "gcsDestination": {
      "outputUriPrefix": "gs://output-bucket/object-id"
    }
  }
}

リクエストを送信するには、次のいずれかのオプションを選択します。

curl

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

curl -X POST \
-H "Authorization: Bearer "$(gcloud auth application-default print-access-token) \
-H "Content-Type: application/json; charset=utf-8" \
-d @request.json \
https://automl.googleapis.com/v1beta1/projects/project-number/locations/location-id/models/model-id:batchPredict

PowerShell

リクエスト本文を request.json という名前のファイルに保存して、次のコマンドを実行します。

$cred = gcloud auth application-default print-access-token
$headers = @{ "Authorization" = "Bearer $cred" }

Invoke-WebRequest `
-Method POST `
-Headers $headers `
-ContentType: "application/json; charset=utf-8" `
-InFile request.json `
-Uri "https://automl.googleapis.com/v1beta1/projects/project-number/locations/location-id/models/model-id:batchPredict " | Select-Object -Expand Content

バッチ予測リクエストのオペレーション ID が返されます(例: VCN926615623331479552)。

CSV ファイルで指定した動画の数によっては、バッチ予測タスクが完了するまでに時間がかかることがあります。タスクが完了すると、次の例のように、オペレーションのステータスが done: true と表示されます。エラーは発生していません。

{
  "name": "projects/project-number/locations/location-id/operations/VCN926615623331479552",
  "metadata": {
    "@type": "type.googleapis.com/google.cloud.automl.v1beta1.OperationMetadata",
    "createTime": "2020-02-11T21:39:19.832131Z",
    "updateTime": "2020-02-11T21:43:43.908318Z",
    "done": true,
    "batchPredictDetails": {
      "inputConfig": {
        "gcsSource": {
          "inputUris": [
            "gs://bucket-name/input-file.csv"
          ]
        }
      },
      "outputInfo": {
        "gcsOutputDirectory": "output-storage-path/prediction-test_model_01-2019-01-11T21:39:19.684Z"
      }
    }
  }
}

バッチ予測タスクが完了すると、コマンドで指定した Cloud Storage バケットに予測の出力が保存されます。動画セグメントごとに JSON ファイルがあります。次に例を示します。

my-video-01.avi.json

{
  "input_uri": "automl-video-sample/sample_video.avi",
  "segment_classification_annotations": [ {
    "annotation_spec": {
      "display_name": "ApplyLipstick",
      "description": "ApplyLipstick"
    },
    "segments": [ {
      "segment": {
        "start_time_offset": {
        },
        "end_time_offset": {
          "seconds": 4,
          "nanos": 960000000
        }
      },
      "confidence": 0.43253016
    }, {
      "segment": {
        "start_time_offset": {
        },
        "end_time_offset": {
          "seconds": 4,
          "nanos": 960000000
        }
      },
      "confidence": 0.56746984
    } ],
    "frames": [ ]
  } ],
  "shot_classification_annotations": [ {
    "annotation_spec": {
      "display_name": "ApplyLipstick",
      "description": "ApplyLipstick"
    },
    "segments": [ {
      "segment": {
        "start_time_offset": {
        },
        "end_time_offset": {
          "seconds": 5
        }
      },
      "confidence": 0.43253016
    }, {
      "segment": {
        "start_time_offset": {
        },
        "end_time_offset": {
          "seconds": 5
        }
      },
      "confidence": 0.56746984
    } ],
    "frames": [ ]
  } ],
  "one_second_sliding_window_classification_annotations": [ {
    "annotation_spec": {
      "display_name": "ApplyLipstick",
      "description": "ApplyLipstick"
    },
    "segments": [ ],
    "frames": [ {
      "time_offset": {
        "nanos": 800000000
      },
      "confidence": 0.54533803
    }, {
      "time_offset": {
        "nanos": 800000000
      },
      ...
      "confidence": 0.57945728
    }, {
      "time_offset": {
        "seconds": 4,
        "nanos": 300000000
      },
      "confidence": 0.42054281
    } ]
  } ],
  "object_annotations": [ ],
  "error": {
    "details": [ ]
  }
}

Java

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.automl.v1beta1.BatchPredictInputConfig;
import com.google.cloud.automl.v1beta1.BatchPredictOutputConfig;
import com.google.cloud.automl.v1beta1.BatchPredictRequest;
import com.google.cloud.automl.v1beta1.BatchPredictResult;
import com.google.cloud.automl.v1beta1.GcsDestination;
import com.google.cloud.automl.v1beta1.GcsSource;
import com.google.cloud.automl.v1beta1.ModelName;
import com.google.cloud.automl.v1beta1.OperationMetadata;
import com.google.cloud.automl.v1beta1.PredictionServiceClient;
import java.io.IOException;
import java.util.concurrent.ExecutionException;

class BatchPredict {

  static void batchPredict() throws IOException, ExecutionException, InterruptedException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "YOUR_PROJECT_ID";
    String modelId = "YOUR_MODEL_ID";
    String inputUri = "gs://YOUR_BUCKET_ID/path_to_your_input_csv_or_jsonl";
    String outputUri = "gs://YOUR_BUCKET_ID/path_to_save_results/";
    batchPredict(projectId, modelId, inputUri, outputUri);
  }

  static void batchPredict(String projectId, String modelId, String inputUri, String outputUri)
      throws IOException, ExecutionException, InterruptedException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (PredictionServiceClient client = PredictionServiceClient.create()) {
      // Get the full path of the model.
      ModelName name = ModelName.of(projectId, "us-central1", modelId);

      // Configure the source of the file from a GCS bucket
      GcsSource gcsSource = GcsSource.newBuilder().addInputUris(inputUri).build();
      BatchPredictInputConfig inputConfig =
          BatchPredictInputConfig.newBuilder().setGcsSource(gcsSource).build();

      // Configure where to store the output in a GCS bucket
      GcsDestination gcsDestination =
          GcsDestination.newBuilder().setOutputUriPrefix(outputUri).build();
      BatchPredictOutputConfig outputConfig =
          BatchPredictOutputConfig.newBuilder().setGcsDestination(gcsDestination).build();

      // Build the request that will be sent to the API
      BatchPredictRequest request =
          BatchPredictRequest.newBuilder()
              .setName(name.toString())
              .setInputConfig(inputConfig)
              .setOutputConfig(outputConfig)
              .build();

      // Start an asynchronous request
      OperationFuture<BatchPredictResult, OperationMetadata> future =
          client.batchPredictAsync(request);

      System.out.println("Waiting for operation to complete...");
      BatchPredictResult response = future.get();
      System.out.println("Batch Prediction results saved to specified Cloud Storage bucket.");
    }
  }
}

Node.js

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const projectId = 'YOUR_PROJECT_ID';
// const location = 'us-central1';
// const modelId = 'YOUR_MODEL_ID';
// const inputUri = 'gs://YOUR_BUCKET_ID/path_to_your_input_csv_or_jsonl';
// const outputUri = 'gs://YOUR_BUCKET_ID/path_to_save_results/';

// Imports the Google Cloud AutoML library
const {PredictionServiceClient} = require('@google-cloud/automl').v1beta1;

// Instantiates a client
const client = new PredictionServiceClient();

async function batchPredict() {
  // Construct request
  const request = {
    name: client.modelPath(projectId, location, modelId),
    inputConfig: {
      gcsSource: {
        inputUris: [inputUri],
      },
    },
    outputConfig: {
      gcsDestination: {
        outputUriPrefix: outputUri,
      },
    },
  };

  const [operation] = await client.batchPredict(request);

  console.log('Waiting for operation to complete...');
  // Wait for operation to complete.
  const [response] = await operation.promise();
  console.log(
    `Batch Prediction results saved to Cloud Storage bucket. ${response}`
  );
}

batchPredict();

Python

from google.cloud import automl_v1beta1 as automl

def batch_predict(
    project_id="YOUR_PROJECT_ID",
    model_id="YOUR_MODEL_ID",
    input_uri="gs://YOUR_BUCKET_ID/path/to/your/input/csv_or_jsonl",
    output_uri="gs://YOUR_BUCKET_ID/path/to/save/results/",
):
    """Batch predict"""
    prediction_client = automl.PredictionServiceClient()

    # Get the full path of the model.
    model_full_id = prediction_client.model_path(
        project_id, "us-central1", model_id
    )

    gcs_source = automl.types.GcsSource(input_uris=[input_uri])

    input_config = automl.types.BatchPredictInputConfig(gcs_source=gcs_source)
    gcs_destination = automl.types.GcsDestination(output_uri_prefix=output_uri)
    output_config = automl.types.BatchPredictOutputConfig(
        gcs_destination=gcs_destination
    )
    params = {}

    response = prediction_client.batch_predict(
        model_full_id, input_config, output_config, params=params
    )

    print("Waiting for operation to complete...")
    print(
        "Batch Prediction results saved to Cloud Storage bucket. {}".format(
            response.result()
        )
    )