Batch image annotation offline

The Vision API can run offline (asynchronous) detection services and annotation of a batch of image files using any Vision API feature type. For example, you can specify one or multiple Vision API features (such as TEXT_DETECTION, LABEL_DETECTION, and LANDMARK_DETECTION) for a single batch of images.

Output from an offline batch request is written to a JSON file created in the specified Google Cloud Storage bucket.

Limitations

The Vision API accepts up to 2,000 image files. A larger batch of image files will return an error.

Currently supported feature types

All feature types
FACE_DETECTION Run face detection.
LANDMARK_DETECTION Run landmark detection.
LOGO_DETECTION Run logo detection.
LABEL_DETECTION Run label detection.
TEXT_DETECTION Run text detection / optical character recognition (OCR). Text detection is optimized for areas of text within a larger image; if the image is a document, use DOCUMENT_TEXT_DETECTION instead.
DOCUMENT_TEXT_DETECTION Run dense text document OCR. Takes precedence when both DOCUMENT_TEXT_DETECTION and TEXT_DETECTION are present.
SAFE_SEARCH_DETECTION Run Safe Search to detect potentially unsafe or undesirable content.
IMAGE_PROPERTIES Compute a set of image properties, such as the image's dominant colors.
CROP_HINTS Run crop hints.
WEB_DETECTION Run web detection.
OBJECT_LOCALIZATION Run localizer for object detection.

Sample code

Use the following code samples to run offline annotation services on a batch of image files in Google Cloud Storage.

Java

Before trying this sample, follow the Java setup instructions in the Vision API Quickstart Using Client Libraries . For more information, see the Vision API Java API reference documentation .

/*
 * Please include the following imports to run this sample.
 *
 * import com.google.cloud.vision.v1.AnnotateImageRequest;
 * import com.google.cloud.vision.v1.AsyncBatchAnnotateImagesRequest;
 * import com.google.cloud.vision.v1.AsyncBatchAnnotateImagesResponse;
 * import com.google.cloud.vision.v1.Feature;
 * import com.google.cloud.vision.v1.GcsDestination;
 * import com.google.cloud.vision.v1.Image;
 * import com.google.cloud.vision.v1.ImageAnnotatorClient;
 * import com.google.cloud.vision.v1.ImageSource;
 * import com.google.cloud.vision.v1.OutputConfig;
 * import java.util.Arrays;
 * import java.util.List;
 */

/** Perform async batch image annotation */
public static void sampleAsyncBatchAnnotateImages(String inputImageUri, String outputUri) {
  try (ImageAnnotatorClient imageAnnotatorClient = ImageAnnotatorClient.create()) {
    // inputImageUri = "gs://cloud-samples-data/vision/label/wakeupcat.jpg";
    // outputUri = "gs://your-bucket/prefix/";
    ImageSource source = ImageSource.newBuilder().setImageUri(inputImageUri).build();
    Image image = Image.newBuilder().setSource(source).build();
    Feature.Type type = Feature.Type.LABEL_DETECTION;
    Feature featuresElement = Feature.newBuilder().setType(type).build();
    Feature.Type type2 = Feature.Type.IMAGE_PROPERTIES;
    Feature featuresElement2 = Feature.newBuilder().setType(type2).build();
    List<Feature> features = Arrays.asList(featuresElement, featuresElement2);
    AnnotateImageRequest requestsElement =
        AnnotateImageRequest.newBuilder().setImage(image).addAllFeatures(features).build();
    List<AnnotateImageRequest> requests = Arrays.asList(requestsElement);
    GcsDestination gcsDestination = GcsDestination.newBuilder().setUri(outputUri).build();

    // The max number of responses to output in each JSON file
    int batchSize = 2;
    OutputConfig outputConfig =
        OutputConfig.newBuilder()
            .setGcsDestination(gcsDestination)
            .setBatchSize(batchSize)
            .build();
    AsyncBatchAnnotateImagesRequest request =
        AsyncBatchAnnotateImagesRequest.newBuilder()
            .addAllRequests(requests)
            .setOutputConfig(outputConfig)
            .build();
    AsyncBatchAnnotateImagesResponse response =
        imageAnnotatorClient.asyncBatchAnnotateImagesAsync(request).get();
    // The output is written to GCS with the provided output_uri as prefix
    String gcsOutputUri = response.getOutputConfig().getGcsDestination().getUri();
    System.out.printf("Output written to GCS with prefix: %s\n", gcsOutputUri);
  } catch (Exception exception) {
    System.err.println("Failed to create the client due to: " + exception);
  }
}

