diff --git a/video/cloud-client/analyze/README.rst b/video/cloud-client/analyze/README.rst index f5fc7437890..fd2b90e9d0f 100644 --- a/video/cloud-client/analyze/README.rst +++ b/video/cloud-client/analyze/README.rst @@ -123,8 +123,8 @@ To run this sample: Google Cloud API. Usage Examples: - python beta_snippets.py transcription gs://python-docs-samples-tests/video/googlework_short.mp4 - python beta_snippets.py video-text-gcs gs://python-docs-samples-tests/video/googlework_short.mp4 + python beta_snippets.py transcription gs://python-docs-samples-tests/video/googlework_tiny.mp4 + python beta_snippets.py video-text-gcs gs://python-docs-samples-tests/video/googlework_tiny.mp4 python beta_snippets.py track-objects /resources/cat.mp4 positional arguments: diff --git a/video/cloud-client/analyze/analyze.py b/video/cloud-client/analyze/analyze.py index e86193c10e4..3ceef445038 100644 --- a/video/cloud-client/analyze/analyze.py +++ b/video/cloud-client/analyze/analyze.py @@ -25,8 +25,8 @@ python analyze.py explicit_content \ gs://cloud-samples-data/video/gbikes_dinosaur.mp4 python analyze.py text_gcs \ - gs://cloud-samples-data/video/googlework_short.mp4 - python analyze.py text_file resources/googlework_short.mp4 + gs://cloud-samples-data/video/googlework_tiny.mp4 + python analyze.py text_file resources/googlework_tiny.mp4 python analyze.py objects_gcs gs://cloud-samples-data/video/cat.mp4 python analyze.py objects_file resources/cat.mp4 """ diff --git a/video/cloud-client/analyze/analyze_test.py b/video/cloud-client/analyze/analyze_test.py index 36288e8e9db..7624c2dfd6c 100644 --- a/video/cloud-client/analyze/analyze_test.py +++ b/video/cloud-client/analyze/analyze_test.py @@ -18,6 +18,9 @@ import analyze +POSSIBLE_TEXTS = ['Google', 'SUR', 'SUR', 'ROTO', 'Vice President', '58oo9', + 'LONDRES', 'OMAR', 'PARIS', 'METRO', 'RUE', 'CARLO'] + @pytest.mark.slow def test_analyze_shots(capsys): @@ -51,9 +54,15 @@ def test_speech_transcription(capsys): @pytest.mark.slow def test_detect_text_gcs(capsys): analyze.video_detect_text_gcs( - 'gs://cloud-samples-data/video/googlework_short.mp4') + 'gs://cloud-samples-data/video/googlework_tiny.mp4') out, _ = capsys.readouterr() - assert 'GOOGLE' in out + + text_exists = False + out_upper = out.upper() + for possible_text in POSSIBLE_TEXTS: + if possible_text.upper() in out_upper: + text_exists = True + assert text_exists @pytest.mark.slow diff --git a/video/cloud-client/analyze/beta_snippets.py b/video/cloud-client/analyze/beta_snippets.py index 1b11020e7d1..3738a568949 100644 --- a/video/cloud-client/analyze/beta_snippets.py +++ b/video/cloud-client/analyze/beta_snippets.py @@ -19,10 +19,10 @@ Usage Examples: python beta_snippets.py transcription \ - gs://python-docs-samples-tests/video/googlework_short.mp4 + gs://python-docs-samples-tests/video/googlework_tiny.mp4 python beta_snippets.py video-text-gcs \ - gs://python-docs-samples-tests/video/googlework_short.mp4 + gs://python-docs-samples-tests/video/googlework_tiny.mp4 python beta_snippets.py track-objects resources/cat.mp4 diff --git a/video/cloud-client/analyze/beta_snippets_test.py b/video/cloud-client/analyze/beta_snippets_test.py index 5652c9e5d0c..9a52dd1ff2e 100644 --- a/video/cloud-client/analyze/beta_snippets_test.py +++ b/video/cloud-client/analyze/beta_snippets_test.py @@ -111,7 +111,7 @@ def test_annotation_to_storage_streaming(capsys, video_path, bucket): @pytest.mark.slow def test_detect_text(): - in_file = './resources/googlework_short.mp4' + in_file = './resources/googlework_tiny.mp4' text_annotations = beta_snippets.video_detect_text(in_file) text_exists = False @@ -124,7 +124,7 @@ def test_detect_text(): @pytest.mark.slow def test_detect_text_gcs(): - in_file = 'gs://python-docs-samples-tests/video/googlework_short.mp4' + in_file = 'gs://python-docs-samples-tests/video/googlework_tiny.mp4' text_annotations = beta_snippets.video_detect_text_gcs(in_file) text_exists = False diff --git a/video/cloud-client/analyze/resources/googlework_tiny.mp4 b/video/cloud-client/analyze/resources/googlework_tiny.mp4 new file mode 100644 index 00000000000..7c6cbc31f1b Binary files /dev/null and b/video/cloud-client/analyze/resources/googlework_tiny.mp4 differ diff --git a/video/cloud-client/analyze/video_detect_logo_beta.py b/video/cloud-client/analyze/video_detect_logo_beta.py new file mode 100644 index 00000000000..3ec90bd242d --- /dev/null +++ b/video/cloud-client/analyze/video_detect_logo_beta.py @@ -0,0 +1,107 @@ +# Copyright 2020 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 +# +# https://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. + +import io + +# [START video_detect_logo_beta] + +from google.cloud import videointelligence_v1p3beta1 +from google.cloud.videointelligence_v1p3beta1 import enums + + +def sample_annotate_video(local_file_path="resources/googlework_tiny.mp4"): + """Performs asynchronous video annotation for logo recognition on a local file.""" + + client = videointelligence_v1p3beta1.VideoIntelligenceServiceClient() + + with io.open(local_file_path, "rb") as f: + input_content = f.read() + features_element = enums.Feature.LOGO_RECOGNITION + features = [features_element] + + operation = client.annotate_video(input_content=input_content, features=features) + + print(u"Waiting for operation to complete...") + response = operation.result() + + # Get the first response, since we sent only one video. + annotation_result = response.annotation_results[0] + # Annotations for list of logos detected, tracked and recognized in video. + for logo_recognition_annotation in annotation_result.logo_recognition_annotations: + entity = logo_recognition_annotation.entity + # Opaque entity ID. Some IDs may be available in [Google Knowledge Graph + # Search API](https://developers.google.com/knowledge-graph/). + print(u"Entity Id : {}".format(entity.entity_id)) + # Textual description, e.g. `Google`. + print(u"Description : {}".format(entity.description)) + # All logo tracks where the recognized logo appears. Each track corresponds + # to one logo instance appearing in consecutive frames. + for track in logo_recognition_annotation.tracks: + # Video segment of a track. + segment = track.segment + segment_start_time_offset = segment.start_time_offset + print( + u"\n\tStart Time Offset : {}.{}".format( + segment_start_time_offset.seconds, segment_start_time_offset.nanos + ) + ) + segment_end_time_offset = segment.end_time_offset + print( + u"\tEnd Time Offset : {}.{}".format( + segment_end_time_offset.seconds, segment_end_time_offset.nanos + ) + ) + print(u"\tConfidence : {}".format(track.confidence)) + # The object with timestamp and attributes per frame in the track. + for timestamped_object in track.timestamped_objects: + # Normalized Bounding box in a frame, where the object is located. + normalized_bounding_box = timestamped_object.normalized_bounding_box + print(u"\n\t\tLeft : {}".format(normalized_bounding_box.left)) + print(u"\t\tTop : {}".format(normalized_bounding_box.top)) + print(u"\t\tRight : {}".format(normalized_bounding_box.right)) + print(u"\t\tBottom : {}".format(normalized_bounding_box.bottom)) + # Optional. The attributes of the object in the bounding box. + for attribute in timestamped_object.attributes: + print(u"\n\t\t\tName : {}".format(attribute.name)) + print(u"\t\t\tConfidence : {}".format(attribute.confidence)) + print(u"\t\t\tValue : {}".format(attribute.value)) + # Optional. Attributes in the track level. + for track_attribute in track.attributes: + print(u"\n\t\tName : {}".format(track_attribute.name)) + print(u"\t\tConfidence : {}".format(track_attribute.confidence)) + print(u"\t\tValue : {}".format(track_attribute.value)) + # All video segments where the recognized logo appears. There might be + # multiple instances of the same logo class appearing in one VideoSegment. + for logo_recognition_annotation_segment in logo_recognition_annotation.segments: + logo_recognition_annotation_segment_start_time_offset = ( + logo_recognition_annotation_segment.start_time_offset + ) + print( + u"\n\tStart Time Offset : {}.{}".format( + logo_recognition_annotation_segment_start_time_offset.seconds, + logo_recognition_annotation_segment_start_time_offset.nanos, + ) + ) + logo_recognition_annotation_segment_end_time_offset = ( + logo_recognition_annotation_segment.end_time_offset + ) + print( + u"\tEnd Time Offset : {}.{}".format( + logo_recognition_annotation_segment_end_time_offset.seconds, + logo_recognition_annotation_segment_end_time_offset.nanos, + ) + ) + + +# [END video_detect_logo_beta] diff --git a/video/cloud-client/analyze/video_detect_logo_beta_test.py b/video/cloud-client/analyze/video_detect_logo_beta_test.py new file mode 100644 index 00000000000..1605fc499c9 --- /dev/null +++ b/video/cloud-client/analyze/video_detect_logo_beta_test.py @@ -0,0 +1,32 @@ +# Copyright 2020 Google +# +# 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. + +import os + +import video_detect_logo_beta + +RESOURCES = os.path.join(os.path.dirname(__file__), "resources") + + +def test_sample_annotate_video(capsys): + local_file_path = os.path.join(RESOURCES, "googlework_tiny.mp4") + + video_detect_logo_beta.sample_annotate_video(local_file_path=local_file_path) + + out, _ = capsys.readouterr() + + assert "Description : Google Maps" in out + assert "Confidence" in out + assert "Start Time Offset" in out + assert "End Time Offset" in out diff --git a/video/cloud-client/analyze/video_detect_logo_gcs_beta.py b/video/cloud-client/analyze/video_detect_logo_gcs_beta.py new file mode 100644 index 00000000000..47ccddd8923 --- /dev/null +++ b/video/cloud-client/analyze/video_detect_logo_gcs_beta.py @@ -0,0 +1,104 @@ +# Copyright 2020 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 +# +# https://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. + +# [START video_detect_logo_gcs_beta] + +from google.cloud import videointelligence_v1p3beta1 +from google.cloud.videointelligence_v1p3beta1 import enums + + +def sample_annotate_video( + input_uri="gs://cloud-samples-data/video/googlework_tiny.mp4", +): + + client = videointelligence_v1p3beta1.VideoIntelligenceServiceClient() + + features_element = enums.Feature.LOGO_RECOGNITION + features = [features_element] + + operation = client.annotate_video(input_uri=input_uri, features=features) + + print(u"Waiting for operation to complete...") + response = operation.result() + + # Get the first response, since we sent only one video. + annotation_result = response.annotation_results[0] + # Annotations for list of logos detected, tracked and recognized in video. + for logo_recognition_annotation in annotation_result.logo_recognition_annotations: + entity = logo_recognition_annotation.entity + # Opaque entity ID. Some IDs may be available in [Google Knowledge Graph + # Search API](https://developers.google.com/knowledge-graph/). + print(u"Entity Id : {}".format(entity.entity_id)) + # Textual description, e.g. `Google`. + print(u"Description : {}".format(entity.description)) + # All logo tracks where the recognized logo appears. Each track corresponds + # to one logo instance appearing in consecutive frames. + for track in logo_recognition_annotation.tracks: + # Video segment of a track. + segment = track.segment + segment_start_time_offset = segment.start_time_offset + print( + u"\n\tStart Time Offset : {}.{}".format( + segment_start_time_offset.seconds, segment_start_time_offset.nanos + ) + ) + segment_end_time_offset = segment.end_time_offset + print( + u"\tEnd Time Offset : {}.{}".format( + segment_end_time_offset.seconds, segment_end_time_offset.nanos + ) + ) + print(u"\tConfidence : {}".format(track.confidence)) + # The object with timestamp and attributes per frame in the track. + for timestamped_object in track.timestamped_objects: + # Normalized Bounding box in a frame, where the object is located. + normalized_bounding_box = timestamped_object.normalized_bounding_box + print(u"\n\t\tLeft : {}".format(normalized_bounding_box.left)) + print(u"\t\tTop : {}".format(normalized_bounding_box.top)) + print(u"\t\tRight : {}".format(normalized_bounding_box.right)) + print(u"\t\tBottom : {}".format(normalized_bounding_box.bottom)) + # Optional. The attributes of the object in the bounding box. + for attribute in timestamped_object.attributes: + print(u"\n\t\t\tName : {}".format(attribute.name)) + print(u"\t\t\tConfidence : {}".format(attribute.confidence)) + print(u"\t\t\tValue : {}".format(attribute.value)) + # Optional. Attributes in the track level. + for track_attribute in track.attributes: + print(u"\n\t\tName : {}".format(track_attribute.name)) + print(u"\t\tConfidence : {}".format(track_attribute.confidence)) + print(u"\t\tValue : {}".format(track_attribute.value)) + # All video segments where the recognized logo appears. There might be + # multiple instances of the same logo class appearing in one VideoSegment. + for logo_recognition_annotation_segment in logo_recognition_annotation.segments: + logo_recognition_annotation_segment_start_time_offset = ( + logo_recognition_annotation_segment.start_time_offset + ) + print( + u"\n\tStart Time Offset : {}.{}".format( + logo_recognition_annotation_segment_start_time_offset.seconds, + logo_recognition_annotation_segment_start_time_offset.nanos, + ) + ) + logo_recognition_annotation_segment_end_time_offset = ( + logo_recognition_annotation_segment.end_time_offset + ) + print( + u"\tEnd Time Offset : {}.{}".format( + logo_recognition_annotation_segment_end_time_offset.seconds, + logo_recognition_annotation_segment_end_time_offset.nanos, + ) + ) + + +# [END video_detect_logo_gcs_beta] diff --git a/video/cloud-client/analyze/video_detect_logo_gcs_beta_test.py b/video/cloud-client/analyze/video_detect_logo_gcs_beta_test.py new file mode 100644 index 00000000000..7c6c6530327 --- /dev/null +++ b/video/cloud-client/analyze/video_detect_logo_gcs_beta_test.py @@ -0,0 +1,32 @@ +# Copyright 2020 Google +# +# 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. + +import os + +import video_detect_logo_gcs_beta + +RESOURCES = os.path.join(os.path.dirname(__file__), "resources") + + +def test_sample_annotate_video(capsys): + input_uri = "gs://cloud-samples-data/video/googlework_tiny.mp4" + + video_detect_logo_gcs_beta.sample_annotate_video(input_uri=input_uri) + + out, _ = capsys.readouterr() + + assert "Description : Google Maps" in out + assert "Confidence" in out + assert "Start Time Offset" in out + assert "End Time Offset" in out