Skip to content

Added beta samples for video object tracking/text detection #1237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 24, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions video/beta/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 @@ -39,7 +39,7 @@
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-video-intelligence</artifactId>
<version>0.56.0-beta</version>
<version>0.67.0-beta</version>
</dependency>

<!-- Test dependencies -->
Expand Down
Binary file added video/beta/resources/cat.mp4
Binary file not shown.
Binary file added video/beta/resources/googlework_short.mp4
Binary file not shown.
2 changes: 1 addition & 1 deletion video/beta/src/main/java/com/example/video/Detect.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public static void speechTranscription(String gcsUri) throws Exception {

System.out.println("Waiting for operation to complete...");
// Display the results
for (VideoAnnotationResults results : response.get(180, TimeUnit.SECONDS)
for (VideoAnnotationResults results : response.get(300, TimeUnit.SECONDS)
.getAnnotationResultsList()) {
for (SpeechTranscription speechTranscription : results.getSpeechTranscriptionsList()) {
try {
Expand Down
168 changes: 168 additions & 0 deletions video/beta/src/main/java/com/example/video/TextDetection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/*
* Copyright 2018 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.video;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.videointelligence.v1p2beta1.AnnotateVideoProgress;
import com.google.cloud.videointelligence.v1p2beta1.AnnotateVideoRequest;
import com.google.cloud.videointelligence.v1p2beta1.AnnotateVideoResponse;
import com.google.cloud.videointelligence.v1p2beta1.Feature;
import com.google.cloud.videointelligence.v1p2beta1.NormalizedVertex;
import com.google.cloud.videointelligence.v1p2beta1.TextAnnotation;
import com.google.cloud.videointelligence.v1p2beta1.TextFrame;
import com.google.cloud.videointelligence.v1p2beta1.TextSegment;
import com.google.cloud.videointelligence.v1p2beta1.VideoAnnotationResults;
import com.google.cloud.videointelligence.v1p2beta1.VideoIntelligenceServiceClient;
import com.google.protobuf.ByteString;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

public class TextDetection {

// [START video_detect_text_beta]
/**
* Detect text in a video.
*
* @param filePath the path to the video file to analyze.
*/
public static VideoAnnotationResults detectText(String filePath) throws Exception {

try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) {

// Read file
Path path = Paths.get(filePath);
byte[] data = Files.readAllBytes(path);

// Create the request
AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder()
.setInputContent(ByteString.copyFrom(data))
.addFeatures(Feature.TEXT_DETECTION)
.build();

// asynchronously perform object tracking on videos
OperationFuture<AnnotateVideoResponse, AnnotateVideoProgress> response =
Copy link
Contributor

Choose a reason for hiding this comment

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

s/response/future

It's a good idea to differentiate between response/futures, since other snippets use response for the Response objects.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

client.annotateVideoAsync(request);

System.out.println("Waiting for operation to complete...");
// The first result is retrieved because a single video was processed.
VideoAnnotationResults result = response.get(300, TimeUnit.SECONDS)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
VideoAnnotationResults result = response.get(300, TimeUnit.SECONDS)
VideoAnnotationResponse response = future.get(300, TimeUnit.SECONDS)
VideoAnnotationResults results = response.getAnnotationResults(0);

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated

.getAnnotationResults(0);

// Get only the first annotation for demo purposes.
TextAnnotation textAnnotation = result.getTextAnnotations(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

s/textAnnotation/annotation


Copy link
Contributor

Choose a reason for hiding this comment

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

Some of these empty lines seem unnecessary - try to only use them between logical groupings of statements to improve readability.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cleaned up

System.out.println("Text: " + textAnnotation.getText());

// Get the first text segment.
TextSegment textSegment = textAnnotation.getSegments(0);

System.out.println(String.format("Start time: %.2f",
textSegment.getSegment().getStartTimeOffset().getSeconds()
Copy link
Contributor

Choose a reason for hiding this comment

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

It's generally a bad practice to use multiple gets in a row, and it's hard to read. Can we use a variable to reuse textSegment.getSegment().getStartTimeOffset(), and add a comment to explain the significance of the constant?

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

+ textSegment.getSegment().getStartTimeOffset().getNanos() / 1e9));

System.out.println(String.format("End time: %.2f",
textSegment.getSegment().getEndTimeOffset().getSeconds()
+ textSegment.getSegment().getEndTimeOffset().getNanos() / 1e9));

System.out.println("Confidence: " + textSegment.getConfidence());

// Show the first result for the first frame in the segment.
TextFrame textFrame = textSegment.getFrames(0);

System.out.println("Time offset for the first frame: "
+ (textFrame.getTimeOffset().getSeconds()
+ textFrame.getTimeOffset().getNanos() / 1e9));

System.out.println("Rotated Bounding Box Vertices:");
for (NormalizedVertex normalizedVertex :
Copy link
Contributor

Choose a reason for hiding this comment

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

This is already two lines, but easier to read:

Suggested change
for (NormalizedVertex normalizedVertex :
List<NormalizedVertex> vertices = textFrame.getRotatedBoundingBox().getVerticesList()
for (NormalizedVertex normalizedVertex : vertices) {

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

textFrame.getRotatedBoundingBox().getVerticesList()) {
System.out.println(String.format("\tVertex.x: %.2f, Vertex.y: %.2f",
Copy link
Contributor

Choose a reason for hiding this comment

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

If you break up parameters, aim for the same indentation. Either break between format( and "\tVertex... or indent normalizedVertex to match.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

normalizedVertex.getX(),
normalizedVertex.getY()));
}

return result;
}
}
// [END video_detect_text_beta]

// [START video_detect_text_gcs_beta]
/**
* Detect Text in a video.
*
* @param gcsUri the path to the video file to analyze.
*/
public static VideoAnnotationResults detectTextGcs(String gcsUri) throws Exception {

try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) {

// Create the request
AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder()
.setInputUri(gcsUri)
.addFeatures(Feature.TEXT_DETECTION)
.build();

// asynchronously perform object tracking on videos
OperationFuture<AnnotateVideoResponse, AnnotateVideoProgress> response =
Copy link
Contributor

Choose a reason for hiding this comment

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

s/response/future

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated

client.annotateVideoAsync(request);

System.out.println("Waiting for operation to complete...");
// The first result is retrieved because a single video was processed.
VideoAnnotationResults result = response.get(300, TimeUnit.SECONDS)
Copy link
Contributor

Choose a reason for hiding this comment

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

Separate response.get from .getAnnotationResults (same as example above)

In general, it's more readable to break up into two statements on two lines instead of 1 statement over 2 lines.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

.getAnnotationResults(0);

// Get only the first annotation for demo purposes.
TextAnnotation textAnnotation = result.getTextAnnotations(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

s/textAnnotation/annotation


System.out.println("Text: " + textAnnotation.getText());

// Get the first text segment.
TextSegment textSegment = textAnnotation.getSegments(0);

System.out.println(String.format("Start time: %.2f",
textSegment.getSegment().getStartTimeOffset().getSeconds()
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above example - break up, reuse, and comment for constant.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

+ textSegment.getSegment().getStartTimeOffset().getNanos() / 1e9));

System.out.println(String.format("End time: %.2f",
textSegment.getSegment().getEndTimeOffset().getSeconds()
+ textSegment.getSegment().getEndTimeOffset().getNanos() / 1e9));

System.out.println("Confidence: " + textSegment.getConfidence());

// Show the first result for the first frame in the segment.
TextFrame textFrame = textSegment.getFrames(0);

System.out.println("Time offset for the first frame: "
+ (textFrame.getTimeOffset().getSeconds()
+ textFrame.getTimeOffset().getNanos() / 1e9));

System.out.println("Rotated Bounding Box Vertices:");
for (NormalizedVertex normalizedVertex :
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above - break into two lines statements over 2 lines instead of 1 statement over 2 lines.

Copy link
Contributor

Choose a reason for hiding this comment

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

Updated

textFrame.getRotatedBoundingBox().getVerticesList()) {
System.out.println(String.format("\tVertex.x: %.2f, Vertex.y: %.2f",
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above - align parameters.

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

normalizedVertex.getX(),
normalizedVertex.getY()));
}

return result;
}
}
// [END video_detect_text_gcs_beta]
}
171 changes: 171 additions & 0 deletions video/beta/src/main/java/com/example/video/TrackObjects.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Copyright 2018 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.video;

import com.google.api.gax.longrunning.OperationFuture;
import com.google.cloud.videointelligence.v1p2beta1.AnnotateVideoProgress;
import com.google.cloud.videointelligence.v1p2beta1.AnnotateVideoRequest;
import com.google.cloud.videointelligence.v1p2beta1.AnnotateVideoResponse;
import com.google.cloud.videointelligence.v1p2beta1.Feature;
import com.google.cloud.videointelligence.v1p2beta1.NormalizedBoundingBox;
import com.google.cloud.videointelligence.v1p2beta1.ObjectTrackingAnnotation;
import com.google.cloud.videointelligence.v1p2beta1.ObjectTrackingFrame;
import com.google.cloud.videointelligence.v1p2beta1.VideoAnnotationResults;
import com.google.cloud.videointelligence.v1p2beta1.VideoIntelligenceServiceClient;
import com.google.cloud.videointelligence.v1p2beta1.VideoSegment;
import com.google.protobuf.ByteString;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.TimeUnit;

public class TrackObjects {

// [START video_object_tracking_beta]
/**
* Track objects in a video.
*
* @param filePath the path to the video file to analyze.
*/
public static VideoAnnotationResults trackObjects(String filePath) throws Exception {

try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) {

// Read file
Path path = Paths.get(filePath);
byte[] data = Files.readAllBytes(path);

// Create the request
AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder()
.setInputContent(ByteString.copyFrom(data))
.addFeatures(Feature.OBJECT_TRACKING)
.setLocationId("us-east1")
.build();

// asynchronously perform object tracking on videos
OperationFuture<AnnotateVideoResponse, AnnotateVideoProgress> response =
Copy link
Contributor

Choose a reason for hiding this comment

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

s/response/future

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

client.annotateVideoAsync(request);

System.out.println("Waiting for operation to complete...");
// The first result is retrieved because a single video was processed.
VideoAnnotationResults result = response.get(1000, TimeUnit.SECONDS)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above - break into response/result

Copy link
Contributor

Choose a reason for hiding this comment

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

Fixed

.getAnnotationResults(0);

// Get only the first annotation for demo purposes.
ObjectTrackingAnnotation objectTrackingAnnotation = result.getObjectAnnotations(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

s/objectTrackingAnnotation/annotation


if (objectTrackingAnnotation.hasEntity()) {
System.out.println("Entity description: "
+ objectTrackingAnnotation.getEntity().getDescription());
System.out.println("Entity id:: " + objectTrackingAnnotation.getEntity().getEntityId());
}

if (objectTrackingAnnotation.hasSegment()) {
VideoSegment videoSegment = objectTrackingAnnotation.getSegment();
System.out.println(String.format("Segment: %.2fs to %.2fs",
videoSegment.getStartTimeOffset().getSeconds()
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above - break, reuse, comment to clarify.

+ videoSegment.getStartTimeOffset().getNanos() / 1e9,
videoSegment.getEndTimeOffset().getSeconds()
+ videoSegment.getEndTimeOffset().getNanos() / 1e9));
}

System.out.println("Confidence: " + objectTrackingAnnotation.getConfidence());


// Here we print only the bounding box of the first frame in this segment.
ObjectTrackingFrame objectTrackingFrame = objectTrackingAnnotation.getFrames(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

s/objectTrackingFrame/frame

Unless it leads to conflicting variable names, dropping adjectives from long class names helps make the code easier to read.

NormalizedBoundingBox normalizedBoundingBox = objectTrackingFrame.getNormalizedBoundingBox();
System.out.println(String.format("Time offset of the first frame: %.2fs",
objectTrackingFrame.getTimeOffset().getSeconds()
+ objectTrackingFrame.getTimeOffset().getNanos() / 1e9));

System.out.println("Bounding box position:");
System.out.println("\tleft: " + normalizedBoundingBox.getLeft());
System.out.println("\ttop: " + normalizedBoundingBox.getTop());
System.out.println("\tright: " + normalizedBoundingBox.getRight());
System.out.println("\tbottom: " + normalizedBoundingBox.getBottom());
return result;
}
}
// [END video_object_tracking_beta]

// [START video_object_tracking_gcs_beta]
/**
* Track objects in a video.
*
* @param gcsUri the path to the video file to analyze.
*/
public static VideoAnnotationResults trackObjectsGcs(String gcsUri) throws Exception {

try (VideoIntelligenceServiceClient client = VideoIntelligenceServiceClient.create()) {

// Create the request
AnnotateVideoRequest request = AnnotateVideoRequest.newBuilder()
.setInputUri(gcsUri)
.addFeatures(Feature.OBJECT_TRACKING)
.setLocationId("us-east1")
.build();

// asynchronously perform object tracking on videos
OperationFuture<AnnotateVideoResponse, AnnotateVideoProgress> response =
Copy link
Contributor

Choose a reason for hiding this comment

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

s/response/future

client.annotateVideoAsync(request);

System.out.println("Waiting for operation to complete...");
// The first result is retrieved because a single video was processed.
VideoAnnotationResults result = response.get(1000, TimeUnit.SECONDS)
Copy link
Contributor

Choose a reason for hiding this comment

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

separate response/future

.getAnnotationResults(0);

// Get only the first annotation for demo purposes.
ObjectTrackingAnnotation objectTrackingAnnotation = result.getObjectAnnotations(0);

if (objectTrackingAnnotation.hasEntity()) {
System.out.println("Entity description: "
+ objectTrackingAnnotation.getEntity().getDescription());
System.out.println("Entity id:: " + objectTrackingAnnotation.getEntity().getEntityId());
}

if (objectTrackingAnnotation.hasSegment()) {
VideoSegment videoSegment = objectTrackingAnnotation.getSegment();
System.out.println(String.format("Segment: %.2fs to %.2fs",
videoSegment.getStartTimeOffset().getSeconds()
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above - break up, reuse, comment for constant.

+ videoSegment.getStartTimeOffset().getNanos() / 1e9,
videoSegment.getEndTimeOffset().getSeconds()
+ videoSegment.getEndTimeOffset().getNanos() / 1e9));
}

System.out.println("Confidence: " + objectTrackingAnnotation.getConfidence());


// Here we print only the bounding box of the first frame in this segment.
ObjectTrackingFrame objectTrackingFrame = objectTrackingAnnotation.getFrames(0);
NormalizedBoundingBox normalizedBoundingBox = objectTrackingFrame.getNormalizedBoundingBox();
System.out.println(String.format("Time offset of the first frame: %.2fs",
objectTrackingFrame.getTimeOffset().getSeconds()
+ objectTrackingFrame.getTimeOffset().getNanos() / 1e9));

System.out.println("Bounding box position:");
System.out.println("\tleft: " + normalizedBoundingBox.getLeft());
System.out.println("\ttop: " + normalizedBoundingBox.getTop());
System.out.println("\tright: " + normalizedBoundingBox.getRight());
System.out.println("\tbottom: " + normalizedBoundingBox.getBottom());
return result;
}
}
// [END video_object_tracking_gcs_beta]
}

Loading