Node.js

Before trying this sample, follow the Node.js setup instructions in the Vision API Quickstart Using Client Libraries . For more information, see the Vision API Node.js API reference documentation .

const vision = require('@google-cloud/vision').v1;

/** Perform async batch image annotation */
async function sampleAsyncBatchAnnotateImages(inputImageUri, outputUri) {
  const client = new vision.ImageAnnotatorClient();
  // const inputImageUri = 'gs://cloud-samples-data/vision/label/wakeupcat.jpg';
  // const outputUri = 'gs://your-bucket/prefix/';
  const source = {
    imageUri: inputImageUri,
  };
  const image = {
    source: source,
  };
  const type = 'LABEL_DETECTION';
  const featuresElement = {
    type: type,
  };
  const type2 = 'IMAGE_PROPERTIES';
  const featuresElement2 = {
    type: type2,
  };
  const features = [featuresElement, featuresElement2];
  const requestsElement = {
    image: image,
    features: features,
  };
  const requests = [requestsElement];
  const gcsDestination = {
    uri: outputUri,
  };

  // The max number of responses to output in each JSON file
  const batchSize = 2;
  const outputConfig = {
    gcsDestination: gcsDestination,
    batchSize: batchSize,
  };
  const request = {
    requests: requests,
    outputConfig: outputConfig,
  };

  // Create a job whose results you can either wait for now, or get later
  const [operation] = await client.asyncBatchAnnotateImages(request);

  // Get a Promise representation of the final result of the job
  const [response] = await operation.promise();

  // The output is written to GCS with the provided output_uri as prefix
  const gcsOutputUri = response.outputConfig.gcsDestination.uri;
  console.log(`Output written to GCS with prefix: ${gcsOutputUri}`);
}

PHP

Before trying this sample, follow the PHP setup instructions in the Vision API Quickstart Using Client Libraries . For more information, see the Vision API PHP API reference documentation .

require __DIR__.'/../../vendor/autoload.php';

use Google\Cloud\Vision\V1\ImageAnnotatorClient;
use Google\Cloud\Vision\V1\AnnotateImageRequest;
use Google\Cloud\Vision\V1\Feature;
use Google\Cloud\Vision\V1\Feature\Type;
use Google\Cloud\Vision\V1\GcsDestination;
use Google\Cloud\Vision\V1\Image;
use Google\Cloud\Vision\V1\ImageSource;
use Google\Cloud\Vision\V1\OutputConfig;

/** Perform async batch image annotation */
function sampleAsyncBatchAnnotateImages($inputImageUri, $outputUri)
{

    $imageAnnotatorClient = new ImageAnnotatorClient();

    // $inputImageUri = 'gs://cloud-samples-data/vision/label/wakeupcat.jpg';
    // $outputUri = 'gs://your-bucket/prefix/';
    $source = new ImageSource();
    $source->setImageUri($inputImageUri);
    $image = new Image();
    $image->setSource($source);
    $type = Type::LABEL_DETECTION;
    $featuresElement = new Feature();
    $featuresElement->setType($type);
    $type2 = Type::IMAGE_PROPERTIES;
    $featuresElement2 = new Feature();
    $featuresElement2->setType($type2);
    $features = [$featuresElement, $featuresElement2];
    $requestsElement = new AnnotateImageRequest();
    $requestsElement->setImage($image);
    $requestsElement->setFeatures($features);
    $requests = [$requestsElement];
    $gcsDestination = new GcsDestination();
    $gcsDestination->setUri($outputUri);

    // The max number of responses to output in each JSON file
    $batchSize = 2;
    $outputConfig = new OutputConfig();
    $outputConfig->setGcsDestination($gcsDestination);
    $outputConfig->setBatchSize($batchSize);

    try {
        $operationResponse = $imageAnnotatorClient->asyncBatchAnnotateImages($requests, $outputConfig);
        $operationResponse->pollUntilComplete();
        if ($operationResponse->operationSucceeded()) {
            $response = $operationResponse->getResult();
            // The output is written to GCS with the provided output_uri as prefix
            $gcsOutputUri = $response->getOutputConfig()->getGcsDestination()->getUri();
            printf('Output written to GCS with prefix: %s'.PHP_EOL, $gcsOutputUri);
        } else {
            $error = $operationResponse->getError();
            // handleError($error)
        }
    } finally {
        $imageAnnotatorClient->close();
    }

}

