diff --git a/vision/cloud-client/product_search/import_product_sets.py b/vision/cloud-client/product_search/import_product_sets.py new file mode 100755 index 00000000000..e3c3f758842 --- /dev/null +++ b/vision/cloud-client/product_search/import_product_sets.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# 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. + +"""This application demonstrates how to perform import product sets operations +on Product set in Cloud Vision Product Search. + +For more information, see the tutorial page at +https://cloud.google.com/vision/product-search/docs/ +""" + +# [START product_search_import] +import argparse + +from google.cloud import vision_v1p3beta1 as vision +# [END product_search_import] + + +# [START product_search_import_product_sets] +def import_product_sets(project_id, location, gcs_uri): + """Import images of different products in the product set. + Args: + project_id: Id of the project. + location: A compute region name. + gcs_uri: Google Cloud Storage URI. + Target files must be in Product Search CSV format. + """ + client = vision.ProductSearchClient() + + # A resource that represents Google Cloud Platform location. + location_path = client.location_path( + project=project_id, location=location) + + # Set the input configuration along with Google Cloud Storage URI + gcs_source = vision.types.ImportProductSetsGcsSource( + csv_file_uri=gcs_uri) + input_config = vision.types.ImportProductSetsInputConfig( + gcs_source=gcs_source) + + # Import the product sets from the input URI. + response = client.import_product_sets( + parent=location_path, input_config=input_config) + + print('Processing operation name: {}'.format(response.operation.name)) + # synchronous check of operation status + result = response.result() + print('Processing done.') + + for i, status in enumerate(result.statuses): + print('Status of processing line {} of the csv: {}'.format( + i, status)) + # Check the status of reference image + # `0` is the code for OK in google.rpc.Code. + if status.code == 0: + reference_image = result.reference_images[i] + print(reference_image) + else: + print('Status code not OK: {}'.format(status.message)) +# [END product_search_import_product_sets] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + subparsers = parser.add_subparsers(dest='command') + parser.add_argument( + '--project_id', + help='Project id. Required', + required=True) + parser.add_argument( + '--location', + help='Compute region name', + default='us-west1') + + import_product_sets_parser = subparsers.add_parser( + 'import_product_sets', help=import_product_sets.__doc__) + import_product_sets_parser.add_argument('gcs_uri') + + args = parser.parse_args() + + if args.command == 'import_product_sets': + import_product_sets(args.project_id, args.location, args.gcs_uri) diff --git a/vision/cloud-client/product_search/import_product_sets_test.py b/vision/cloud-client/product_search/import_product_sets_test.py new file mode 100644 index 00000000000..ac2dcae4bf0 --- /dev/null +++ b/vision/cloud-client/product_search/import_product_sets_test.py @@ -0,0 +1,93 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 pytest + +from import_product_sets import import_product_sets +from product_in_product_set_management import list_products_in_product_set +from product_management import delete_product, list_products +from product_set_management import delete_product_set, list_product_sets +from reference_image_management import list_reference_images + + +PROJECT_ID = os.getenv('GCLOUD_PROJECT') +LOCATION = 'us-west1' + +GCS_URI = 'gs://python-docs-samples-tests/product_search/product_sets.csv' +PRODUCT_SET_DISPLAY_NAME = 'fake_product_set_display_name_for_testing' +PRODUCT_SET_ID = 'fake_product_set_id_for_testing' +PRODUCT_ID_1 = 'fake_product_id_for_testing_1' +PRODUCT_ID_2 = 'fake_product_id_for_testing_2' +IMAGE_URI_1 = 'shoes_1.jpg' +IMAGE_URI_2 = 'shoes_2.jpg' + + +@pytest.fixture +def teardown(): + # no set up, tear down only + yield None + + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID_1) + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID_2) + delete_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + + +def test_import_product_sets(capsys, teardown): + list_product_sets(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_SET_ID not in out + + list_products(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 not in out + assert PRODUCT_ID_2 not in out + + list_products_in_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 not in out + assert PRODUCT_ID_2 not in out + + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID_1) + out, _ = capsys.readouterr() + assert IMAGE_URI_1 not in out + + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID_2) + out, _ = capsys.readouterr() + assert IMAGE_URI_2 not in out + + import_product_sets(PROJECT_ID, LOCATION, GCS_URI) + + list_product_sets(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_SET_ID in out + + list_products(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 in out + assert PRODUCT_ID_2 in out + + list_products_in_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 in out + assert PRODUCT_ID_2 in out + + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID_1) + out, _ = capsys.readouterr() + assert IMAGE_URI_1 in out + + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID_2) + out, _ = capsys.readouterr() + assert IMAGE_URI_2 in out diff --git a/vision/cloud-client/product_search/product_in_product_set_management.py b/vision/cloud-client/product_search/product_in_product_set_management.py new file mode 100755 index 00000000000..a126478176b --- /dev/null +++ b/vision/cloud-client/product_search/product_in_product_set_management.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# 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. + +"""This application demonstrates how to perform create operations +on Product set in Cloud Vision Product Search. + +For more information, see the tutorial page at +https://cloud.google.com/vision/product-search/docs/ +""" + +# [START product_search_import] +import argparse + +from google.cloud import vision_v1p3beta1 as vision +# [END product_search_import] + + +# [START product_search_add_product_to_product_set] +def add_product_to_product_set( + project_id, location, product_id, product_set_id): + """Add a product to a product set. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + product_set_id: Id of the product set. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product set. + product_set_path = client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + + # Get the full path of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # Add the product to the product set. + client.add_product_to_product_set( + name=product_set_path, product=product_path) + print('Product added to product set.') +# [END product_search_add_product_to_product_set] + + +# [START product_search_list_products_in_product_set] +def list_products_in_product_set( + project_id, location, product_set_id): + """List all products in a product set. + Args: + project_id: Id of the project. + location: A compute region name. + product_set_id: Id of the product set. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product set. + product_set_path = client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + + # List all the products available in the product set. + products = client.list_products_in_product_set(name=product_set_path) + + # Display the product information. + for product in products: + print('Product name: {}'.format(product.name)) + print('Product id: {}'.format(product.name.split('/')[-1])) + print('Product display name: {}'.format(product.display_name)) + print('Product description: {}'.format(product.description)) + print('Product category: {}'.format(product.product_category)) + print('Product labels: {}'.format(product.product_labels)) +# [END product_search_list_products_in_product_set] + + +# [START product_search_remove_product_from_product_set] +def remove_product_from_product_set( + project_id, location, product_id, product_set_id): + """Remove a product from a product set. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + product_set_id: Id of the product set. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product set. + product_set_path = client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + + # Get the full path of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # Remove the product from the product set. + client.remove_product_from_product_set( + name=product_set_path, product=product_path) + print('Product removed from product set.') +# [END product_search_remove_product_from_product_set] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + subparsers = parser.add_subparsers(dest='command') + parser.add_argument( + '--project_id', + help='Project id. Required', + required=True) + parser.add_argument( + '--location', + help='Compute region name', + default='us-west1') + + add_product_to_product_set_parser = subparsers.add_parser( + 'add_product_to_product_set', help=add_product_to_product_set.__doc__) + add_product_to_product_set_parser.add_argument('product_id') + add_product_to_product_set_parser.add_argument('product_set_id') + + list_products_in_product_set_parser = subparsers.add_parser( + 'list_products_in_product_set', + help=list_products_in_product_set.__doc__) + list_products_in_product_set_parser.add_argument('product_set_id') + + remove_product_from_product_set_parser = subparsers.add_parser( + 'remove_product_from_product_set', + help=remove_product_from_product_set.__doc__) + remove_product_from_product_set_parser.add_argument('product_id') + remove_product_from_product_set_parser.add_argument('product_set_id') + + args = parser.parse_args() + + if args.command == 'add_product_to_product_set': + add_product_to_product_set( + args.project_id, args.location, args.product_id, + args.product_set_id) + elif args.command == 'list_products_in_product_set': + list_products_in_product_set( + args.project_id, args.location, args.product_set_id) + elif args.command == 'remove_product_from_product_set': + remove_product_from_product_set( + args.project_id, args.location, args.product_id, + args.product_set_id) diff --git a/vision/cloud-client/product_search/product_in_product_set_management_test.py b/vision/cloud-client/product_search/product_in_product_set_management_test.py new file mode 100644 index 00000000000..cae2d2caa02 --- /dev/null +++ b/vision/cloud-client/product_search/product_in_product_set_management_test.py @@ -0,0 +1,77 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 pytest + +from product_in_product_set_management import ( + add_product_to_product_set, list_products_in_product_set, + remove_product_from_product_set) +from product_management import create_product, delete_product +from product_set_management import ( + create_product_set, delete_product_set) + + +PROJECT_ID = os.getenv('GCLOUD_PROJECT') +LOCATION = 'us-west1' + +PRODUCT_SET_DISPLAY_NAME = 'fake_product_set_display_name_for_testing' +PRODUCT_SET_ID = 'fake_product_set_id_for_testing' + +PRODUCT_DISPLAY_NAME = 'fake_product_display_name_for_testing' +PRODUCT_CATEGORY = 'homegoods' +PRODUCT_ID = 'fake_product_id_for_testing' + + +@pytest.fixture +def product_and_product_set(): + # set up + create_product_set( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, PRODUCT_SET_DISPLAY_NAME) + create_product( + PROJECT_ID, LOCATION, PRODUCT_ID, + PRODUCT_DISPLAY_NAME, PRODUCT_CATEGORY) + + yield None + + # tear down + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) + delete_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + + +def test_add_product_to_product_set(capsys, product_and_product_set): + list_products_in_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + out, _ = capsys.readouterr() + assert PRODUCT_ID not in out + + add_product_to_product_set( + PROJECT_ID, LOCATION, PRODUCT_ID, PRODUCT_SET_ID) + list_products_in_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + out, _ = capsys.readouterr() + assert PRODUCT_ID in out + + +def test_remove_product_from_product_set(capsys, product_and_product_set): + add_product_to_product_set( + PROJECT_ID, LOCATION, PRODUCT_ID, PRODUCT_SET_ID) + list_products_in_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + out, _ = capsys.readouterr() + assert PRODUCT_ID in out + + remove_product_from_product_set( + PROJECT_ID, LOCATION, PRODUCT_ID, PRODUCT_SET_ID) + list_products_in_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + out, _ = capsys.readouterr() + assert PRODUCT_ID not in out diff --git a/vision/cloud-client/product_search/product_management.py b/vision/cloud-client/product_search/product_management.py new file mode 100755 index 00000000000..5bb25839173 --- /dev/null +++ b/vision/cloud-client/product_search/product_management.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# 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. + +"""This application demonstrates how to perform basic operations on Product +in Cloud Vision Product Search. + +For more information, see the tutorial page at +https://cloud.google.com/vision/product-search/docs/ +""" + +# [START product_search_import] +import argparse + +from google.cloud import vision_v1p3beta1 as vision +# [END product_search_import] + + +# [START product_search_create_product] +def create_product( + project_id, location, product_id, product_display_name, + product_category): + """Create one product. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + product_display_name: Display name of the product. + product_category: Category of the product. + """ + client = vision.ProductSearchClient() + + # A resource that represents Google Cloud Platform location. + location_path = client.location_path(project=project_id, location=location) + + # Create a product with the product specification in the region. + # Set product name and product display name. + product = vision.types.Product( + display_name=product_display_name, + product_category=product_category) + + # The response is the product with the `name` field populated. + response = client.create_product( + parent=location_path, + product=product, + product_id=product_id) + + # Display the product information. + print('Product name: {}'.format(response.name)) +# [END product_search_create_product] + + +# [START product_search_list_products] +def list_products(project_id, location): + """List all products. + Args: + project_id: Id of the project. + location: A compute region name. + """ + client = vision.ProductSearchClient() + + # A resource that represents Google Cloud Platform location. + location_path = client.location_path(project=project_id, location=location) + + # List all the products available in the region. + products = client.list_products(parent=location_path) + + # Display the product information. + for product in products: + print('Product name: {}'.format(product.name)) + print('Product id: {}'.format(product.name.split('/')[-1])) + print('Product display name: {}'.format(product.display_name)) + print('Product description: {}'.format(product.description)) + print('Product category: {}'.format(product.product_category)) + print('Product labels: {}\n'.format(product.product_labels)) +# [END product_search_list_products] + + +# [START product_search_get_product] +def get_product(project_id, location, product_id): + """Get information about a product. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # Get complete detail of the product. + product = client.get_product(name=product_path) + + # Display the product information. + print('Product name: {}'.format(product.name)) + print('Product id: {}'.format(product.name.split('/')[-1])) + print('Product display name: {}'.format(product.display_name)) + print('Product description: {}'.format(product.description)) + print('Product category: {}'.format(product.product_category)) + print('Product labels: {}'.format(product.product_labels)) +# [END product_search_get_product] + + +# [START product_search_update_product_labels] +def update_product_labels( + project_id, location, product_id, key, value): + """Update the product labels. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + key: The key of the label. + value: The value of the label. + """ + client = vision.ProductSearchClient() + + # Get the name of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # Set product name, product label and product display name. + # Multiple labels are also supported. + key_value = vision.types.Product.KeyValue(key=key, value=value) + product = vision.types.Product( + name=product_path, + product_labels=[key_value]) + + # Updating only the product_labels field here. + update_mask = vision.types.FieldMask(paths=['product_labels']) + + # This overwrites the product_labels. + updated_product = client.update_product( + product=product, update_mask=update_mask) + + # Display the updated product information. + print('Product name: {}'.format(updated_product.name)) + print('Updated product labels: {}'.format(product.product_labels)) +# [END product_search_update_product_labels] + + +# [START product_search_delete_product] +def delete_product(project_id, location, product_id): + """Delete the product and all its reference images. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # Delete a product. + client.delete_product(name=product_path) + print('Product deleted.') +# [END product_search_delete_product] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument( + '--project_id', + help='Project id. Required', + required=True) + parser.add_argument( + '--location', + help='Compute region name', + default='us-west1') + + subparsers = parser.add_subparsers(dest='command') + + create_product_parser = subparsers.add_parser( + 'create_product', help=create_product.__doc__) + create_product_parser.add_argument('product_id') + create_product_parser.add_argument('product_display_name') + create_product_parser.add_argument('product_category') + + list_products_parser = subparsers.add_parser( + 'list_products', help=list_products.__doc__) + + get_product_parser = subparsers.add_parser( + 'get_product', help=get_product.__doc__) + get_product_parser.add_argument('product_id') + + update_product_labels_parser = subparsers.add_parser( + 'update_product_labels', help=update_product_labels.__doc__) + update_product_labels_parser.add_argument('product_id') + update_product_labels_parser.add_argument('key') + update_product_labels_parser.add_argument('value') + + delete_product_parser = subparsers.add_parser( + 'delete_product', help=delete_product.__doc__) + delete_product_parser.add_argument('product_id') + + args = parser.parse_args() + + if args.command == 'create_product': + create_product( + args.project_id, args.location, args.product_id, + args.product_display_name, args.product_category) + elif args.command == 'list_products': + list_products(args.project_id, args.location) + elif args.command == 'get_product': + get_product(args.project_id, args.location, args.product_id) + elif args.command == 'update_product_labels': + update_product_labels( + args.project_id, args.location, args.product_id, + args.key, args.value) + elif args.command == 'delete_product': + delete_product(args.project_id, args.location, args.product_id) diff --git a/vision/cloud-client/product_search/product_management_test.py b/vision/cloud-client/product_search/product_management_test.py new file mode 100644 index 00000000000..fd1ad24aeb6 --- /dev/null +++ b/vision/cloud-client/product_search/product_management_test.py @@ -0,0 +1,85 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 pytest + +from product_management import ( + create_product, delete_product, get_product, list_products, + update_product_labels) + + +PROJECT_ID = os.getenv('GCLOUD_PROJECT') +LOCATION = 'us-west1' + +PRODUCT_DISPLAY_NAME = 'fake_product_display_name_for_testing' +PRODUCT_CATEGORY = 'homegoods' +PRODUCT_ID = 'fake_product_id_for_testing' +KEY = 'fake_key_for_testing' +VALUE = 'fake_value_for_testing' + + +@pytest.fixture +def product(): + # set up + create_product( + PROJECT_ID, LOCATION, PRODUCT_ID, + PRODUCT_DISPLAY_NAME, PRODUCT_CATEGORY) + + yield None + + # tear down + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) + + +def test_create_product(capsys): + list_products(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_ID not in out + + create_product( + PROJECT_ID, LOCATION, PRODUCT_ID, + PRODUCT_DISPLAY_NAME, PRODUCT_CATEGORY) + list_products(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_ID in out + + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) + + +def test_delete_product(capsys, product): + list_products(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_ID in out + + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) + + list_products(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_ID not in out + + +def test_update_product_labels(capsys, product): + get_product(PROJECT_ID, LOCATION, PRODUCT_ID) + out, _ = capsys.readouterr() + assert KEY not in out + assert VALUE not in out + + update_product_labels(PROJECT_ID, LOCATION, PRODUCT_ID, KEY, VALUE) + out, _ = capsys.readouterr() + assert KEY in out + assert VALUE in out + + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) diff --git a/vision/cloud-client/product_search/product_search.py b/vision/cloud-client/product_search/product_search.py new file mode 100755 index 00000000000..8ae8c1293a9 --- /dev/null +++ b/vision/cloud-client/product_search/product_search.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# 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. + +"""This tutorial demonstrates how users query the product set with their +own images and find the products similer to the image using the Cloud +Vision Product Search API. + +For more information, see the tutorial page at +https://cloud.google.com/vision/product-search/docs/ +""" + +# [START product_search_import] +import argparse + +from google.cloud import vision_v1p3beta1 as vision +# [END product_search_import] + + +# [START product_search_get_similar_products_file] +def get_similar_products_file( + project_id, location, product_set_id, product_category, + file_path, filter): + """Search similar products to image. + Args: + project_id: Id of the project. + location: A compute region name. + product_set_id: Id of the product set. + product_category: Category of the product. + file_path: Local file path of the image to be searched. + filter: Condition to be applied on the labels. + Example for filter: (color = red OR color = blue) AND style = kids + It will search on all products with the following labels: + color:red AND style:kids + color:blue AND style:kids + """ + # product_search_client is needed only for its helper methods. + product_search_client = vision.ProductSearchClient() + image_annotator_client = vision.ImageAnnotatorClient() + + # Read the image as a stream of bytes. + with open(file_path, 'rb') as image_file: + content = image_file.read() + + # Create annotate image request along with product search feature. + image = vision.types.Image(content=content) + + # product search specific parameters + product_set_path = product_search_client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + product_search_params = vision.types.ProductSearchParams( + product_set=product_set_path, + product_categories=[product_category], + filter=filter) + image_context = vision.types.ImageContext( + product_search_params=product_search_params) + + # Search products similar to the image. + response = image_annotator_client.product_search( + image, image_context=image_context) + + index_time = response.product_search_results.index_time + print('Product set index time:') + print(' seconds: {}'.format(index_time.seconds)) + print(' nanos: {}\n'.format(index_time.nanos)) + + results = response.product_search_results.results + + print('Search results:') + for result in results: + product = result.product + + print('Score(Confidence): {}'.format(result.score)) + print('Image name: {}'.format(result.image)) + + print('Product name: {}'.format(product.name)) + print('Product display name: {}'.format( + product.display_name)) + print('Product description: {}\n'.format(product.description)) + print('Product labels: {}\n'.format(product.product_labels)) +# [END product_search_get_similar_products_file] + + +# [START product_search_get_similar_products_uri] +def get_similar_products_uri( + project_id, location, product_set_id, product_category, + image_uri, filter): + """Search similar products to image. + Args: + project_id: Id of the project. + location: A compute region name. + product_set_id: Id of the product set. + product_category: Category of the product. + file_path: Local file path of the image to be searched. + filter: Condition to be applied on the labels. + Example for filter: (color = red OR color = blue) AND style = kids + It will search on all products with the following labels: + color:red AND style:kids + color:blue AND style:kids + """ + # product_search_client is needed only for its helper methods. + product_search_client = vision.ProductSearchClient() + image_annotator_client = vision.ImageAnnotatorClient() + + # Create annotate image request along with product search feature. + image_source = vision.types.ImageSource(image_uri=image_uri) + image = vision.types.Image(source=image_source) + + # product search specific parameters + product_set_path = product_search_client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + product_search_params = vision.types.ProductSearchParams( + product_set=product_set_path, + product_categories=[product_category], + filter=filter) + image_context = vision.types.ImageContext( + product_search_params=product_search_params) + + # Search products similar to the image. + response = image_annotator_client.product_search( + image, image_context=image_context) + + index_time = response.product_search_results.index_time + print('Product set index time:') + print(' seconds: {}'.format(index_time.seconds)) + print(' nanos: {}\n'.format(index_time.nanos)) + + results = response.product_search_results.results + + print('Search results:') + for result in results: + product = result.product + + print('Score(Confidence): {}'.format(result.score)) + print('Image name: {}'.format(result.image)) + + print('Product name: {}'.format(product.name)) + print('Product display name: {}'.format( + product.display_name)) + print('Product description: {}\n'.format(product.description)) + print('Product labels: {}\n'.format(product.product_labels)) +# [END product_search_get_similar_products_uri] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + subparsers = parser.add_subparsers(dest='command') + parser.add_argument( + '--project_id', + help='Project id. Required', + required=True) + parser.add_argument( + '--location', + help='Compute region name', + default='us-west1') + parser.add_argument('--product_set_id') + parser.add_argument('--product_category') + parser.add_argument('--filter', default='') + + get_similar_products_file_parser = subparsers.add_parser( + 'get_similar_products_file', help=get_similar_products_file.__doc__) + get_similar_products_file_parser.add_argument('--file_path') + + get_similar_products_uri_parser = subparsers.add_parser( + 'get_similar_products_uri', help=get_similar_products_uri.__doc__) + get_similar_products_uri_parser.add_argument('--image_uri') + + args = parser.parse_args() + + if args.command == 'get_similar_products_file': + get_similar_products_file( + args.project_id, args.location, args.product_set_id, + args.product_category, args.file_path, args.filter) + elif args.command == 'get_similar_products_uri': + get_similar_products_uri( + args.project_id, args.location, args.product_set_id, + args.product_category, args.image_uri, args.filter) diff --git a/vision/cloud-client/product_search/product_search_test.py b/vision/cloud-client/product_search/product_search_test.py new file mode 100644 index 00000000000..8ac59f18d7f --- /dev/null +++ b/vision/cloud-client/product_search/product_search_test.py @@ -0,0 +1,66 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 + +from product_search import get_similar_products_file, get_similar_products_uri + + +PROJECT_ID = os.getenv('GCLOUD_PROJECT') +LOCATION = 'us-west1' + +PRODUCT_SET_ID = 'indexed_product_set_id_for_testing' +PRODUCT_CATEGORY = 'apparel' +PRODUCT_ID_1 = 'indexed_product_id_for_testing_1' +PRODUCT_ID_2 = 'indexed_product_id_for_testing_2' + +FILE_PATH_1 = 'resources/shoes_1.jpg' +IMAGE_URI_1 = 'gs://python-docs-samples-tests/product_search/shoes_1.jpg' +FILTER = 'style=womens' + + +def test_get_similar_products_file(capsys): + get_similar_products_file( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, PRODUCT_CATEGORY, FILE_PATH_1, + '') + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 in out + assert PRODUCT_ID_2 in out + + +def test_get_similar_products_uri(capsys): + get_similar_products_uri( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, PRODUCT_CATEGORY, IMAGE_URI_1, + '') + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 in out + assert PRODUCT_ID_2 in out + + +def test_get_similar_products_file_with_filter(capsys): + get_similar_products_file( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, PRODUCT_CATEGORY, FILE_PATH_1, + FILTER) + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 in out + assert PRODUCT_ID_2 not in out + + +def test_get_similar_products_uri_with_filter(capsys): + get_similar_products_uri( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, PRODUCT_CATEGORY, IMAGE_URI_1, + FILTER) + out, _ = capsys.readouterr() + assert PRODUCT_ID_1 in out + assert PRODUCT_ID_2 not in out diff --git a/vision/cloud-client/product_search/product_set_management.py b/vision/cloud-client/product_search/product_set_management.py new file mode 100755 index 00000000000..2f4906d7c3b --- /dev/null +++ b/vision/cloud-client/product_search/product_set_management.py @@ -0,0 +1,180 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# 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. + +"""This application demonstrates how to perform operations +on Product set in Cloud Vision Product Search. + +For more information, see the tutorial page at +https://cloud.google.com/vision/product-search/docs/ +""" + +# [START product_search_import] +import argparse + +from google.cloud import vision_v1p3beta1 as vision +# [END product_search_import] + + +# [START product_search_create_product_set] +def create_product_set( + project_id, location, product_set_id, product_set_display_name): + """Create a product set. + Args: + project_id: Id of the project. + location: A compute region name. + product_set_id: Id of the product set. + product_set_display_name: Display name of the product set. + """ + client = vision.ProductSearchClient() + + # A resource that represents Google Cloud Platform location. + location_path = client.location_path( + project=project_id, location=location) + + # Create a product set with the product set specification in the region. + product_set = vision.types.ProductSet( + display_name=product_set_display_name) + + # The response is the product set with `name` populated. + response = client.create_product_set( + parent=location_path, + product_set=product_set, + product_set_id=product_set_id) + + # Display the product set information. + print('Product set name: {}'.format(response.name)) +# [END product_search_create_product_set] + + +# [START product_search_list_product_sets] +def list_product_sets(project_id, location): + """List all product sets. + Args: + project_id: Id of the project. + location: A compute region name. + """ + client = vision.ProductSearchClient() + + # A resource that represents Google Cloud Platform location. + location_path = client.location_path( + project=project_id, location=location) + + # List all the product sets available in the region. + product_sets = client.list_product_sets(parent=location_path) + + # Display the product set information. + for product_set in product_sets: + print('Product set name: {}'.format(product_set.name)) + print('Product set id: {}'.format(product_set.name.split('/')[-1])) + print('Product set display name: {}'.format(product_set.display_name)) + print('Product set index time:') + print(' seconds: {}'.format(product_set.index_time.seconds)) + print(' nanos: {}\n'.format(product_set.index_time.nanos)) +# [END product_search_list_product_sets] + + +# [START product_search_get_product_set] +def get_product_set(project_id, location, product_set_id): + """Get info about the product set. + Args: + project_id: Id of the project. + location: A compute region name. + product_set_id: Id of the product set. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product set. + product_set_path = client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + + # Get complete detail of the product set. + product_set = client.get_product_set(name=product_set_path) + + # Display the product set information. + print('Product set name: {}'.format(product_set.name)) + print('Product set id: {}'.format(product_set.name.split('/')[-1])) + print('Product set display name: {}'.format(product_set.display_name)) + print('Product set index time:') + print(' seconds: {}'.format(product_set.index_time.seconds)) + print(' nanos: {}'.format(product_set.index_time.nanos)) +# [END product_search_get_product_set] + + +# [START product_search_delete_product_set] +def delete_product_set(project_id, location, product_set_id): + """Delete a product set. + Args: + project_id: Id of the project. + location: A compute region name. + product_set_id: Id of the product set. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product set. + product_set_path = client.product_set_path( + project=project_id, location=location, + product_set=product_set_id) + + # Delete the product set. + client.delete_product_set(name=product_set_path) + print('Product set deleted.') +# [END product_search_delete_product_set] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + subparsers = parser.add_subparsers(dest='command') + parser.add_argument( + '--project_id', + help='Project id. Required', + required=True) + parser.add_argument( + '--location', + help='Compute region name', + default='us-west1') + + create_product_set_parser = subparsers.add_parser( + 'create_product_set', help=create_product_set.__doc__) + create_product_set_parser.add_argument('product_set_id') + create_product_set_parser.add_argument('product_set_display_name') + + list_product_sets_parser = subparsers.add_parser( + 'list_product_sets', help=list_product_sets.__doc__) + + get_product_set_parser = subparsers.add_parser( + 'get_product_set', help=get_product_set.__doc__) + get_product_set_parser.add_argument('product_set_id') + + delete_product_set_parser = subparsers.add_parser( + 'delete_product_set', help=delete_product_set.__doc__) + delete_product_set_parser.add_argument('product_set_id') + + args = parser.parse_args() + + if args.command == 'create_product_set': + create_product_set( + args.project_id, args.location, args.product_set_id, + args.product_set_display_name) + elif args.command == 'list_product_sets': + list_product_sets(args.project_id, args.location) + elif args.command == 'get_product_set': + get_product_set(args.project_id, args.location, args.product_set_id) + elif args.command == 'delete_product_set': + delete_product_set( + args.project_id, args.location, args.product_set_id) diff --git a/vision/cloud-client/product_search/product_set_management_test.py b/vision/cloud-client/product_search/product_set_management_test.py new file mode 100644 index 00000000000..2148f29e345 --- /dev/null +++ b/vision/cloud-client/product_search/product_set_management_test.py @@ -0,0 +1,66 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 pytest + +from product_set_management import ( + create_product_set, delete_product_set, list_product_sets) + + +PROJECT_ID = os.getenv('GCLOUD_PROJECT') +LOCATION = 'us-west1' + +PRODUCT_SET_DISPLAY_NAME = 'fake_product_set_display_name_for_testing' +PRODUCT_SET_ID = 'fake_product_set_id_for_testing' + + +@pytest.fixture +def product_set(): + # set up + create_product_set( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, PRODUCT_SET_DISPLAY_NAME) + + yield None + + # tear down + delete_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + + +def test_create_product_set(capsys): + list_product_sets(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_SET_ID not in out + + create_product_set( + PROJECT_ID, LOCATION, PRODUCT_SET_ID, + PRODUCT_SET_DISPLAY_NAME) + list_product_sets(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_SET_ID in out + + delete_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + + +def test_delete_product_set(capsys, product_set): + list_product_sets(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_SET_ID in out + + delete_product_set(PROJECT_ID, LOCATION, PRODUCT_SET_ID) + + list_product_sets(PROJECT_ID, LOCATION) + out, _ = capsys.readouterr() + assert PRODUCT_SET_ID not in out diff --git a/vision/cloud-client/product_search/reference_image_management.py b/vision/cloud-client/product_search/reference_image_management.py new file mode 100755 index 00000000000..dac2ddeb157 --- /dev/null +++ b/vision/cloud-client/product_search/reference_image_management.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python + +# Copyright 2018 Google Inc. All Rights Reserved. +# +# 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. + +"""This application demonstrates how to perform basic operations on reference +images in Cloud Vision Product Search. + +For more information, see the tutorial page at +https://cloud.google.com/vision/product-search/docs/ +""" + +# [START product_search_import] +import argparse + +from google.cloud import vision_v1p3beta1 as vision +# [END product_search_import] + + +# [START product_search_create_reference_image] +def create_reference_image( + project_id, location, product_id, reference_image_id, gcs_uri): + """Create a reference image. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + reference_image_id: Id of the reference image. + gcs_uri: Google Cloud Storage path of the input image. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # Create a reference image. + reference_image = vision.types.ReferenceImage(uri=gcs_uri) + + # The response is the reference image with `name` populated. + image = client.create_reference_image( + parent=product_path, + reference_image=reference_image, + reference_image_id=reference_image_id) + + # Display the reference image information. + print('Reference image name: {}'.format(image.name)) + print('Reference image uri: {}'.format(image.uri)) +# [END product_search_create_reference_image] + + +# [START product_search_list_reference_images] +def list_reference_images( + project_id, location, product_id): + """List all images in a product. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + """ + client = vision.ProductSearchClient() + + # Get the full path of the product. + product_path = client.product_path( + project=project_id, location=location, product=product_id) + + # List all the reference images available in the product. + reference_images = client.list_reference_images(parent=product_path) + + # Display the reference image information. + for image in reference_images: + print('Reference image name: {}'.format(image.name)) + print('Reference image id: {}'.format(image.name.split('/')[-1])) + print('Reference image uri: {}'.format(image.uri)) + print('Reference image bounding polygons: {}'.format( + image.bounding_polys)) +# [END product_search_list_reference_images] + + +# [START product_search_get_reference_image] +def get_reference_image( + project_id, location, product_id, reference_image_id): + """Get info about a reference image. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + reference_image_id: Id of the reference image. + """ + client = vision.ProductSearchClient() + + # Get the full path of the reference image. + reference_image_path = client.reference_image_path( + project=project_id, location=location, product=product_id, + reference_image=reference_image_id) + + # Get complete detail of the reference image. + image = client.get_reference_image(name=reference_image_path) + + # Display the reference image information. + print('Reference image name: {}'.format(image.name)) + print('Reference image id: {}'.format(image.name.split('/')[-1])) + print('Reference image uri: {}'.format(image.uri)) + print('Reference image bounding polygons: {}'.format(image.bounding_polys)) +# [END product_search_get_reference_image] + + +# [START product_search_delete_reference_image] +def delete_reference_image( + project_id, location, product_id, reference_image_id): + """Delete a reference image. + Args: + project_id: Id of the project. + location: A compute region name. + product_id: Id of the product. + reference_image_id: Id of the reference image. + """ + client = vision.ProductSearchClient() + + # Get the full path of the reference image. + reference_image_path = client.reference_image_path( + project=project_id, location=location, product=product_id, + reference_image=reference_image_id) + + # Delete the reference image. + client.delete_reference_image(name=reference_image_path) + print('Reference image deleted from product.') +# [END product_search_delete_reference_image] + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + subparsers = parser.add_subparsers(dest='command') + parser.add_argument( + '--project_id', + help='Project id. Required', + required=True) + parser.add_argument( + '--location', + help='Compute region name', + default='us-west1') + + create_reference_image_parser = subparsers.add_parser( + 'create_reference_image', help=create_reference_image.__doc__) + create_reference_image_parser.add_argument('product_id') + create_reference_image_parser.add_argument('reference_image_id') + create_reference_image_parser.add_argument('gcs_uri') + + list_reference_images_parser = subparsers.add_parser( + 'list_reference_images', + help=list_reference_images.__doc__) + list_reference_images_parser.add_argument('product_id') + + get_reference_image_parser = subparsers.add_parser( + 'get_reference_image', help=get_reference_image.__doc__) + get_reference_image_parser.add_argument('product_id') + get_reference_image_parser.add_argument('reference_image_id') + + delete_reference_image_parser = subparsers.add_parser( + 'delete_reference_image', help=delete_reference_image.__doc__) + delete_reference_image_parser.add_argument('product_id') + delete_reference_image_parser.add_argument('reference_image_id') + + args = parser.parse_args() + + if args.command == 'create_reference_image': + create_reference_image( + args.project_id, args.location, args.product_id, + args.reference_image_id, args.gcs_uri) + elif args.command == 'list_reference_images': + list_reference_images( + args.project_id, args.location, args.product_id) + elif args.command == 'get_reference_image': + get_reference_image( + args.project_id, args.location, args.product_id, + args.reference_image_id) + elif args.command == 'delete_reference_image': + delete_reference_image( + args.project_id, args.location, args.product_id, + args.reference_image_id) diff --git a/vision/cloud-client/product_search/reference_image_management_test.py b/vision/cloud-client/product_search/reference_image_management_test.py new file mode 100644 index 00000000000..1a5c273577e --- /dev/null +++ b/vision/cloud-client/product_search/reference_image_management_test.py @@ -0,0 +1,77 @@ +# Copyright 2016 Google Inc. All Rights Reserved. +# +# 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 pytest + +from product_management import create_product, delete_product +from reference_image_management import ( + create_reference_image, delete_reference_image, list_reference_images) + + +PROJECT_ID = os.getenv('GCLOUD_PROJECT') +LOCATION = 'us-west1' + +PRODUCT_DISPLAY_NAME = 'fake_product_display_name_for_testing' +PRODUCT_CATEGORY = 'homegoods' +PRODUCT_ID = 'fake_product_id_for_testing' + +REFERENCE_IMAGE_ID = 'fake_reference_image_id_for_testing' +GCS_URI = 'gs://python-docs-samples-tests/product_search/shoes_1.jpg' + + +@pytest.fixture +def product(): + # set up + create_product( + PROJECT_ID, LOCATION, PRODUCT_ID, + PRODUCT_DISPLAY_NAME, PRODUCT_CATEGORY) + + yield None + + # tear down + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) + + +def test_create_reference_image(capsys, product): + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID) + out, _ = capsys.readouterr() + assert REFERENCE_IMAGE_ID not in out + + create_reference_image( + PROJECT_ID, LOCATION, PRODUCT_ID, REFERENCE_IMAGE_ID, + GCS_URI) + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID) + out, _ = capsys.readouterr() + assert REFERENCE_IMAGE_ID in out + + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) + + +def test_delete_reference_image(capsys, product): + create_reference_image( + PROJECT_ID, LOCATION, PRODUCT_ID, REFERENCE_IMAGE_ID, + GCS_URI) + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID) + out, _ = capsys.readouterr() + assert REFERENCE_IMAGE_ID in out + + delete_reference_image( + PROJECT_ID, LOCATION, PRODUCT_ID, REFERENCE_IMAGE_ID) + list_reference_images(PROJECT_ID, LOCATION, PRODUCT_ID) + out, _ = capsys.readouterr() + assert REFERENCE_IMAGE_ID not in out + + delete_product(PROJECT_ID, LOCATION, PRODUCT_ID) diff --git a/vision/cloud-client/product_search/requirements.txt b/vision/cloud-client/product_search/requirements.txt new file mode 100644 index 00000000000..47993a0c54f --- /dev/null +++ b/vision/cloud-client/product_search/requirements.txt @@ -0,0 +1 @@ +google-cloud-vision==0.33.0 diff --git a/vision/cloud-client/product_search/resources/indexed_product_sets.csv b/vision/cloud-client/product_search/resources/indexed_product_sets.csv new file mode 100644 index 00000000000..7d1cb3c519f --- /dev/null +++ b/vision/cloud-client/product_search/resources/indexed_product_sets.csv @@ -0,0 +1,2 @@ +"gs://python-docs-samples-tests/product_search/shoes_1.jpg","indexed_product_set_id_for_testing","indexed_product_id_for_testing_1","apparel","style=womens","0.1,0.1,0.9,0.1,0.9,0.9,0.1,0.9" +"gs://python-docs-samples-tests/product_search/shoes_2.jpg","indexed_product_set_id_for_testing","indexed_product_id_for_testing_2","apparel",, \ No newline at end of file diff --git a/vision/cloud-client/product_search/resources/product_sets.csv b/vision/cloud-client/product_search/resources/product_sets.csv new file mode 100644 index 00000000000..2104b99afae --- /dev/null +++ b/vision/cloud-client/product_search/resources/product_sets.csv @@ -0,0 +1,2 @@ +"gs://python-docs-samples-tests/product_search/shoes_1.jpg","fake_product_set_id_for_testing","fake_product_id_for_testing_1","apparel","style=womens","0.1,0.1,0.9,0.1,0.9,0.9,0.1,0.9" +"gs://python-docs-samples-tests/product_search/shoes_2.jpg","fake_product_set_id_for_testing","fake_product_id_for_testing_2","apparel",, \ No newline at end of file diff --git a/vision/cloud-client/product_search/resources/shoes_1.jpg b/vision/cloud-client/product_search/resources/shoes_1.jpg new file mode 100644 index 00000000000..78318eeff66 Binary files /dev/null and b/vision/cloud-client/product_search/resources/shoes_1.jpg differ diff --git a/vision/cloud-client/product_search/resources/shoes_2.jpg b/vision/cloud-client/product_search/resources/shoes_2.jpg new file mode 100644 index 00000000000..cdfa80dd899 Binary files /dev/null and b/vision/cloud-client/product_search/resources/shoes_2.jpg differ