Transformers documentation
Détection d'objets en zéro tir
Détection d'objets en zéro tir
Traditionnellement, les modèles utilisés pour la détection d'objets nécessitent des jeux de données d'images étiquetées pour l'entraînement, et sont limités à la détection de l'ensemble des classes présentes dans les données d'entraînement.
La détection d’objets en zéro tir est une tâche de vision par ordinateur visant à détecter des objets et leurs classes dans des images, sans entraînement préalable ni connaissance des classes. Les modèles de détection d’objets en zéro tir reçoivent en entrée une image ainsi qu’une liste de classes candidates, et produisent en sortie les boîtes englobantes et les étiquettes des objets détectés.
Hugging Face héberge de nombreux détecteurs d'objets à vocabulaire ouvert et sans étiquetage de ce type.
Dans ce guide, vous apprendrez comment utiliser ce type de modèles :
- pour détecter des objets à partir de prompts textuels
- pour la détection d'objets par lot
- pour la détection d'objets guidée par image
Avant de commencer, assurez-vous d'avoir installé toutes les bibliothèques nécessaires :
pip install -q transformers
Pipeline de détection d'objets en zéro-shot
La manière la plus simple d’essayer l’inférence avec des modèles est de l’utiliser dans un pipeline(). Instanciez un pipeline pour la détection d’objets zéro-shot à partir d’un point de contrôle sur le 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")Ensuite, choisissez une image dans laquelle vous souhaitez détecter des objets. Nous utiliserons ici l’image de l’astronaute Eileen Collins, qui fait partie du jeu de données Great Images de la 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
Transmettez l’image ainsi que les étiquettes d’objets candidats à rechercher au pipeline. Ici, nous transmettons l’image directement ; d’autres options appropriées incluent un chemin local vers une image ou une URL d’image. Nous transmettons également des descriptions textuelles pour tous les éléments que nous souhaitons interroger dans l’image.
>>> 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}}]Visualisons les prédictions :
>>> 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
Détection d'objets zéro-shot guidée par texte, manuellement
Maintenant que vous avez vu comment utiliser le pipeline de détection d'objets en zéro tir, reproduisons manuellement le même résultat.
Commencez par charger le modèle et le processeur associés depuis un point de contrôle sur le Hugging Face Hub. Ici, nous utiliserons le même point de contrôle que précédemment :
>>> from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection
>>> model = AutoModelForZeroShotObjectDetection.from_pretrained(checkpoint, device_map="auto")
>>> processor = AutoProcessor.from_pretrained(checkpoint)Prenons une autre image pour changer.
>>> url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/zero-sh-obj-detection_3.png"
>>> image = load_image(url)
>>> image
Utilisez le processeur pour préparer les entrées du modèle.
>>> text_labels = ["hat", "book", "sunglasses", "camera"]
>>> inputs = processor(text=text_labels, images=image, return_tensors="pt").to(model.device)Faites passer les entrées à travers le modèle, effectuez le post-traitement et visualisez les résultats. Comme le processeur d’images a redimensionné les images avant de les transmettre au modèle, vous devez utiliser la méthode post_process_object_detection pour vous assurer que les boîtes englobantes prédites ont les coordonnées correctes par rapport à l’image d’origine :
>>> 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
Traitement par lots
Vous pouvez transmettre plusieurs ensembles d’images et de requêtes textuelles pour rechercher des objets différents (ou identiques) dans plusieurs images. Utilisons ensemble une image d’astronaute et l’image de plage. Pour le traitement par lots, vous devez transmettre les requêtes textuelles sous forme de liste imbriquée au processeur, et les images sous forme de listes d’images PIL, de tenseurs PyTorch ou de tableaux 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)Jusqu’ici, pour le post-traitement, vous passiez la taille de l’image unique sous forme de tenseur, mais vous pouvez également passer un tuple, ou, dans le cas de plusieurs images, une liste de tuples. Créons des prédictions pour les deux exemples et visualisons le second (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,
... )Visualisons les résultats :
>>> 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]
Détection d'objets guidée par image
En plus de la détection d'objets en zéro tir avec des requêtes textuelles, des modèles comme OWL-ViT et OWLv2 proposent la détection d'objets guidée par image. Cela signifie que vous pouvez utiliser une requête image pour trouver des objets similaires dans l'image cible.
>>> from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection
>>> checkpoint = "google/owlv2-base-patch16-ensemble"
>>> model = AutoModelForZeroShotObjectDetection.from_pretrained(checkpoint, device_map="auto")
>>> processor = AutoProcessor.from_pretrained(checkpoint)Contrairement aux requêtes textuelles, une seule image d’exemple est autorisée.
Prenons une image avec deux chats sur un canapé comme image cible, et une image d’un seul chat comme requête :
>>> 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)Jetons un rapide coup d’œil aux images :
>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(1, 2)
>>> ax[0].imshow(image_target)
>>> ax[1].imshow(query_image)
>>> fig.show()
À l'étape de prétraitement, vous devez désormais utiliser query_images au lieu de requêtes textuelles :
>>> inputs = processor(images=image_target, query_images=query_image, return_tensors="pt")Pour les prédictions, au lieu de passer les entrées au modèle, passez-les à image_guided_detection(). Dessinez les prédictions comme avant, sauf qu'il n'y a plus d'étiquettes.
>>> 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