Tutorial de sugestões de corte

Público-alvo

O objetivo deste tutorial é ajudar a desenvolver aplicações com a funcionalidade Crop Hints da API Vision. Parte do princípio de que tem conhecimentos das técnicas e das construções de programação básicas. No entanto, mesmo que seja um programador iniciante, deve conseguir seguir e executar este tutorial sem dificuldade e, em seguida, usar a documentação de referência da API Vision para criar aplicações básicas.

Este tutorial explica passo a passo uma aplicação da API Vision, mostrando como fazer uma chamada à API Vision para usar a respetiva funcionalidade de sugestões de recorte.

Pré-requisitos

Vista geral

Este tutorial explica passo a passo uma aplicação básica da API Vision que usa um Crop Hints pedido. Pode fornecer a imagem a ser processada através de um URI do Cloud Storage (localização do contentor do Cloud Storage) ou incorporada no pedido. Uma Crop Hints resposta bem-sucedida devolve as coordenadas de uma caixa delimitadora recortada à volta do objeto ou da cara dominante na imagem.

Lista de códigos

À medida que lê o código, recomendamos que o siga consultando a referência Python da Cloud Vision API.

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)

Uma visão mais detalhada

Importar bibliotecas

import argparse

from typing import MutableSequence

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

Importamos bibliotecas padrão:

  • argparse para permitir que a aplicação aceite nomes de ficheiros de entrada como argumentos
  • io para E/S de ficheiros

Outras importações:

  • A classe ImageAnnotatorClient na biblioteca google.cloud.vision para aceder à API Vision.
  • O módulo types na biblioteca google.cloud.vision para criar pedidos
  • Os módulos Image e ImageDraw da Python Imaging Library (PIL). para desenhar uma caixa de limite na imagem de entrada.

Executar a aplicação

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)

Aqui, analisamos simplesmente o argumento transmitido que especifica o nome do ficheiro da imagem local e transmitimo-lo a uma função para recortar a imagem ou desenhar a sugestão.

Autenticação na API

Antes de comunicar com o serviço da API Vision, tem de autenticar o seu serviço através de credenciais adquiridas anteriormente. Numa aplicação, a forma mais simples de obter credenciais é usar as Credenciais padrão da aplicação (ADC). Por predefinição, a biblioteca de cliente tenta obter credenciais da variável de ambiente GOOGLE_APPLICATION_CREDENTIALS, que deve ser definida para apontar para o ficheiro de chave JSON da sua conta de serviço (consulte o artigo Configure uma conta de serviço para mais informações).

Obter anotações de sugestões de recorte para a imagem

Agora que a biblioteca de cliente Vision está autenticada, podemos aceder ao serviço chamando o método crop_hints da instância ImageAnnotatorClient. A proporção do resultado é especificada num objeto ImageContext. Se forem transmitidas várias proporções, são devolvidas várias sugestões de recorte, uma para cada proporção.

"""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

A biblioteca de cliente encapsula os detalhes dos pedidos e das respostas à API. Consulte a referência da API Vision para ver informações completas sobre a estrutura de um pedido.

Usar a resposta para recortar ou desenhar a caixa delimitadora da sugestão

Assim que a operação for concluída com êxito, a resposta da API vai conter as coordenadas da caixa delimitadora de um ou mais cropHints. O método draw_hint desenha linhas à volta da caixa delimitadora CropHints e, em seguida, escreve a imagem em 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")

O método crop_to_hint recorta a imagem com base na sugestão de recorte.

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")

Executar a aplicação

Para executar a aplicação, pode transferir este ficheiro cat.jpg (pode ter de clicar com o botão direito do rato no link) e, em seguida, transmitir a localização onde transferiu o ficheiro no seu computador local para a aplicação do tutorial (crop_hints.py).

Segue-se o comando Python, seguido do resultado da consola, que apresenta a resposta JSON cropHintsAnnotation. Esta resposta inclui as coordenadas da caixa delimitadora cropHints. Pedimos uma área de recorte com uma proporção de 1, 77 de largura para altura, e as coordenadas x,y devolvidas do retângulo de recorte superior esquerdo e inferior direito são 0,336, 1100,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
     }
    ]
   }
  }
 ]
}

E aqui está a imagem recortada.

Parabéns! Executou a API Cloud Vision Crop Hints para devolver as coordenadas da caixa delimitadora otimizadas em torno do objeto dominante detetado na imagem!