Instructivo sobre sugerencias de recorte

Público

El objetivo de este instructivo es ayudarte a desarrollar aplicaciones mediante la característica de sugerencias de recorte de la API de Vision. Se supone que estás familiarizado con las construcciones y técnicas de programación básicas. Sin embargo, aunque seas un programador principiante, podrás seguir y ejecutar este instructivo sin dificultad y, luego, usar la documentación de referencia de la API de Vision para crear aplicaciones básicas.

En este instructivo, se explica una aplicación de la API de Vision y se muestra cómo realizar una llamada a la API de Vision para usar la característica de sugerencias de recorte.

Requisitos previos

Python

Resumen

En este instructivo, se muestra una aplicación básica de la API de Vision que usa una solicitud de Crop Hints. Puedes proporcionar la imagen que quieres procesar a través de un URI de Cloud Storage (ubicación del bucket de Cloud Storage) o incorporarla en la solicitud. Una respuesta de Crop Hints correcta muestra las coordenadas de un cuadro de límite recortado alrededor del objeto o rostro predominante en la imagen.

Lee el código

A medida que leas el código, te recomendamos que consultes la referencia de la API de Cloud Vision para Python.

import argparse

from typing import MutableSequence

from google.cloud import vision
from PIL import Image, ImageDraw

def get_crop_hint(path: str) -> MutableSequence[vision.Vertex]:
    """Detect crop hints on a single image and return the first result.

    Args:
        path: path to the image file.

    Returns:
        The vertices for the bounding polygon.
    """
    client = vision.ImageAnnotatorClient()

    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

    # Get bounds for the first crop hint using an aspect ratio of 1.77.
    vertices = hints[0].bounding_poly.vertices

    return vertices

def draw_hint(image_file: str) -> None:
    """Draw a border around the image using the hints in the vector list.

    Args:
        image_file: path to the image file.
    """
    vects = get_crop_hint(image_file)

    im = Image.open(image_file)
    draw = ImageDraw.Draw(im)
    draw.polygon(
        [
            vects[0].x,
            vects[0].y,
            vects[1].x,
            vects[1].y,
            vects[2].x,
            vects[2].y,
            vects[3].x,
            vects[3].y,
        ],
        None,
        "red",
    )
    im.save("output-hint.jpg", "JPEG")
    print("Saved new image to output-hint.jpg")

def crop_to_hint(image_file: str) -> None:
    """Crop the image using the hints in the vector list.

    Args:
        image_file: path to the image file.
    """
    vects = get_crop_hint(image_file)

    im = Image.open(image_file)
    im2 = im.crop([vects[0].x, vects[0].y, vects[2].x - 1, vects[2].y - 1])
    im2.save("output-crop.jpg", "JPEG")
    print("Saved new image to output-crop.jpg")

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("image_file", help="The image you'd like to crop.")
    parser.add_argument("mode", help='Set to "crop" or "draw".')
    args = parser.parse_args()

    if args.mode == "crop":
        crop_to_hint(args.image_file)
    elif args.mode == "draw":
        draw_hint(args.image_file)

Información detallada

Importa bibliotecas

import argparse

from typing import MutableSequence

from google.cloud import vision
from PIL import Image, ImageDraw

Importamos las siguientes bibliotecas estándar:

  • argparse para permitir que la aplicación acepte los nombres de archivos de entrada como argumentos
  • io para la E/S de archivos

Otras importaciones son:

  • La clase ImageAnnotatorClient dentro de la biblioteca google.cloud.vision para acceder a la API de Vision
  • El módulo types dentro de la biblioteca de google.cloud.vision para crear solicitudes.
  • Los módulos Image y ImageDraw de Python Imaging Library (PIL) para crear un cuadro de límite en la imagen de entrada.

Ejecuta la aplicación

parser = argparse.ArgumentParser()
parser.add_argument("image_file", help="The image you'd like to crop.")
parser.add_argument("mode", help='Set to "crop" or "draw".')
args = parser.parse_args()

if args.mode == "crop":
    crop_to_hint(args.image_file)
elif args.mode == "draw":
    draw_hint(args.image_file)

Aquí, solo analizamos el argumento ingresado que especifica el nombre de archivo de la imagen local y lo pasamos a una función para recortar la imagen o crear la sugerencia.

