裁剪提示教學課程

目標對象

本教學課程的目標是協助您使用 Vision API 的裁剪提示功能開發應用程式。並假設您熟悉基本的程式設計建構和技術。不過,即使您是程式設計新手,也應該能輕鬆跟著操作並執行本教學課程,然後使用 Vision API 參考說明文件建立基本應用程式。

本教學課程會逐步說明 Vision API 應用程式,並示範如何呼叫 Vision API 來使用裁剪提示功能。

必要條件

總覽

本教學課程會逐步說明如何使用 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 檔案 I/O

其他匯入項目:

  • 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 回應會包含一或多個 cropHint 的邊界方塊座標。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,傳回圖片中偵測到的主要物件周圍最佳化邊界框座標!