Python

Before trying this sample, follow the Python setup instructions in the Vision API Quickstart Using Client Libraries . For more information, see the Vision API Python API reference documentation .

from google.cloud import vision_v1
from google.cloud.vision_v1 import enums
import six

def sample_async_batch_annotate_images(input_image_uri, output_uri):
  """Perform async batch image annotation"""

  client = vision_v1.ImageAnnotatorClient()

  # input_image_uri = 'gs://cloud-samples-data/vision/label/wakeupcat.jpg'
  # output_uri = 'gs://your-bucket/prefix/'

  if isinstance(input_image_uri, six.binary_type):
    input_image_uri = input_image_uri.decode('utf-8')
  if isinstance(output_uri, six.binary_type):
    output_uri = output_uri.decode('utf-8')
  source = {'image_uri': input_image_uri}
  image = {'source': source}
  type_ = enums.Feature.Type.LABEL_DETECTION
  features_element = {'type': type_}
  type_2 = enums.Feature.Type.IMAGE_PROPERTIES
  features_element_2 = {'type': type_2}
  features = [features_element, features_element_2]
  requests_element = {'image': image, 'features': features}
  requests = [requests_element]
  gcs_destination = {'uri': output_uri}

  # The max number of responses to output in each JSON file
  batch_size = 2
  output_config = {'gcs_destination': gcs_destination, 'batch_size': batch_size}

  operation = client.async_batch_annotate_images(requests, output_config)

  print('Waiting for operation to complete...')
  response = operation.result()

  # The output is written to GCS with the provided output_uri as prefix
  gcs_output_uri = response.output_config.gcs_destination.uri
  print('Output written to GCS with prefix: {}'.format(gcs_output_uri))

Ruby

Before trying this sample, follow the Ruby setup instructions in the Vision API Quickstart Using Client Libraries . For more information, see the Vision API Ruby API reference documentation .

# Perform async batch image annotation
def sample_async_batch_annotate_images(input_image_uri, output_uri)
  # Instantiate a client
  image_annotator_client = Google::Cloud::Vision::ImageAnnotator.new version: :v1

  # input_image_uri = "gs://cloud-samples-data/vision/label/wakeupcat.jpg"
  # output_uri = "gs://your-bucket/prefix/"
  source = { image_uri: input_image_uri }
  image = { source: source }
  type = :LABEL_DETECTION
  features_element = { type: type }
  type_2 = :IMAGE_PROPERTIES
  features_element_2 = { type: type_2 }
  features = [features_element, features_element_2]
  requests_element = { image: image, features: features }
  requests = [requests_element]
  gcs_destination = { uri: output_uri }

  # The max number of responses to output in each JSON file
  batch_size = 2
  output_config = { gcs_destination: gcs_destination, batch_size: batch_size }

  # Make the long-running operation request
  operation = image_annotator_client.async_batch_annotate_images(requests, output_config)

  # Block until operation complete
  operation.wait_until_done!

  raise operation.results.message if operation.error?

  response = operation.response

  # The output is written to GCS with the provided output_uri as prefix
  gcs_output_uri = response.output_config.gcs_destination.uri
  puts "Output written to GCS with prefix: #{gcs_output_uri}"

