-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Changes from 2 commits
c1925cd
c85903a
696a54a
8ca1b5b
bad98d1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 = | ||||||||
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) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/textAnnotation/annotation |
||||||||
|
||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 : | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is already two lines, but easier to read:
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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", | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 = | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/response/future There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Separate In general, it's more readable to break up into two statements on two lines instead of 1 statement over 2 lines. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above example - break up, reuse, and comment for constant. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 : | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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", | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above - align parameters. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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] | ||||||||
} |
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 = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s/response/future There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above - break into response/result There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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] | ||
} | ||
|
There was a problem hiding this comment.
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.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed