Skip to content

Commit

Permalink
Beta feature : Vision : PDF/TIFF/GIF document feature detection (#1349)
Browse files Browse the repository at this point in the history
* Beta feature : Vision : PDF/TIFF/GIF document feature detection

* Beta feature : Vision : PDF/TIFF/GIF document feature detection : Add AsyncBatchAnnotateImages sample

* Update after review comments

* Update after review comments
  • Loading branch information
nirupa-kumar authored and nnegrey committed Mar 20, 2019
1 parent e30c014 commit a700bbf
Show file tree
Hide file tree
Showing 6 changed files with 413 additions and 8 deletions.
4 changes: 2 additions & 2 deletions vision/beta/cloud-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
<parent>
<groupId>com.google.cloud.samples</groupId>
<artifactId>shared-configuration</artifactId>
<version>1.0.9</version>
<version>1.0.10</version>
</parent>

<properties>
Expand All @@ -40,7 +40,7 @@
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vision</artifactId>
<version>1.62.0</version>
<version>1.64.0</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
Expand Down
Binary file added vision/beta/cloud-client/resources/kafka.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.vision;

// [START vision_async_batch_annotate_images_beta]
import com.google.api.core.ApiFuture;
import com.google.api.gax.paging.Page;
import com.google.cloud.storage.Blob;
import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.Storage.BlobListOption;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.vision.v1p4beta1.AnnotateImageRequest;
import com.google.cloud.vision.v1p4beta1.AsyncBatchAnnotateImagesRequest;
import com.google.cloud.vision.v1p4beta1.BatchAnnotateImagesResponse.Builder;
import com.google.cloud.vision.v1p4beta1.BatchAnnotateImagesResponse;
import com.google.cloud.vision.v1p4beta1.Feature;
import com.google.cloud.vision.v1p4beta1.Feature.Type;
import com.google.cloud.vision.v1p4beta1.GcsDestination;
import com.google.cloud.vision.v1p4beta1.Image;
import com.google.cloud.vision.v1p4beta1.ImageAnnotatorClient;
import com.google.cloud.vision.v1p4beta1.ImageSource;
import com.google.cloud.vision.v1p4beta1.OutputConfig;

import com.google.longrunning.Operation;
import com.google.protobuf.util.JsonFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AsyncBatchAnnotateImagesGcs {

// Performs asynchronous batch annotation of images on Google Cloud Storage
public static void asyncBatchAnnotateImagesGcs(String gcsSourcePath, String gcsDestinationPath)
throws Exception {
// String gcsSourcePath = "gs://YOUR_BUCKET_ID/path_to_your_data";
// String gcsDestinationPath = "gs://YOUR_BUCKET_ID/path_to_store_annotation";

try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
List<AnnotateImageRequest> requests = new ArrayList<>();

ImageSource imgSource = ImageSource.newBuilder().setImageUri(gcsSourcePath).build();

Image image = Image.newBuilder().setSource(imgSource).build();

// Set the GCS destination path for where to save the results.
GcsDestination gcsDestination =
GcsDestination.newBuilder().setUri(gcsDestinationPath).build();

// Create the configuration for the output with the batch size.
// The batch size sets how many pages should be grouped into each json output file.
OutputConfig outputConfig =
OutputConfig.newBuilder().setGcsDestination(gcsDestination).setBatchSize(2).build();

// Select the Features required by the vision API
Feature features =
Feature.newBuilder()
.setType(Type.LABEL_DETECTION)
.setType(Type.TEXT_DETECTION)
.setType(Type.IMAGE_PROPERTIES)
.build();

// Build the request
AnnotateImageRequest annotateImageRequest =
AnnotateImageRequest.newBuilder().setImage(image).addFeatures(features).build();

requests.add(annotateImageRequest);
AsyncBatchAnnotateImagesRequest request =
AsyncBatchAnnotateImagesRequest.newBuilder()
.addAllRequests(requests)
.setOutputConfig(outputConfig)
.build();

ApiFuture<Operation> future = client.asyncBatchAnnotateImagesCallable().futureCall(request);
// Wait for the request to finish. (The result is not used, since the API saves the result to
// the specified location on GCS.)
Operation response = future.get(180, TimeUnit.SECONDS);

System.out.println("Waiting for the operation to finish.");

// Once the request has completed and the output has been
// written to GCS, we can list all the output files.
Storage storage = StorageOptions.getDefaultInstance().getService();

// Get the destination location from the gcsDestinationPath
Pattern pattern = Pattern.compile("gs://([^/]+)/(.+)");
Matcher matcher = pattern.matcher(gcsDestinationPath);

if (matcher.find()) {
String bucketName = matcher.group(1);
String prefix = matcher.group(2);

// Get the list of objects with the given prefix from the GCS bucket
Bucket bucket = storage.get(bucketName);
Page<Blob> pageList = bucket.list(BlobListOption.prefix(prefix));

Blob firstOutputFile = null;

// List objects with the given prefix.
System.out.println("Output files:");
for (Blob blob : pageList.iterateAll()) {
System.out.println(blob.getName());

// Process the first output file from GCS.
// Since we specified batch size = 2, the first response contains
// the first two image requests
if (firstOutputFile == null) {
firstOutputFile = blob;
}
}

// Get the contents of the file and convert the JSON contents to an
// BatchAnnotateImagesResponse
// object. If the Blob is small read all its content in one request
// (Note: the file is a .json file)
// Storage guide: https://cloud.google.com/storage/docs/downloading-objects
String jsonContents = new String(firstOutputFile.getContent());
Builder builder = BatchAnnotateImagesResponse.newBuilder();
JsonFormat.parser().merge(jsonContents, builder);

// Build the AnnotateFileResponse object
BatchAnnotateImagesResponse batchAnnotateImagesResponse = builder.build();

// Here we print the response for the first image
// The response contains more information:
// annotation/pages/blocks/paragraphs/words/symbols/colors
// including confidence score and bounding boxes
System.out.format("\nResponse: %s\n", batchAnnotateImagesResponse.getResponses(0));

} else {
System.out.println("No MATCH");
}
} catch (Exception e) {
System.out.println("Error during asyncBatchAnnotateImagesGcs: \n" + e.toString());
}
}
}