end

Response

A successful request returns response JSON files in the Google Cloud Storage bucket you indicated in the code sample. The number of responses per JSON file is dictated by batch_size in the code sample.

The returned response is similar to regular Cloud Vision API feature responses, depending on which features you request for an image.

The following responses show LABEL_DETECTION and TEXT_DETECTION annotations for image1.png, IMAGE_PROPERTIES annotations for image2.jpg, and OBJECT_LOCALIZATION annotations for image3.jpg.

The response also contain a context field showing the file's URI.

offline_batch_output/output-1-to-2.json

{
  "responses": [
    {
      "labelAnnotations": [
        {
          "mid": "/m/07s6nbt",
          "description": "Text",
          "score": 0.93413997,
          "topicality": 0.93413997
        },
        {
          "mid": "/m/0dwx7",
          "description": "Logo",
          "score": 0.8733531,
          "topicality": 0.8733531
        },
        ...
        {
          "mid": "/m/03bxgrp",
          "description": "Company",
          "score": 0.5682425,
          "topicality": 0.5682425
        }
      ],
      "textAnnotations": [
        {
          "locale": "en",
          "description": "Google\n",
          "boundingPoly": {
            "vertices": [
              {
                "x": 72,
                "y": 40
              },
              {
                "x": 613,
                "y": 40
              },
              {
                "x": 613,
                "y": 233
              },
              {
                "x": 72,
                "y": 233
              }
            ]
          }
        },
        ...
                ],
                "blockType": "TEXT"
              }
            ]
          }
        ],
        "text": "Google\n"
      },
      "context": {
        "uri": "gs://cloud-samples-data/vision/document_understanding/image1.png"
      }
    },
    {
      "imagePropertiesAnnotation": {
        "dominantColors": {
          "colors": [
            {
              "color": {
                "red": 229,
                "green": 230,
                "blue": 238
              },
              "score": 0.2744754,
              "pixelFraction": 0.075339235
            },
            ...
            {
              "color": {
                "red": 86,
                "green": 87,
                "blue": 95
              },
              "score": 0.025770646,
              "pixelFraction": 0.13109145
            }
          ]
        }
      },
      "cropHintsAnnotation": {
        "cropHints": [
          {
            "boundingPoly": {
              "vertices": [
                {},
                {
                  "x": 1599
                },
                {
                  "x": 1599,
                  "y": 1199
                },
                {
                  "y": 1199
                }
              ]
            },
            "confidence": 0.79999995,
            "importanceFraction": 1
          }
        ]
      },
      "context": {
        "uri": "gs://cloud-samples-data/vision/document_understanding/image2.jpg"
      }
    }
  ]
}

offline_batch_output/output-3-to-3.json

{
  "responses": [
    {
      "context": {
        "uri": "gs://cloud-samples-data/vision/document_understanding/image3.jpg"
      },
      "localizedObjectAnnotations": [
        {
          "mid": "/m/0bt9lr",
          "name": "Dog",
          "score": 0.9669734,
          "boundingPoly": {
            "normalizedVertices": [
              {
                "x": 0.6035543,
                "y": 0.1357359
              },
              {
                "x": 0.98546547,
                "y": 0.1357359
              },
              {
                "x": 0.98546547,
                "y": 0.98426414
              },
              {
                "x": 0.6035543,
                "y": 0.98426414
              }
            ]
          }
        },
        ...
        {
          "mid": "/m/0jbk",
          "name": "Animal",
          "score": 0.58003056,
          "boundingPoly": {
            "normalizedVertices": [
              {
                "x": 0.014534635,
                "y": 0.1357359
              },
              {
                "x": 0.37197515,
                "y": 0.1357359
              },
              {
                "x": 0.37197515,
                "y": 0.98426414
              },
              {
                "x": 0.014534635,
                "y": 0.98426414
              }
            ]
          }
        }
      ]
    }
  ]
}
Was this page helpful? Let us know how we did:

Send feedback about...

Cloud Vision API Documentation
Need help? Visit our support page.