Transformers documentation

Обнаружение объектов в режиме zero-shot

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.2).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Обнаружение объектов в режиме zero-shot

Традиционно модели, используемые для обнаружения объектов, требуют размеченных наборов данных изображений для обучения и ограничены обнаружением набора классов, присутствующих в обучающих данных.

Zero-shot object detection — это задача компьютерного зрения, состоящая в обнаружении объектов и их классов на изображениях без какого-либо предварительного обучения или знаний о классах. Модели zero-shot object detection принимают на вход изображение, а также список кандидатов классов, и на выходе предоставляют ограничивающие рамки (bounding boxes) и метки, где были обнаружены объекты.

Hugging Face содержит множество таких детекторов объектов с открытым словарём и нулевой настройкой.

В этом руководстве вы узнаете, как использовать такие модели:

  • для обнаружения объектов на основе текстовых запросов
  • для пакетного обнаружения объектов
  • для обнаружения объектов с использованием изображений

Прежде чем начать, убедитесь, что у вас установлены все необходимые библиотеки:

pip install -q transformers

Пайплайн обнаружения объектов в режиме zero-shot

Самый простой способ попробовать инференс с моделями — использовать его в pipeline(). Создайте экземпляр пайплайна для zero-shot обнаружения объектов из чекпоинта на 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.

>>> 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
Astronaut Eileen Collins

Передайте в конвейер изображение и метки объектов, которые нужно найти. Здесь мы передаём изображение напрямую; другие допустимые варианты — локальный путь к изображению или 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
Visualized predictions on NASA image

Ручная детекция объектов в режиме zero-shot по текстовому промпту

Теперь, когда вы узнали, как использовать конвейер zero-shot обнаружения объектов, давайте воспроизведем тот же результат вручную.

Начните с загрузки модели и соответствующего процессора из чекпоинта на 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
Beach photo

Используйте processor для подготовки входных данных для модели.

>>> 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
Beach photo with detected objects

Пакетная обработка

Вы можете передавать несколько наборов изображений и текстовых запросов, чтобы искать разные (или одинаковые) объекты на нескольких изображениях. Используем вместе изображение астронавта и изображение пляжа. Для пакетной обработки текстовые запросы следует передавать процессору в виде вложенного списка, а изображения — в виде списков изображений 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)

Ранее для постобработки вы передавали размер одного изображения в виде тензора, но также можно передать кортеж, а в случае нескольких изображений — список кортежей. Создадим предсказания для двух примеров и визуализируем второй (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]
Beach photo with detected objects

Обнаружение объектов с использованием изображений

Помимо обнаружения объектов в режиме zero-shot по текстовым запросам, такие модели, как 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)

В отличие от текстовых запросов, допускается только одно изображение-пример.

Возьмём в качестве целевого изображения картинку с двумя кошками на диване, а в качестве запроса — изображение одной кошки:

>>> 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()
Cats

На этапе предобработки вместо текстовых запросов теперь необходимо использовать 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
Cats with bounding boxes
Update on GitHub