Buckets:

hf-doc-build/doc / transformers /main /ja /tasks /zero_shot_object_detection.md
mishig's picture
|
download
raw
11.8 kB

ゼロショット物体検出

従来、オブジェクト検出に使用されるモデルは、学習のためにラベル付きの画像データセットを必要とし、検出できるクラスは学習データに含まれるクラスに限定されていました。

Zero-shot object detection(ゼロショットオブジェクト検出)は、クラスに関する事前の学習や知識なしに、画像内のオブジェクトとそのクラスを検出するコンピュータビジョンのタスクです。Zero-shot object detectionモデルは、画像と候補クラスのリストを入力として受け取り、検出されたオブジェクトのbounding box(バウンディングボックス)とラベルを出力します。

Hugging Face には、このような オープンボキャブラリーのゼロショットオブジェクト検出器 が多数あります。

このガイドでは、このようなモデルの使用方法を学びます。

  • テキストプロンプトに基づいてオブジェクトを検出するために
  • バッチオブジェクト検出
  • 画像誘導型オブジェクト検出

開始前に、必要なライブラリがすべてインストールされていることを確認してください。

pip install -q transformers

ゼロショットオブジェクト検出パイプライン

モデルで推論を試す最も簡単な方法は、pipeline()でそれを使用することです。Hugging Face Hub上のチェックポイントから、ゼロショットオブジェクト検出のパイプラインをインスタンス化します:

>>> from transformers import pipeline

>>> # Use any checkpoint from the hf.co/models?pipeline_tag=zero-shot-object-detection
>>> checkpoint = "iSEE-Laboratory/llmdet_large"
>>> detector = pipeline(model=checkpoint, task="zero-shot-object-detection")

次に、オブジェクトを検出したい画像を選択します。ここでは、NASA Great Images データセットに含まれる、アストロノートの Eileen Collins の画像を使用します。

>>> from transformers.image_utils import load_image

>>> url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/zero-sh-obj-detection_1.png"
>>> image = load_image(url)
>>> image

パイプラインに、画像と検索対象の候補オブジェクトラベルを渡します。ここでは画像を直接渡していますが、他の適切なオプションとしては、画像へのローカルパスや画像のURLなどが挙げられます。また、画像に対してクエリしたいすべてのアイテムのテキスト説明も渡します。

>>> predictions = detector(
...     image,
...     candidate_labels=["human face", "rocket", "nasa badge", "star-spangled banner"],
...     threshold=0.45,
... )
>>> predictions
[{'score': 0.8409242033958435,
  'label': 'human face',
  'box': {'xmin': 179, 'ymin': 74, 'xmax': 272, 'ymax': 179}},
 {'score': 0.7380027770996094,
  'label': 'rocket',
  'box': {'xmin': 353, 'ymin': 0, 'xmax': 466, 'ymax': 284}},
 {'score': 0.5850900411605835,
  'label': 'star-spangled banner',
  'box': {'xmin': 0, 'ymin': 0, 'xmax': 96, 'ymax': 511}},
 {'score': 0.5697067975997925,
  'label': 'human face',
  'box': {'xmin': 18, 'ymin': 15, 'xmax': 366, 'ymax': 511}},
 {'score': 0.47813931107521057,
  'label': 'star-spangled banner',
  'box': {'xmin': 353, 'ymin': 0, 'xmax': 459, 'ymax': 274}},
 {'score': 0.46597740054130554,
  'label': 'nasa badge',
  'box': {'xmin': 353, 'ymin': 0, 'xmax': 462, 'ymax': 279}},
 {'score': 0.4585932493209839,
  'label': 'nasa badge',
  'box': {'xmin': 132, 'ymin': 348, 'xmax': 208, 'ymax': 423}}]

予測を可視化してみましょう:

>>> from PIL import ImageDraw

>>> draw = ImageDraw.Draw(image)

>>> for prediction in predictions:
...     box = prediction["box"]
...     label = prediction["label"]
...     score = prediction["score"]

...     xmin, ymin, xmax, ymax = box.values()
...     draw.rectangle((xmin, ymin, xmax, ymax), outline="red", width=1)
...     draw.text((xmin, ymin), f"{label}: {round(score,2)}", fill="white")

>>> image

手動によるテキストプロンプト付きゼロショットオブジェクト検出

ゼロショットオブジェクト検出パイプラインの使い方を確認したので、ここでは同じ結果を手動で再現します。

Hugging Face Hub上のチェックポイントからモデルと関連するプロセッサを読み込むことから始めます。ここでは、以前と同じチェックポイントを使用します:

>>> from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection

>>> model = AutoModelForZeroShotObjectDetection.from_pretrained(checkpoint, device_map="auto")
>>> processor = AutoProcessor.from_pretrained(checkpoint)

気分転換に、別の画像を使ってみましょう。

>>> url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/zero-sh-obj-detection_3.png"
>>> image = load_image(url)
>>> image

プロセッサを使用して、モデルの入力を準備します。

>>> text_labels = ["hat", "book", "sunglasses", "camera"]
>>> inputs = processor(text=text_labels, images=image, return_tensors="pt").to(model.device)

入力をモデルに通し、後処理を実行して、結果を可視化します。画像プロセッサはモデルに渡す前に画像をリサイズするため、予測されたバウンディングボックスが元の画像に対して正しい座標を持つことを確認するには、post_process_object_detection メソッドを使用する必要があります:

