Transformers documentation
Zero-shot 객체 감지
Zero-shot 객체 감지
전통적으로 객체 감지에 사용되는 모델은 학습을 위해 라벨이 붙은 이미지 데이터셋이 필요하며, 학습 데이터에 포함된 클래스 집합 내에서만 감지가 가능합니다.
Zero-shot object detection은 사전 학습이나 클래스에 대한 사전 지식 없이 이미지에서 객체와 해당 클래스를 감지하는 컴퓨터 비전 작업입니다. Zero-shot object detection 모델은 이미지와 후보 클래스 목록을 입력으로 받아, 객체가 감지된 위치의 bounding box와 라벨을 출력합니다.
Hugging Face에는 이러한 오픈 보카불리 제로샷 객체 감지기가 많이 있습니다.
이 가이드에서는 이러한 모델을 사용하는 방법을 배웁니다:
- 텍스트 프롬프트를 기반으로 객체를 감지
- 배치 객체 감지
- 이미지 기반 객체 감지를 위한
시작하기 전에 필요한 라이브러리가 모두 설치되어 있는지 확인하세요:
pip install -q transformers
Zero-shot 객체 감지 파이프라인
모델로 추론을 가장 간단하게 시도하는 방법은 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
이미지와 탐색할 후보 객체 라벨을 pipeline에 전달합니다. 여기서는 이미지를 직접 전달하지만, 이미지 로컬 경로나 이미지 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
수동으로 텍스트 프롬프트 기반 제로샷 객체 감지
zero-shot object detection 파이프라인 사용법을 확인했으니, 이제 동일한 결과를 수동으로 재현해 보겠습니다.
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
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
배치 처리
여러 이미지에 대해 서로 다른(또는 동일한) 객체를 검색하기 위해 여러 세트의 이미지와 텍스트 쿼리를 전달할 수 있습니다. 천체 비행사 이미지와 해변 이미지를 함께 사용해 보겠습니다. 배치 처리를 수행하려면, 프로세서에 텍스트 쿼리를 중첩 리스트로 전달하고, 이미지는 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]
이미지 기반 객체 감지
텍스트 쿼리를 이용한 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()
전처리 단계에서는 텍스트 쿼리 대신 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