Migrer vers la bibliothèque cliente Python v0.25.1

La bibliothèque cliente Python v0.25.1 apporte des modifications importantes à la conception des bibliothèques clientes précédentes. Ces modifications peuvent être résumées comme suit :

  • Consolidation des modules en moins de types

  • Remplacement des paramètres non typés par des classes et des énumérations fortement typées

Cette rubrique décrit en détail les modifications à apporter au code Python pour les bibliothèques clientes de l'API Cloud Vision afin d'utiliser la bibliothèque cliente Python v0.25.1.

Exécuter des versions précédentes de la bibliothèque cliente

Passer à la version 0.25.1 de la bibliothèque cliente Python n'est pas obligatoire. Pour continuer à vous servir d'une version précédente de la bibliothèque cliente Python sans migrer le code, indiquez la version de bibliothèque cliente Python utilisée par l'application. Pour spécifier une version de bibliothèque, modifiez le fichier requirements.txt comme suit :

google-cloud-vision==0.25

Modules supprimés

Les modules suivants ont été supprimés du package de la bibliothèque cliente Python v0.25.1 :

  • google.cloud.vision.annotations

  • google.cloud.vision.batch

  • google.cloud.vision.client

  • google.cloud.vision.color

  • google.cloud.vision.crop_hint

  • google.cloud.vision.entity

  • google.cloud.vision.face

  • google.cloud.vision.feature

  • google.cloud.vision.geometry

  • google.cloud.vision.image

  • google.cloud.vision.likelihood

  • google.cloud.vision.safe_search

  • google.cloud.vision.text

  • google.cloud.vision.web

Modifications de code requises

Importations

Incluez le nouveau module google.cloud.vision.types afin d'accéder aux nouveaux types dans la bibliothèque cliente Python v0.25.1.

Le module types contient les nouvelles classes requises pour créer des requêtes, telles que types.Image.

from google.cloud import vision

De plus, le nouveau module google.cloud.vision.enums contient les énumérations utiles pour l'analyse et la compréhension des réponses de l'API, telles que enums.Likelihood.UNLIKELY et enums.FaceAnnotation.Landmark.Type.LEFT_EYE.

Créer un client

La classe Client a été remplacée par la classe ImageAnnotatorClient. Remplacez les références à la classe Client par ImageAnnotatorClient.

Versions précédentes des bibliothèques clientes :

old_client = vision.Client()

Bibliothèque cliente Python v0.25.1 :

client = vision.ImageAnnotatorClient()

Créer des objets représentant du contenu image

Pour identifier le contenu d'une image à partir d'un fichier local, d'un URI Google Cloud Storage ou d'un URI Web, utilisez la nouvelle classe Image.

Créer des objets représentant du contenu image à partir d'un fichier local

L'exemple suivant vous montre la nouvelle façon de représenter du contenu image à partir d'un fichier local.

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

Créer des objets représentant du contenu image à partir d'un URI

L'exemple suivant vous montre la nouvelle façon de représenter le contenu d'une image à partir d'un URI Google Cloud Storage ou d'un URI Web. uri est l'URI d'un fichier image stocké dans Google Cloud Storage ou sur le Web.

Versions précédentes des bibliothèques clientes :

image = old_client.image(source_uri=uri)

Bibliothèque cliente Python v0.25.1 :

image = vision.Image()
image.source.image_uri = uri

Envoyer des requêtes et traiter les réponses

Avec la bibliothèque cliente Python v0.25.1, les méthodes d'API telles que face_detection appartiennent à l'objet ImageAnnotatorClient et non aux objets Image.

Les valeurs renvoyées sont différentes pour plusieurs méthodes, comme expliqué ci-dessous.

En particulier, les sommets des cadres de délimitation sont désormais stockés dans bounding_poly.vertices et non plus dans bounds.vertices. Les coordonnées de chaque sommet sont stockées dans vertex.x et vertex.y, et non plus dans vertex.x_coordinate et vertex.y_coordinate.

Ces modifications du cadre de délimitation affectent face_detection, logo_detection, text_detection, document_text_detection et crop_hints.

Envoyer une requête de détection des visages et traiter la réponse

Les probabilités d'émotion sont désormais renvoyées sous forme d'énumérations stockées dans face.surprise_likelihood et non plus dans face.emotions.surprise. Les noms des étiquettes de probabilité peuvent être récupérés en important google.cloud.vision.enums.Likelihood.

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

faces = image.detect_faces()

for face in faces:
    print('anger: {}'.format(face.emotions.anger))
    print('joy: {}'.format(face.emotions.joy))
    print('surprise: {}'.format(face.emotions.surprise))

    vertices = (['({},{})'.format(bound.x_coordinate, bound.y_coordinate)
                for bound in face.bounds.vertices])

    print('face bounds: {}'.format(','.join(vertices)))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.face_detection(image=image)
faces = response.face_annotations

