クロップヒントのチュートリアル

対象

このチュートリアルの目的は、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: ファイル I/O

その他のインポート:

  • google.cloud.vision ライブラリ内の ImageAnnotatorClient クラス: Vision API へのアクセスを提供する
  • google.cloud.vision ライブラリ内の types モジュール: リクエストを作成する
  • Python Imaging Library(PIL)の Image モジュールと ImageDraw モジュール。入力画像に境界ボックスを描画します。

アプリケーションの実行

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 オブジェクトの中で指定します。複数のアスペクト比を渡した場合は、アスペクト比ごとに 1 つずつ、複数のクロップヒントが返されます。

"""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 レスポンスには 1 つ以上の 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 クロップヒント API を実行し、画像内に検出された主要オブジェクトの周囲の最適化境界ボックス座標が返されました。