Тексто-управляемые модели детекции: OmDet‑Turbo vs Grounding DINO
В последние годы модели открытого словаря (open‑vocabulary) произвели революцию в компьютерном зрении, позволив детектировать объекты, не входящие в обучающую выборку. Два ярких представителя этого класса — OmDet‑Turbo (OM‑AI Lab) и Grounding DINO (IDEA Research). Обе модели принимают на вход произвольный текстовый запрос и изображение, возвращая ограничивающие рамки для указанных объектов. Рассмотрим данные модели по той причине, что обе они распространяются под лицензией Apache 2.0, в отличие от модели распространения YOLO.
Точность моделей

Наиболее интересна возможность использования в условиях, близких к реальному времени, поэтому рассматриваем tiny модели. Это модели:
Тестирование
import time
import torch
import requests
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
from transformers import AutoProcessor, OmDetTurboForObjectDetection
# Загрузка процессора и модели (пока на CPU, потом перенесём)
processor = AutoProcessor.from_pretrained("omlab/omdet-turbo-swin-tiny-hf")
model = OmDetTurboForObjectDetection.from_pretrained(
"omlab/omdet-turbo-swin-tiny-hf",
low_cpu_mem_usage=False # для совместимости с timm
)
model.eval()
# Загрузка тестового изображения
url = "http://images.cocodataset.org/val2017/000000039769.jpg"
image = Image.open(requests.get(url, stream=True).raw).convert("RGB")
classes = ["cat", "remote"]
def measure_inference_time(model, processor, image, classes, device, num_runs=20, warmup=5):
"""Замеряет среднее время инференса на указанном устройстве."""
model = model.to(device)
# Подготовка данных (процессор сам приведёт к 640×640)
inputs = processor(images=image, text=classes, return_tensors="pt").to(device)
# Прогрев
with torch.no_grad():
for _ in range(warmup):
_ = model(**inputs)
# Синхронизация для GPU
if device.type == 'cuda':
torch.cuda.synchronize()
start = time.perf_counter()
for _ in range(num_runs):
with torch.no_grad():
_ = model(**inputs)
if device.type == 'cuda':
torch.cuda.synchronize()
end = time.perf_counter()
return (end - start) / num_runs
# Сравнение
if torch.cuda.is_available():
print("Сравнение CPU и GPU")
print("-" * 40)
# CPU
cpu_time = measure_inference_time(model, processor, image, classes, torch.device('cpu'))
print(f"CPU: {cpu_time:.4f} сек/кадр")
# GPU
gpu_time = measure_inference_time(model, processor, image, classes, torch.device('cuda'))
print(f"GPU: {gpu_time:.4f} сек/кадр")
print(f"Ускорение GPU: {cpu_time / gpu_time:.2f}x")
else:
print("CUDA недоступна, выполняем только на CPU")
cpu_time = measure_inference_time(model, processor, image, classes, torch.device('cpu'))
print(f"CPU: {cpu_time:.4f} сек/кадр")
# Визуализация детекций (на GPU, если доступен)
def visualize_detections(image, processor, model, classes, threshold=0.3):
device = next(model.parameters()).device
inputs = processor(images=image, text=classes, return_tensors="pt").to(device)
with torch.no_grad():
outputs = model(**inputs)
results = processor.post_process_grounded_object_detection(
outputs,
target_sizes=[(image.height, image.width)],
text_labels=classes,
threshold=threshold,
nms_threshold=0.3,
)
result = results[0]
boxes, scores, text_labels = result["boxes"], result["scores"], result["text_labels"]
fig, ax = plt.subplots(1, figsize=(10, 10))
ax.imshow(image)
for box, score, text_label in zip(boxes, scores, text_labels):
x1, y1, x2, y2 = box.tolist()
rect = patches.Rectangle(
(x1, y1), x2 - x1, y2 - y1,
linewidth=2, edgecolor='red', facecolor='none'
)
ax.add_patch(rect)
ax.text(x1, y1 - 5, f"{text_label} {score:.2f}",
color='red', fontsize=12, backgroundcolor='white')
ax.axis('off')
plt.show()
# Покажем результат на GPU, если он есть, иначе на CPU
model.to(torch.device('cuda' if torch.cuda.is_available() else 'cpu'))
visualize_detections(image, processor, model, classes)
Результат на i7-6700K и NVIDIA RTX 2080 Super:
CPU: 1.2375 сек/кадр
GPU: 0.0442 сек/кадр
Ускорение GPU: 28.02x

Для grounding-dino-tiny проводилось 2 теста. Для изображения 640x640:
GPU: среднее = 0.1971 сек
CPU: среднее = 6.0049 сек
Ускорение GPU: 27.28x
Для изображения 224x224:
GPU: среднее = 0.0933 сек
CPU: среднее = 0.8232 сек
Ускорение GPU: 8.82x
Результаты
Даже если брать маленькое изображение, то grounding-dino-tiny на GPU намного медленнее:
0.0933 сек против 0.0442 сек
При этом на CPU быстрее:
0.8232 сек против 1.2375 сек
При снижении входного размера до 224×224 мы наблюдаем незначительное падение качества детекции: объекты мелкого размера (например, пульт на стандартном изображении) становятся менее уверенными, но крупные (кошка) по‑прежнему распознаются хорошо. Однако модели при этом на CPU ненамного быстрее, что не позволяет ее использовать в около-реальном времени.
Поэтому для коммерческого продукта, близкого к работе в реальном времени остается лишь использовать OmDet‑Turbo на GPU. Yolo может работать быстрее, но лицензия там не позволяет включить ее в закрытый монолитный продукт.