>>> import torch

>>> with torch.inference_mode():
...     outputs = model(**inputs)

>>> results = processor.post_process_grounded_object_detection(
...    outputs, threshold=0.50, target_sizes=[(image.height, image.width)], text_labels=text_labels,
... )[0]

>>> draw = ImageDraw.Draw(image)

>>> scores = results["scores"]
>>> text_labels = results["text_labels"]
>>> boxes = results["boxes"]

>>> for box, score, text_label in zip(boxes, scores, text_labels):
...     xmin, ymin, xmax, ymax = box
...     draw.rectangle((xmin, ymin, xmax, ymax), outline="red", width=1)
...     draw.text((xmin, ymin), f"{text_label}: {round(score.item(),2)}", fill="white")

>>> image

バッチ処理

複数の画像セットとテキストクエリを渡すことで、複数の画像内の異なる(または同じ)オブジェクトを検索できます。ここでは、宇宙飛行士の画像とビーチの画像を一緒に使用します。バッチ処理を行う場合は、テキストクエリをネストされたリストとしてプロセッサに渡し、画像はPIL画像、PyTorchテンソル、またはNumPy配列のリストとして渡す必要があります。

>>> url1 = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/zero-sh-obj-detection_1.png"
>>> url2 = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/zero-sh-obj-detection_3.png"
>>> images = [load_image(url1), load_image(url2)]
>>> text_queries = [
...     ["human face", "rocket", "nasa badge", "star-spangled banner"],
...     ["hat", "book", "sunglasses", "camera", "can"],
... ]
>>> inputs = processor(text=text_queries, images=images, return_tensors="pt", padding=True)

以前は後処理で単一の画像のサイズをテンソルとして渡していましたが、タプルを渡すことも、複数の画像の場合はタプルのリストを渡すこともできます。2つの例について予測を作成し、2番目のもの(image_idx = 1)を可視化してみましょう。

>>> with torch.no_grad():
>>>     outputs = model(**inputs)

>>> target_sizes = [(image.height, image.width) for image in images]
>>> results = processor.post_process_grounded_object_detection(
...     outputs, threshold=0.3, target_sizes=target_sizes, text_labels=text_labels,
... )

結果を可視化してみましょう:

>>> image_idx = 1
>>> draw = ImageDraw.Draw(images[image_idx])

>>> scores = results[image_idx]["scores"].tolist()
>>> text_labels = results[image_idx]["text_labels"]
>>> boxes = results[image_idx]["boxes"].tolist()

>>> for box, score, text_label in zip(boxes, scores, text_labels):
>>>     xmin, ymin, xmax, ymax = box
>>>     draw.rectangle((xmin, ymin, xmax, ymax), outline="red", width=1)
>>>     draw.text((xmin, ymin), f"{text_label}: {round(score,2)}", fill="white")

>>> images[image_idx]

画像ガイドによる物体検出

テキストクエリによるゼロショットオブジェクト検出に加えて、OWL-ViT や OWLv2 などのモデルは、画像ガイドによるオブジェクト検出も提供しています。これにより、画像クエリを使用して、ターゲット画像内の類似オブジェクトを検出できます。

>>> from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection

>>> checkpoint = "google/owlv2-base-patch16-ensemble"
>>> model = AutoModelForZeroShotObjectDetection.from_pretrained(checkpoint, device_map="auto")
>>> processor = AutoProcessor.from_pretrained(checkpoint)

テキストクエリとは異なり、例として使用できる画像は1枚のみです。

ソファに2匹の猫が写っている画像をターゲット画像とし、1匹の猫が写っている画像をクエリとして設定します。

>>> url = "http://images.cocodataset.org/val2017/000000039769.jpg"
>>> image_target = Image.open(requests.get(url, stream=True).raw)

>>> query_url = "http://images.cocodataset.org/val2017/000000524280.jpg"
>>> query_image = Image.open(requests.get(query_url, stream=True).raw)

画像を簡単に確認してみましょう:

>>> import matplotlib.pyplot as plt

>>> fig, ax = plt.subplots(1, 2)
>>> ax[0].imshow(image_target)
>>> ax[1].imshow(query_image)
>>> fig.show()

前処理ステップでは、テキストクエリではなく、query_imagesを使用する必要があります:

>>> inputs = processor(images=image_target, query_images=query_image, return_tensors="pt")

予測を行う場合は、入力をモデルに渡す代わりに、image_guided_detection()に渡します。予測結果は以前と同様に描画しますが、今回はラベルがありません。

>>> with torch.no_grad():
...     outputs = model.image_guided_detection(**inputs)
...     target_sizes = torch.tensor([image_target.size[::-1]])
...     results = processor.post_process_image_guided_detection(outputs=outputs, target_sizes=target_sizes)[0]

>>> draw = ImageDraw.Draw(image_target)

>>> scores = results["scores"].tolist()
>>> boxes = results["boxes"].tolist()

>>> for box, score in zip(boxes, scores):
...     xmin, ymin, xmax, ymax = box
...     draw.rectangle((xmin, ymin, xmax, ymax), outline="white", width=4)

>>> image_target

Xet Storage Details

Size:
11.8 kB
·
Xet hash:
9ca3f84e15c2f3161b713ef4b212cb37325dec0ce70080606967ebd7b5df677c

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.