Given a list of image urls I want to annotate each image, i.e. extract text from each image. For that, I want to use Google Cloud Vision API client library in Java. Here is my pseudocode:

List<String> imageUrls = ...;
List<AnnotateImageRequest> requests = imageUrls.stream()
    .map(convertToRequest)
    .collect(Collectors::toList);
BatchAnnotateImagesResponse batchResponse = imageAnnotatorClient.batchAnnotateImages(requests);

Now from batchResponse I can get a list of AnnotateImageResponse. The questions are, does the number of AnnotateImageResponse correspond to the number of requests? Does the order of responses correspond to the order of requests? Can I safely assume that by doing so

for (int i = 0 ; i < imageUrls.size(); i++) {
    var url = imageUrls.get(i);
    var annotations = batchResponse.getResponses(i).getTextAnnotationsList();
}

I will get annotations for the right image on each iteration of the for loop? This is something that is not clear to me from the documentation.

1

There are 1 best solutions below

0
On

If you check one of the official snippets DetectText.java you will find this interesting comment:

// 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.

This means that once you have the client set it up you can make the calls but as you said it does not mention anything about order. More information about ImageAnnotatorClient can be found, here.

After testing, I found that the batch is the same size and the same order of your provided requests list. You can find details of BatchAnnotateImagesResponse, here.

As a final note, I'm leaving below code with an updated version of function asyncBatchAnnotateImages from the official cloud vision annotation sample which can expand further the handling of image annotations and check how it handles request. (maybe is out of the current scope but I think it can be useful)

public static void asyncBatchAnnotateImages(List<String> uris, String outputUri)
      throws IOException, ExecutionException, InterruptedException {

  try (ImageAnnotatorClient imageAnnotatorClient = ImageAnnotatorClient.create()) {

    List<AnnotateImageRequest> imageRequests = new ArrayList<AnnotateImageRequest>();

    for (String inputImageUri : uris) {
       ImageSource source = ImageSource.newBuilder().setImageUri(inputImageUri).build();
       Image image = Image.newBuilder().setSource(source).build();

       Feature feature = Feature.newBuilder().setType(Feature.Type.LABEL_DETECTION).build();

       AnnotateImageRequest imageRequest = AnnotateImageRequest.newBuilder().setImage(image).addFeatures(feature).build();
       imageRequests.add(imageRequest);
    } 
       
    GcsDestination gcsDestination = GcsDestination.newBuilder().setUri(outputUri).build();
    OutputConfig outputConfig = OutputConfig.newBuilder()
              .setGcsDestination(gcsDestination)
              .setBatchSize(1) // The max number of responses to output in each JSON file
              .build();

    AsyncBatchAnnotateImagesRequest request = AsyncBatchAnnotateImagesRequest.newBuilder()
              .addAllRequests(imageRequests)
              .setOutputConfig(outputConfig)
              .build();


    AsyncBatchAnnotateImagesResponse response = imageAnnotatorClient.asyncBatchAnnotateImagesAsync(request).get();

    String gcsOutputUri = response.getOutputConfig().getGcsDestination().getUri();
    System.out.format("Output written to GCS with prefix: %s%n", gcsOutputUri);
  }
}