# Names of likelihood from google.cloud.vision.enums
likelihood_name = (
    "UNKNOWN",
    "VERY_UNLIKELY",
    "UNLIKELY",
    "POSSIBLE",
    "LIKELY",
    "VERY_LIKELY",
)
print("Faces:")

for face in faces:
    print(f"anger: {likelihood_name[face.anger_likelihood]}")
    print(f"joy: {likelihood_name[face.joy_likelihood]}")
    print(f"surprise: {likelihood_name[face.surprise_likelihood]}")

    vertices = [
        f"({vertex.x},{vertex.y})" for vertex in face.bounding_poly.vertices
    ]

    print("face bounds: {}".format(",".join(vertices)))

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de détection d'étiquettes et traiter la réponse

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

labels = image.detect_labels()

for label in labels:
    print(label.description)

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.label_detection(image=image)
labels = response.label_annotations
print("Labels:")

for label in labels:
    print(label.description)

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de détection de point de repère et traiter la réponse

Versions précédentes des bibliothèques clientes :

La latitude et la longitude des repères sont désormais stockées dans location.lat_lng.latitude et location.lat_lng.longitude, et non plus dans location.latitude et location.longitude.

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

landmarks = image.detect_landmarks()

for landmark in landmarks:
    print(landmark.description, landmark.score)
    for location in landmark.locations:
        print('Latitude'.format(location.latitude))
        print('Longitude'.format(location.longitude))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.landmark_detection(image=image)
landmarks = response.landmark_annotations
print("Landmarks:")

for landmark in landmarks:
    print(landmark.description)
    for location in landmark.locations:
        lat_lng = location.lat_lng
        print(f"Latitude {lat_lng.latitude}")
        print(f"Longitude {lat_lng.longitude}")

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de détection de logo et traiter la réponse

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

logos = image.detect_logos()

for logo in logos:
    print(logo.description, logo.score)

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.logo_detection(image=image)
logos = response.logo_annotations
print("Logos:")

for logo in logos:
    print(logo.description)

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Faire une demande de détection de recherche sécurisée et traiter la réponse

Les probabilités de recherche sécurisée sont maintenant renvoyées sous forme d'énumérations. Les noms des étiquettes de probabilité peuvent être récupérés en important google.cloud.vision.enums.Likelihood.

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

safe = image.detect_safe_search()
print('Safe search:')
print('adult: {}'.format(safe.adult))
print('medical: {}'.format(safe.medical))
print('spoofed: {}'.format(safe.spoof))
print('violence: {}'.format(safe.violence))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.safe_search_detection(image=image)
safe = response.safe_search_annotation

# Names of likelihood from google.cloud.vision.enums
likelihood_name = (
    "UNKNOWN",
    "VERY_UNLIKELY",
    "UNLIKELY",
    "POSSIBLE",
    "LIKELY",
    "VERY_LIKELY",
)
print("Safe search:")

print(f"adult: {likelihood_name[safe.adult]}")
print(f"medical: {likelihood_name[safe.medical]}")
print(f"spoofed: {likelihood_name[safe.spoof]}")
print(f"violence: {likelihood_name[safe.violence]}")
print(f"racy: {likelihood_name[safe.racy]}")

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de détection de texte et traiter la réponse

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

texts = image.detect_text()

for text in texts:
    print('\n"{}"'.format(text.description))

    vertices = (['({},{})'.format(bound.x_coordinate, bound.y_coordinate)
                for bound in text.bounds.vertices])

    print('bounds: {}'.format(','.join(vertices)))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.text_detection(image=image)
texts = response.text_annotations
print("Texts:")

for text in texts:
    print(f'\n"{text.description}"')

    vertices = [
        f"({vertex.x},{vertex.y})" for vertex in text.bounding_poly.vertices
    ]

    print("bounds: {}".format(",".join(vertices)))

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de détection de document texte et traiter la réponse

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

document = image.detect_full_text()

for page in document.pages:
    for block in page.blocks:
        block_words = []
        for paragraph in block.paragraphs:
            block_words.extend(paragraph.words)

        block_symbols = []
        for word in block_words:
            block_symbols.extend(word.symbols)

        block_text = ''
        for symbol in block_symbols:
            block_text = block_text + symbol.text

        print('Block Content: {}'.format(block_text))
        print('Block Bounds:\n {}'.format(block.bounding_box))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.document_text_detection(image=image)

for page in response.full_text_annotation.pages:
    for block in page.blocks:
        print(f"\nBlock confidence: {block.confidence}\n")

        for paragraph in block.paragraphs:
            print("Paragraph confidence: {}".format(paragraph.confidence))

            for word in paragraph.words:
                word_text = "".join([symbol.text for symbol in word.symbols])
                print(
                    "Word text: {} (confidence: {})".format(
                        word_text, word.confidence
                    )
                )

                for symbol in word.symbols:
                    print(
                        "\tSymbol: {} (confidence: {})".format(
                            symbol.text, symbol.confidence
                        )
                    )

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de propriétés d’image et traiter la réponse

