Transformers documentation

Detecção de objetos 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.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Detecção de objetos zero-shot

Tradicionalmente, os modelos usados para detecção de objetos exigem conjuntos de dados de imagens rotulados para o treinamento e são limitados à detecção do conjunto de classes dos dados de treinamento.

A detecção de objetos zero-shot é uma tarefa de visão computacional para detectar objetos e suas classes em imagens, sem nenhum treinamento prévio ou conhecimento das classes. Os modelos de detecção de objetos zero-shot recebem uma imagem como entrada, bem como uma lista de classes candidatas, e produzem as caixas delimitadoras e os rótulos onde os objetos foram detectados.

O Hugging Face abriga muitos desses detectores de objetos zero shot com vocabulário aberto.

Neste guia, você aprenderá a usar esses modelos:

  • para detectar objetos com base em prompts de texto
  • para detecção de objetos em lote
  • para detecção de objetos guiada por imagem

Antes de começar, verifique se você tem todas as bibliotecas necessárias instaladas:

pip install -q transformers

Pipeline de detecção de objetos zero-shot

A maneira mais simples de testar a inferência com modelos é usá-la em um pipeline(). Instancie um pipeline para detecção de objetos zero-shot a partir de um checkpoint no 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")

Em seguida, escolha uma imagem em que você deseja detectar objetos. Aqui, usaremos a imagem da astronauta Eileen Collins, que faz parte do conjunto de dados Great Images da NASA.

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

Passe a imagem e os rótulos dos objetos candidatos a serem procurados para o pipeline. Aqui, passamos a imagem diretamente; outras opções adequadas incluem um caminho local para uma imagem ou uma URL de imagem. Também passamos descrições em texto para todos os itens que queremos consultar na imagem.

>>> 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}}]

Vamos visualizar as previsões:

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

Detecção de objetos zero-shot com prompt de texto, feita manualmente

Agora que você viu como usar o pipeline de detecção de objetos zero-shot, vamos replicar o mesmo resultado manualmente.

Comece carregando o modelo e o processador associado de um checkpoint no Hugging Face Hub. Aqui, usaremos o mesmo checkpoint de antes:

>>> from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection

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

Vamos usar uma imagem diferente para variar.

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

Use o processor para preparar as entradas para o modelo.

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

Passe as entradas pelo modelo, faça o pós-processamento e visualize os resultados. Como o processador de imagens redimensionou as imagens antes de enviá-las ao modelo, você precisa usar o método post_process_object_detection para garantir que as caixas delimitadoras previstas tenham as coordenadas corretas em relação à imagem original:

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

Processamento em lote

Você pode passar vários conjuntos de imagens e consultas de texto para buscar objetos diferentes (ou os mesmos) em várias imagens. Vamos usar uma imagem de um astronauta e a imagem da praia juntos. Para processamento em lote, você deve passar as consultas de texto como uma lista aninhada para o processador e as imagens como listas de imagens PIL, tensors do PyTorch ou arrays 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)

Anteriormente, para o pós-processamento, você passava o tamanho da imagem única como um tensor, mas também pode passar uma tupla ou, no caso de várias imagens, uma lista de tuplas. Vamos criar previsões para os dois exemplos e visualizar o segundo (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,
... )

Vamos visualizar os resultados:

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

Detecção de objetos guiada por imagem

Além da detecção de objetos zero-shot com consultas de texto, modelos como OWL-ViT e OWLv2 oferecem detecção de objetos guiada por imagem. Isso significa que você pode usar uma consulta de imagem para encontrar objetos semelhantes na imagem de destino.

>>> from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection

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

Diferentemente das consultas de texto, apenas uma única imagem de exemplo é permitida.

Vamos usar uma imagem com dois gatos em um sofá como imagem de referência e uma imagem de um único gato como consulta:

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

Vamos dar uma olhada rápida nas imagens:

>>> import matplotlib.pyplot as plt

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

Na etapa de pré-processamento, em vez de consultas de texto, você agora precisa usar query_images:

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

Para as previsões, em vez de passar as entradas para o modelo, passe-as para image_guided_detection(). Desenhe as previsões como antes, exceto que agora não há rótulos.

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