Autenticar en la API

Antes de comunicarte con el servicio de la API de Vision, debes autenticar tu servicio con las credenciales ya adquiridas. Dentro de una aplicación, la manera más simple de obtener credenciales es usar las credenciales predeterminadas de la aplicación (ADC). Según la configuración predeterminada, la biblioteca cliente intentará obtener credenciales de la variable de entorno GOOGLE_APPLICATION_CREDENTIALS, que debería estar configurada para que apunte al archivo de claves JSON de tu cuenta de servicio (consulta Configura una cuenta de servicio a fin de obtener más información).

Obtén anotaciones de sugerencias de recorte para la imagen

Ahora que la biblioteca cliente de Vision está autenticada, podemos acceder al servicio mediante una llamada al método crop_hints de la instancia ImageAnnotatorClient. La relación de aspecto para el resultado se especifica en un objeto ImageContext. Si se ingresan múltiples relaciones de aspecto, se mostrarán varias sugerencias de recorte, una para cada relación de aspecto.

"""Detect crop hints on a single image and return the first result.

Args:
    path: path to the image file.

Returns:
    The vertices for the bounding polygon.
"""
client = vision.ImageAnnotatorClient()

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

# Get bounds for the first crop hint using an aspect ratio of 1.77.
vertices = hints[0].bounding_poly.vertices

La biblioteca cliente abarca los detalles de las solicitudes y respuestas a la API. Consulta la referencia de la API de Vision para obtener información completa sobre la estructura de una solicitud.

Usa la respuesta para recortar o crear el cuadro de límite de la sugerencia

Una vez que la operación se completó correctamente, la respuesta de la API contendrá las coordenadas del cuadro de límite de una o más cropHint. El método draw_hint crea líneas alrededor del cuadro de límite de CropHints y, luego, guarda la imagen en output-hint.jpg.

vects = get_crop_hint(image_file)

im = Image.open(image_file)
draw = ImageDraw.Draw(im)
draw.polygon(
    [
        vects[0].x,
        vects[0].y,
        vects[1].x,
        vects[1].y,
        vects[2].x,
        vects[2].y,
        vects[3].x,
        vects[3].y,
    ],
    None,
    "red",
)
im.save("output-hint.jpg", "JPEG")
print("Saved new image to output-hint.jpg")

El método crop_to_hint recorta la imagen con la sugerencia de recorte proporcionada.

vects = get_crop_hint(image_file)

im = Image.open(image_file)
im2 = im.crop([vects[0].x, vects[0].y, vects[2].x - 1, vects[2].y - 1])
im2.save("output-crop.jpg", "JPEG")
print("Saved new image to output-crop.jpg")

Ejecuta la aplicación

Para ejecutar la aplicación, puedes descargar este archivo cat.jpg (es posible que debas hacer clic con el botón derecho en el vínculo) y, luego, pasar la ubicación en la que descargaste el archivo en tu máquina local a la aplicación del instructivo (crop_hints.py).

Este es el comando de Python, seguido del resultado de la consola, que muestra la respuesta JSON cropHintsAnnotation. Esta respuesta incluye las coordenadas del cuadro de límite de cropHints. Solicitamos un área de recorte con una relación de aspecto de ancho y altura de 1.77. Las coordenadas x,y que se encuentran arriba a la izquierda y abajo a la derecha del rectángulo de recorte que se muestran son 0,3361100,967.

python crop_hints.py cat.jpeg crop
{
 "responses": [
  {
   "cropHintsAnnotation": {
    "cropHints": [
     {
      "boundingPoly": {
       "vertices": [
        {
         "y": 336
        },
        {
         "x": 1100,
         "y": 336
        },
        {
         "x": 1100,
         "y": 967
        },
        {
         "y": 967
        }
       ]
      },
      "confidence": 0.79999995,
      "importanceFraction": 0.69
     }
    ]
   }
  }
 ]
}

Y esta es la imagen recortada.

Felicitaciones Ejecutaste la API de sugerencias de recorte de Cloud Vision para mostrar las coordenadas optimizadas del cuadro de límite alrededor del objeto predominante que se detectó en la imagen.