Les informations sur les couleurs dominantes sont désormais stockées dans props.dominant_colors.colors et non plus dans props.colors.

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

props = image.detect_properties()

for color in props.colors:
    print('fraction: {}'.format(color.pixel_fraction))
    print('\tr: {}'.format(color.color.red))
    print('\tg: {}'.format(color.color.green))
    print('\tb: {}'.format(color.color.blue))
    print('\ta: {}'.format(color.color.alpha))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.image_properties(image=image)
props = response.image_properties_annotation
print("Properties:")

for color in props.dominant_colors.colors:
    print(f"fraction: {color.pixel_fraction}")
    print(f"\tr: {color.color.red}")
    print(f"\tg: {color.color.green}")
    print(f"\tb: {color.color.blue}")
    print(f"\ta: {color.color.alpha}")

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de détection sur le Web et traiter la réponse

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

notes = image.detect_web()

if notes.pages_with_matching_images:
    print('\n{} Pages with matching images retrieved')

    for page in notes.pages_with_matching_images:
        print('Score : {}'.format(page.score))
        print('Url   : {}'.format(page.url))

if notes.full_matching_images:
    print ('\n{} Full Matches found: '.format(
           len(notes.full_matching_images)))

    for image in notes.full_matching_images:
        print('Score:  {}'.format(image.score))
        print('Url  : {}'.format(image.url))

if notes.partial_matching_images:
    print ('\n{} Partial Matches found: '.format(
           len(notes.partial_matching_images)))

    for image in notes.partial_matching_images:
        print('Score: {}'.format(image.score))
        print('Url  : {}'.format(image.url))

if notes.web_entities:
    print ('\n{} Web entities found: '.format(len(notes.web_entities)))

    for entity in notes.web_entities:
        print('Score      : {}'.format(entity.score))
        print('Description: {}'.format(entity.description))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()

image = vision.Image(content=content)

response = client.web_detection(image=image)
annotations = response.web_detection

if annotations.best_guess_labels:
    for label in annotations.best_guess_labels:
        print(f"\nBest guess label: {label.label}")

if annotations.pages_with_matching_images:
    print(
        "\n{} Pages with matching images found:".format(
            len(annotations.pages_with_matching_images)
        )
    )

    for page in annotations.pages_with_matching_images:
        print(f"\n\tPage url   : {page.url}")

        if page.full_matching_images:
            print(
                "\t{} Full Matches found: ".format(len(page.full_matching_images))
            )

            for image in page.full_matching_images:
                print(f"\t\tImage url  : {image.url}")

        if page.partial_matching_images:
            print(
                "\t{} Partial Matches found: ".format(
                    len(page.partial_matching_images)
                )
            )

            for image in page.partial_matching_images:
                print(f"\t\tImage url  : {image.url}")

if annotations.web_entities:
    print("\n{} Web entities found: ".format(len(annotations.web_entities)))

    for entity in annotations.web_entities:
        print(f"\n\tScore      : {entity.score}")
        print(f"\tDescription: {entity.description}")

if annotations.visually_similar_images:
    print(
        "\n{} visually similar images found:\n".format(
            len(annotations.visually_similar_images)
        )
    )

    for image in annotations.visually_similar_images:
        print(f"\tImage url    : {image.url}")

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Envoyer une requête de possibilités de découpage et traiter la réponse

Versions précédentes des bibliothèques clientes :

with io.open(file_name, 'rb') as image_file:
    content = image_file.read()

image = old_client.image(content=content)

hints = image.detect_crop_hints(aspect_ratios=[1.77])

for n, hint in enumerate(hints):
    print('\nCrop Hint: {}'.format(n))

    vertices = (['({},{})'.format(bound.x_coordinate, bound.y_coordinate)
                for bound in hint.bounds.vertices])

    print('bounds: {}'.format(','.join(vertices)))

Bibliothèque cliente Python v0.25.1 :

with open(path, "rb") as image_file:
    content = image_file.read()
image = vision.Image(content=content)

crop_hints_params = vision.CropHintsParams(aspect_ratios=[1.77])
image_context = vision.ImageContext(crop_hints_params=crop_hints_params)

response = client.crop_hints(image=image, image_context=image_context)
hints = response.crop_hints_annotation.crop_hints

for n, hint in enumerate(hints):
    print(f"\nCrop Hint: {n}")

    vertices = [
        f"({vertex.x},{vertex.y})" for vertex in hint.bounding_poly.vertices
    ]

    print("bounds: {}".format(",".join(vertices)))

if response.error.message:
    raise Exception(
        "{}\nFor more info on error messages, check: "
        "https://cloud.google.com/apis/design/errors".format(response.error.message)
    )

Notez que le format doit être transmis par le biais d'un CropHintsParams et d'un ImageContext.