Skip to content

Commit 80cc4e5

Browse files
texasmichellennegreyleahecole
authored
video: add auto-generated Logo Recognition Samples (GoogleCloudPlatform#2755)
* Add auto-generated Logo Recognition Samples * Add tests Remove boilerplate Update copyright date Blacken Remove unused imports Shorten docstrings Remove CLI Set defaults in function definition * Edit test video to 3 seconds from 35 Reduce quota usage to allow for parallel tests Retain longer version only for tests that require it * Fix bug Co-authored-by: Noah Negrey <[email protected]> Co-authored-by: Leah E. Cole <[email protected]>
1 parent 8e6d407 commit 80cc4e5

10 files changed

+294
-10
lines changed

video/cloud-client/analyze/README.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ To run this sample:
123123
Google Cloud API.
124124
125125
Usage Examples:
126-
python beta_snippets.py transcription gs://python-docs-samples-tests/video/googlework_short.mp4
127-
python beta_snippets.py video-text-gcs gs://python-docs-samples-tests/video/googlework_short.mp4
126+
python beta_snippets.py transcription gs://python-docs-samples-tests/video/googlework_tiny.mp4
127+
python beta_snippets.py video-text-gcs gs://python-docs-samples-tests/video/googlework_tiny.mp4
128128
python beta_snippets.py track-objects /resources/cat.mp4
129129
130130
positional arguments:

video/cloud-client/analyze/analyze.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
python analyze.py explicit_content \
2626
gs://cloud-samples-data/video/gbikes_dinosaur.mp4
2727
python analyze.py text_gcs \
28-
gs://cloud-samples-data/video/googlework_short.mp4
29-
python analyze.py text_file resources/googlework_short.mp4
28+
gs://cloud-samples-data/video/googlework_tiny.mp4
29+
python analyze.py text_file resources/googlework_tiny.mp4
3030
python analyze.py objects_gcs gs://cloud-samples-data/video/cat.mp4
3131
python analyze.py objects_file resources/cat.mp4
3232
"""

video/cloud-client/analyze/analyze_test.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import analyze
2020

21+
POSSIBLE_TEXTS = ['Google', 'SUR', 'SUR', 'ROTO', 'Vice President', '58oo9',
22+
'LONDRES', 'OMAR', 'PARIS', 'METRO', 'RUE', 'CARLO']
23+
2124

2225
@pytest.mark.slow
2326
def test_analyze_shots(capsys):
@@ -51,9 +54,15 @@ def test_speech_transcription(capsys):
5154
@pytest.mark.slow
5255
def test_detect_text_gcs(capsys):
5356
analyze.video_detect_text_gcs(
54-
'gs://cloud-samples-data/video/googlework_short.mp4')
57+
'gs://cloud-samples-data/video/googlework_tiny.mp4')
5558
out, _ = capsys.readouterr()
56-
assert 'GOOGLE' in out
59+
60+
text_exists = False
61+
out_upper = out.upper()
62+
for possible_text in POSSIBLE_TEXTS:
63+
if possible_text.upper() in out_upper:
64+
text_exists = True
65+
assert text_exists
5766

5867

5968
@pytest.mark.slow

video/cloud-client/analyze/beta_snippets.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
2020
Usage Examples:
2121
python beta_snippets.py transcription \
22-
gs://python-docs-samples-tests/video/googlework_short.mp4
22+
gs://python-docs-samples-tests/video/googlework_tiny.mp4
2323
2424
python beta_snippets.py video-text-gcs \
25-
gs://python-docs-samples-tests/video/googlework_short.mp4
25+
gs://python-docs-samples-tests/video/googlework_tiny.mp4
2626
2727
python beta_snippets.py track-objects resources/cat.mp4
2828

video/cloud-client/analyze/beta_snippets_test.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def test_annotation_to_storage_streaming(capsys, video_path, bucket):
111111

112112
@pytest.mark.slow
113113
def test_detect_text():
114-
in_file = './resources/googlework_short.mp4'
114+
in_file = './resources/googlework_tiny.mp4'
115115
text_annotations = beta_snippets.video_detect_text(in_file)
116116

117117
text_exists = False
@@ -124,7 +124,7 @@ def test_detect_text():
124124

125125
@pytest.mark.slow
126126
def test_detect_text_gcs():
127-
in_file = 'gs://python-docs-samples-tests/video/googlework_short.mp4'
127+
in_file = 'gs://python-docs-samples-tests/video/googlework_tiny.mp4'
128128
text_annotations = beta_snippets.video_detect_text_gcs(in_file)
129129

130130
text_exists = False
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import io
16+
17+
# [START video_detect_logo_beta]
18+
19+
from google.cloud import videointelligence_v1p3beta1
20+
from google.cloud.videointelligence_v1p3beta1 import enums
21+
22+
23+
def sample_annotate_video(local_file_path="resources/googlework_tiny.mp4"):
24+
"""Performs asynchronous video annotation for logo recognition on a local file."""
25+
26+
client = videointelligence_v1p3beta1.VideoIntelligenceServiceClient()
27+
28+
with io.open(local_file_path, "rb") as f:
29+
input_content = f.read()
30+
features_element = enums.Feature.LOGO_RECOGNITION
31+
features = [features_element]
32+
33+
operation = client.annotate_video(input_content=input_content, features=features)
34+
35+
print(u"Waiting for operation to complete...")
36+
response = operation.result()
37+
38+
# Get the first response, since we sent only one video.
39+
annotation_result = response.annotation_results[0]
40+
# Annotations for list of logos detected, tracked and recognized in video.
41+
for logo_recognition_annotation in annotation_result.logo_recognition_annotations:
42+
entity = logo_recognition_annotation.entity
43+
# Opaque entity ID. Some IDs may be available in [Google Knowledge Graph
44+
# Search API](https://developers.google.com/knowledge-graph/).
45+
print(u"Entity Id : {}".format(entity.entity_id))
46+
# Textual description, e.g. `Google`.
47+
print(u"Description : {}".format(entity.description))
48+
# All logo tracks where the recognized logo appears. Each track corresponds
49+
# to one logo instance appearing in consecutive frames.
50+
for track in logo_recognition_annotation.tracks:
51+
# Video segment of a track.
52+
segment = track.segment
53+
segment_start_time_offset = segment.start_time_offset
54+
print(
55+
u"\n\tStart Time Offset : {}.{}".format(
56+
segment_start_time_offset.seconds, segment_start_time_offset.nanos
57+
)
58+
)
59+
segment_end_time_offset = segment.end_time_offset
60+
print(
61+
u"\tEnd Time Offset : {}.{}".format(
62+
segment_end_time_offset.seconds, segment_end_time_offset.nanos
63+
)
64+
)
65+
print(u"\tConfidence : {}".format(track.confidence))
66+
# The object with timestamp and attributes per frame in the track.
67+
for timestamped_object in track.timestamped_objects:
68+
# Normalized Bounding box in a frame, where the object is located.
69+
normalized_bounding_box = timestamped_object.normalized_bounding_box
70+
print(u"\n\t\tLeft : {}".format(normalized_bounding_box.left))
71+
print(u"\t\tTop : {}".format(normalized_bounding_box.top))
72+
print(u"\t\tRight : {}".format(normalized_bounding_box.right))
73+
print(u"\t\tBottom : {}".format(normalized_bounding_box.bottom))
74+
# Optional. The attributes of the object in the bounding box.
75+
for attribute in timestamped_object.attributes:
76+
print(u"\n\t\t\tName : {}".format(attribute.name))
77+
print(u"\t\t\tConfidence : {}".format(attribute.confidence))
78+
print(u"\t\t\tValue : {}".format(attribute.value))
79+
# Optional. Attributes in the track level.
80+
for track_attribute in track.attributes:
81+
print(u"\n\t\tName : {}".format(track_attribute.name))
82+
print(u"\t\tConfidence : {}".format(track_attribute.confidence))
83+
print(u"\t\tValue : {}".format(track_attribute.value))
84+
# All video segments where the recognized logo appears. There might be
85+
# multiple instances of the same logo class appearing in one VideoSegment.
86+
for logo_recognition_annotation_segment in logo_recognition_annotation.segments:
87+
logo_recognition_annotation_segment_start_time_offset = (
88+
logo_recognition_annotation_segment.start_time_offset
89+
)
90+
print(
91+
u"\n\tStart Time Offset : {}.{}".format(
92+
logo_recognition_annotation_segment_start_time_offset.seconds,
93+
logo_recognition_annotation_segment_start_time_offset.nanos,
94+
)
95+
)
96+
logo_recognition_annotation_segment_end_time_offset = (
97+
logo_recognition_annotation_segment.end_time_offset
98+
)
99+
print(
100+
u"\tEnd Time Offset : {}.{}".format(
101+
logo_recognition_annotation_segment_end_time_offset.seconds,
102+
logo_recognition_annotation_segment_end_time_offset.nanos,
103+
)
104+
)
105+
106+
107+
# [END video_detect_logo_beta]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2020 Google
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
17+
import video_detect_logo_beta
18+
19+
RESOURCES = os.path.join(os.path.dirname(__file__), "resources")
20+
21+
22+
def test_sample_annotate_video(capsys):
23+
local_file_path = os.path.join(RESOURCES, "googlework_tiny.mp4")
24+
25+
video_detect_logo_beta.sample_annotate_video(local_file_path=local_file_path)
26+
27+
out, _ = capsys.readouterr()
28+
29+
assert "Description : Google Maps" in out
30+
assert "Confidence" in out
31+
assert "Start Time Offset" in out
32+
assert "End Time Offset" in out
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Copyright 2020 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START video_detect_logo_gcs_beta]
16+
17+
from google.cloud import videointelligence_v1p3beta1
18+
from google.cloud.videointelligence_v1p3beta1 import enums
19+
20+
21+
def sample_annotate_video(
22+
input_uri="gs://cloud-samples-data/video/googlework_tiny.mp4",
23+
):
24+
25+
client = videointelligence_v1p3beta1.VideoIntelligenceServiceClient()
26+
27+
features_element = enums.Feature.LOGO_RECOGNITION
28+
features = [features_element]
29+
30+
operation = client.annotate_video(input_uri=input_uri, features=features)
31+
32+
print(u"Waiting for operation to complete...")
33+
response = operation.result()
34+
35+
# Get the first response, since we sent only one video.
36+
annotation_result = response.annotation_results[0]
37+
# Annotations for list of logos detected, tracked and recognized in video.
38+
for logo_recognition_annotation in annotation_result.logo_recognition_annotations:
39+
entity = logo_recognition_annotation.entity
40+
# Opaque entity ID. Some IDs may be available in [Google Knowledge Graph
41+
# Search API](https://developers.google.com/knowledge-graph/).
42+
print(u"Entity Id : {}".format(entity.entity_id))
43+
# Textual description, e.g. `Google`.
44+
print(u"Description : {}".format(entity.description))
45+
# All logo tracks where the recognized logo appears. Each track corresponds
46+
# to one logo instance appearing in consecutive frames.
47+
for track in logo_recognition_annotation.tracks:
48+
# Video segment of a track.
49+
segment = track.segment
50+
segment_start_time_offset = segment.start_time_offset
51+
print(
52+
u"\n\tStart Time Offset : {}.{}".format(
53+
segment_start_time_offset.seconds, segment_start_time_offset.nanos
54+
)
55+
)
56+
segment_end_time_offset = segment.end_time_offset
57+
print(
58+
u"\tEnd Time Offset : {}.{}".format(
59+
segment_end_time_offset.seconds, segment_end_time_offset.nanos
60+
)
61+
)
62+
print(u"\tConfidence : {}".format(track.confidence))
63+
# The object with timestamp and attributes per frame in the track.
64+
for timestamped_object in track.timestamped_objects:
65+
# Normalized Bounding box in a frame, where the object is located.
66+
normalized_bounding_box = timestamped_object.normalized_bounding_box
67+
print(u"\n\t\tLeft : {}".format(normalized_bounding_box.left))
68+
print(u"\t\tTop : {}".format(normalized_bounding_box.top))
69+
print(u"\t\tRight : {}".format(normalized_bounding_box.right))
70+
print(u"\t\tBottom : {}".format(normalized_bounding_box.bottom))
71+
# Optional. The attributes of the object in the bounding box.
72+
for attribute in timestamped_object.attributes:
73+
print(u"\n\t\t\tName : {}".format(attribute.name))
74+
print(u"\t\t\tConfidence : {}".format(attribute.confidence))
75+
print(u"\t\t\tValue : {}".format(attribute.value))
76+
# Optional. Attributes in the track level.
77+
for track_attribute in track.attributes:
78+
print(u"\n\t\tName : {}".format(track_attribute.name))
79+
print(u"\t\tConfidence : {}".format(track_attribute.confidence))
80+
print(u"\t\tValue : {}".format(track_attribute.value))
81+
# All video segments where the recognized logo appears. There might be
82+
# multiple instances of the same logo class appearing in one VideoSegment.
83+
for logo_recognition_annotation_segment in logo_recognition_annotation.segments:
84+
logo_recognition_annotation_segment_start_time_offset = (
85+
logo_recognition_annotation_segment.start_time_offset
86+
)
87+
print(
88+
u"\n\tStart Time Offset : {}.{}".format(
89+
logo_recognition_annotation_segment_start_time_offset.seconds,
90+
logo_recognition_annotation_segment_start_time_offset.nanos,
91+
)
92+
)
93+
logo_recognition_annotation_segment_end_time_offset = (
94+
logo_recognition_annotation_segment.end_time_offset
95+
)
96+
print(
97+
u"\tEnd Time Offset : {}.{}".format(
98+
logo_recognition_annotation_segment_end_time_offset.seconds,
99+
logo_recognition_annotation_segment_end_time_offset.nanos,
100+
)
101+
)
102+
103+
104+
# [END video_detect_logo_gcs_beta]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2020 Google
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
17+
import video_detect_logo_gcs_beta
18+
19+
RESOURCES = os.path.join(os.path.dirname(__file__), "resources")
20+
21+
22+
def test_sample_annotate_video(capsys):
23+
input_uri = "gs://cloud-samples-data/video/googlework_tiny.mp4"
24+
25+
video_detect_logo_gcs_beta.sample_annotate_video(input_uri=input_uri)
26+
27+
out, _ = capsys.readouterr()
28+
29+
assert "Description : Google Maps" in out
30+
assert "Confidence" in out
31+
assert "Start Time Offset" in out
32+
assert "End Time Offset" in out

0 commit comments

Comments
 (0)