// [END vision_async_batch_annotate_images_beta]
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.vision;

// [START vision_batch_annotate_files_beta]
import com.google.api.core.ApiFuture;
import com.google.cloud.vision.v1p4beta1.AnnotateFileRequest;
import com.google.cloud.vision.v1p4beta1.AnnotateFileResponse;
import com.google.cloud.vision.v1p4beta1.BatchAnnotateFilesRequest;
import com.google.cloud.vision.v1p4beta1.BatchAnnotateFilesResponse;
import com.google.cloud.vision.v1p4beta1.Block;
import com.google.cloud.vision.v1p4beta1.Feature;
import com.google.cloud.vision.v1p4beta1.Feature.Type;
import com.google.cloud.vision.v1p4beta1.ImageAnnotatorClient;
import com.google.cloud.vision.v1p4beta1.InputConfig;
import com.google.cloud.vision.v1p4beta1.Page;
import com.google.cloud.vision.v1p4beta1.Paragraph;
import com.google.cloud.vision.v1p4beta1.Symbol;
import com.google.cloud.vision.v1p4beta1.TextAnnotation;
import com.google.cloud.vision.v1p4beta1.Word;
import com.google.protobuf.ByteString;

import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DetectBatchAnnotateFiles {

// Performs document feature detection on a local PDF/TIFF/GIF file.
public static void detectBatchAnnotateFiles(String filePath) {
// String filePath = "path/to/your_file";

try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
// Annotate the first two pages and the last one (max 5 pages)
// First page starts at 1, and not 0. Last page is -1.
List<Integer> pages = Arrays.asList(1, 2, -1);
ByteString pdfBytes = ByteString.readFrom(new FileInputStream(filePath));
Feature feat = Feature.newBuilder().setType(Type.DOCUMENT_TEXT_DETECTION).build();
// Other supported mime types : 'image/tiff' or 'image/gif'
InputConfig inputConfig =
InputConfig.newBuilder().setMimeType("application/pdf").setContent(pdfBytes).build();
AnnotateFileRequest request =
AnnotateFileRequest.newBuilder()
.addFeatures(feat)
.setInputConfig(inputConfig)
.addAllPages(pages)
.build();
List<AnnotateFileRequest> requests = new ArrayList<>();
requests.add(request);

BatchAnnotateFilesRequest batchAnnotateFilesRequest =
BatchAnnotateFilesRequest.newBuilder().addAllRequests(requests).build();
ApiFuture<BatchAnnotateFilesResponse> future =
client.batchAnnotateFilesCallable().futureCall(batchAnnotateFilesRequest);
BatchAnnotateFilesResponse response = future.get();

// Getting the first response
AnnotateFileResponse annotateFileResponse = response.getResponses(0);

// For full list of available annotations, see http://g.co/cloud/vision/docs
TextAnnotation textAnnotation = annotateFileResponse.getResponses(0).getFullTextAnnotation();
for (Page page : textAnnotation.getPagesList()) {
String pageText = "";
for (Block block : page.getBlocksList()) {
String blockText = "";
for (Paragraph para : block.getParagraphsList()) {
String paraText = "";
for (Word word : para.getWordsList()) {
String wordText = "";
for (Symbol symbol : word.getSymbolsList()) {
wordText = wordText + symbol.getText();
System.out.format(
"Symbol text: %s (Confidence: %f)\n", symbol.getText(), symbol.getConfidence());
}
System.out.format(
"Word text: %s (Confidence: %f)\n\n", wordText, word.getConfidence());
paraText = String.format("%s %s", paraText, wordText);
}
// Output Example using Paragraph:
System.out.println("\nParagraph: \n" + paraText);
System.out.format("Paragraph Confidence: %f\n", para.getConfidence());
blockText = blockText + paraText;
}
pageText = pageText + blockText;
}
}
System.out.println("\nComplete annotation:");
System.out.println(textAnnotation.getText());

} catch (Exception e) {
System.out.println("Error during detectPdfText: \n" + e.toString());
}
}
}
// [END vision_batch_annotate_files_beta]
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.example.vision;

// [START vision_batch_annotate_files_gcs_beta]
import com.google.api.core.ApiFuture;
import com.google.cloud.vision.v1p4beta1.AnnotateFileRequest;
import com.google.cloud.vision.v1p4beta1.AnnotateFileResponse;
import com.google.cloud.vision.v1p4beta1.BatchAnnotateFilesRequest;
import com.google.cloud.vision.v1p4beta1.BatchAnnotateFilesResponse;
import com.google.cloud.vision.v1p4beta1.Block;
import com.google.cloud.vision.v1p4beta1.Feature;
import com.google.cloud.vision.v1p4beta1.Feature.Type;
import com.google.cloud.vision.v1p4beta1.GcsSource;
import com.google.cloud.vision.v1p4beta1.ImageAnnotatorClient;
import com.google.cloud.vision.v1p4beta1.InputConfig;
import com.google.cloud.vision.v1p4beta1.Page;
import com.google.cloud.vision.v1p4beta1.Paragraph;
import com.google.cloud.vision.v1p4beta1.Symbol;
import com.google.cloud.vision.v1p4beta1.TextAnnotation;
import com.google.cloud.vision.v1p4beta1.Word;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DetectBatchAnnotateFilesGcs {

// Performs document feature detection on a remote PDF/TIFF/GIF file on Google Cloud Storage.
public static void detectBatchAnnotateFilesGcs(String gcsPath) {
// String gcsPath = "gs://Your_BUCKET_ID/path_to_your_data";

try (ImageAnnotatorClient client = ImageAnnotatorClient.create()) {
// Annotate the first two pages and the last one (max 5 pages)
// First page starts at 1, and not 0. Last page is -1.
List<Integer> pages = Arrays.asList(1, 2, -1);
GcsSource gcsSource = GcsSource.newBuilder().setUri(gcsPath).build();
Feature feat = Feature.newBuilder().setType(Type.DOCUMENT_TEXT_DETECTION).build();
//Other supported mime types : 'image/tiff' or 'image/gif'
InputConfig inputConfig =
InputConfig.newBuilder().setMimeType("application/pdf").setGcsSource(gcsSource).build();
AnnotateFileRequest request =
AnnotateFileRequest.newBuilder()
.addFeatures(feat)
.setInputConfig(inputConfig)
.addAllPages(pages)
.build();
List<AnnotateFileRequest> requests = new ArrayList<>();
requests.add(request);

BatchAnnotateFilesRequest batchAnnotateFilesRequest =
BatchAnnotateFilesRequest.newBuilder().addAllRequests(requests).build();
ApiFuture<BatchAnnotateFilesResponse> future =
client.batchAnnotateFilesCallable().futureCall(batchAnnotateFilesRequest);
BatchAnnotateFilesResponse response = future.get();

// Getting the first response
AnnotateFileResponse annotateFileResponse = response.getResponses(0);

// For full list of available annotations, see http://g.co/cloud/vision/docs
TextAnnotation textAnnotation = annotateFileResponse.getResponses(0).getFullTextAnnotation();
for (Page page : textAnnotation.getPagesList()) {
String pageText = "";
for (Block block : page.getBlocksList()) {
String blockText = "";
for (Paragraph para : block.getParagraphsList()) {
String paraText = "";
for (Word word : para.getWordsList()) {
String wordText = "";
for (Symbol symbol : word.getSymbolsList()) {
wordText = wordText + symbol.getText();
System.out.format(
"Symbol text: %s (Confidence: %f)\n", symbol.getText(), symbol.getConfidence());
}
System.out.format(
"Word text: %s (Confidence: %f)\n\n", wordText, word.getConfidence());
paraText = String.format("%s %s", paraText, wordText);
}
// Output Example using Paragraph:
System.out.println("\nParagraph: \n" + paraText);
System.out.format("Paragraph Confidence: %f\n", para.getConfidence());
blockText = blockText + paraText;
}
pageText = pageText + blockText;
}
}
System.out.println("\nComplete annotation:");
System.out.println(textAnnotation.getText());

} catch (Exception e) {
System.out.println("Error during detectPdfText: \n" + e.toString());
}
}
}
// [END vision_batch_annotate_files_gcs_beta]
Loading

1 comment on commit a700bbf

@ghadigaonkarnilesh
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Nirupa Kumar,
I understand you have done changes to read local pdf files. This is really great. However these are in old vision repo (https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/vision/beta/.)

Now Google has recommended below repo
(https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/vision/cloud-client/src/main/java/com/example/vision/Detect.java)

Do you have any plans to do same changes in new Repo as going forward it will be used?

Please sign in to comment.