剪裁提示教程

受众

本教程旨在帮助您开发具有 Vision API 裁剪提示功能的应用。本教程假定您熟悉基本的编程结构和技术。不过,即使您是初级程序员,也应该能够毫不费力地根据本教程进行操作,然后使用 Vision API 参考文档创建基本应用。

本教程将逐步介绍一个 Vision API 应用,展示如何通过调用 Vision API 来使用其剪裁提示功能。

前提条件

Python

概览

本教程介绍了一个使用 Crop Hints 请求的基本 Vision API 应用。您可以通过 Cloud Storage URI(Cloud Storage 存储分区位置)提供要处理的图片,也可以将该图片嵌入到相应请求中。如果 Crop Hints 响应成功,则会返回围绕图片中的主要对象或面孔剪裁的边界框的坐标。

代码清单

我们建议您在阅读代码时参照 Cloud Vision API 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)

深入了解

导入库

import argparse

from typing import MutableSequence

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

导入标准库:

  • argparse:允许应用接受输入文件名作为参数
  • io:用于文件输入/输出

其他导入:

  • google.cloud.vision 库中的 ImageAnnotatorClient 类,用于访问 Vision API。
  • google.cloud.vision 库中的 types 模块,用于构建请求。
  • Python Imaging Library (PIL) 中的 ImageImageDraw 模块用于在输入图片上绘制边界框。

运行应用

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)

在这里,我们仅解析用于指定本地图片文件名的传入参数,并将其传递给函数,以剪裁相应图片或绘制提示。

向 API 进行身份验证

您必须先使用先前获得的凭据向 Vision API 服务进行身份验证,然后才能与该服务通信。在应用中,获取凭据的最简单方法是使用应用默认凭据 (ADC)。默认情况下,客户端库将尝试从 GOOGLE_APPLICATION_CREDENTIALS 环境变量获取凭据,该变量应设置为指向您的服务账号的 JSON 密钥文件(如需了解详情,请参阅设置服务账号)。

获取图片的剪裁提示注释

由于 Vision 客户端库已通过身份验证,因此我们可以通过调用 ImageAnnotatorClient 实例的 crop_hints 方法来访问该服务。输出的宽高比在 ImageContext 对象中指定;如果传入了多个宽高比,则会返回多个剪裁提示(每个宽高比对应一个剪裁提示)。

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

客户端库将对向 API 发出请求以及获得响应的相关详细信息进行封装。如需全面了解请求的结构,请参阅 Vision API 参考

使用响应剪裁或绘制提示的边界框

操作成功完成后,API 响应将包含一个或多个 cropHints 的边界框坐标。draw_hint 方法会围绕 CropHints 边界框绘制线条,然后将图片写入 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")

crop_to_hint 方法使用建议的剪裁提示来剪裁图片。

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

运行应用

要运行该应用,您可以下载此 cat.jpg 文件(可能需要右键点击该链接),然后将本地机器上的文件下载目标位置传递给本教程中的应用 (crop_hints.py)。

以下是相应的 Python 命令,后跟显示 JSON cropHintsAnnotation 响应的控制台输出。此响应包含 cropHints 边界框的坐标。我们请求了宽高比为 1.77 的剪裁区域,返回的剪裁矩形的左上和右下 x 轴、y 轴坐标分别是 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
     }
    ]
   }
  }
 ]
}

以下是剪裁后的图片。

恭喜!您已运行 Cloud Vision Crop Hints API,返回了围绕图片中检测到的主要对象且经过优化的边界框坐标!