Detección de vocabulario abierto
La detección de vocabulario abierto sustituye la lista fija de clases de un checkpoint por las palabras que elijas en el momento de la llamada. En LibreYOLO no es una tarea aparte: es la tarea detect servida por un nivel de modelos aparte, que se carga mediante la factoría LibreOpenVocab en lugar de LibreYOLO.
Definición
La detección de vocabulario abierto devuelve Results de detección normales:
bounding boxes, confianzas e índices de clase, con result.names mapeando esos
índices de vuelta a las cadenas que pediste. Lo que cambia es de dónde sale la
lista de clases. Un detector convencional se entrena contra un conjunto fijo de
categorías y nunca puede emitir una categoría fuera de él. Estos modelos reciben
el vocabulario como texto en tiempo de inferencia, así que
set_classes(["forklift", "safety cone"]) basta para que esas sean las clases.
LibreYOLO no tiene una clave de tarea open-vocabulary. Estos modelos declaran
SUPPORTED_TASKS = ("detect",) como cualquier otro detector. Lo que los separa
es la ruta de carga: son snapshots de Hugging Face en lugar de checkpoints de
state-dict de LibreYOLO, así que quedan fuera de la factoría LibreYOLO() y se
construyen mediante LibreOpenVocab(). Esa factoría es hermana de LibreSAM()
y LibreVLM(), no un reemplazo de LibreYOLO().
Las puntuaciones son puntuaciones de detección reales, no un caption generado y parseado a posteriori. Cada familia puntúa regiones de la imagen contra el embedding de texto de cada prompt.
Modelos
Cuatro familias componen este nivel, y todas son solo de predicción. Carga
cualquiera de ellas por alias mediante LibreOpenVocab.
Grounding DINO, de IDEA Research, en tamaños t
y b. Es la opción por defecto del nivel, y la única familia que acepta
text_threshold, un segundo corte sobre la puntuación de tokens de la frase
decodificada.
OWLv2, de Google Research, en tamaños b16 y l14.
Puntúa regiones de la imagen contra embeddings de texto de un encoder tipo CLIP.
OMDet-Turbo, de Om AI Lab, en un único tamaño t.
Desacopla los embeddings de clase de un prompt de tarea en lenguaje natural, y
es la única familia aquí que suprime bounding boxes solapados dentro de su
propio post-procesado, así que iou= sí se respeta.
OV-DEIM, en tamaños s, m y l, un detector de tipo
DETR que empareja las queries del decoder con embeddings de texto de una torre
de texto MobileCLIP incluida. Usa emparejamiento uno a uno con selección top-K,
así que no se ejecuta NMS en ninguna parte.
Los pesos de OV-DEIM son el caso restringido de este nivel. Los pesos del
detector son CC BY-NC 4.0, no comercial. La torre de texto incluida está bajo la
Machine Learning Research Model license de Apple, solo para uso de
investigación. El checkpoint l añade un fine-tune de backbone DINOv3-S bajo la
DINOv3 License de Meta. Los tres textos de licencia van dentro del repositorio
de pesos, y la biblioteca registra el mismo resumen cuando resuelve los pesos,
antes de construir el modelo. Lee OV-DEIM antes de
desplegarlo.
Este nivel necesita un extra:
pip install "libreyolo[openvocab]"Eso cubre transformers y timm para las tres familias envueltas, y los
paquetes huggingface_hub, safetensors, regex y ftfy que OV-DEIM necesita
al ser un port nativo.
Hay un segundo nivel que también recibe un vocabulario de texto: LibreVLM()
carga modelos generativos de visión y lenguaje, como
Qwen3-VL y Florence-2, y
convierte su salida en los mismos Results. Comparte la superficie de
set_classes(). La diferencia está en qué produce los bounding boxes: las
familias de esta página son detectores discriminativos que emiten puntuaciones
directamente, mientras que el nivel de VLM los genera.
Predicción
from libreyolo import LibreOpenVocab, SAMPLE_IMAGE model = LibreOpenVocab("grounding-dino-t")model.set_classes(["person", "dog", "skateboard"]) result = model.predict(SAMPLE_IMAGE, conf=0.25)print(result.names)for box in result.boxes: print(box.cls, box.conf, box.xyxy)from libreyolo import LibreOpenVocab, SAMPLE_IMAGE model = LibreOpenVocab("owlv2-b16") # set_classes es persistente: se mantiene hasta la siguiente llamada.# Las etiquetas deben ser únicas en minúsculas y sin artículos.model.set_classes(["a red backpack", "traffic cone"])result = model.predict(SAMPLE_IMAGE) model.set_classes(["bicycle wheel"])result = model.predict(SAMPLE_IMAGE)from libreyolo import LibreOpenVocab, SAMPLE_IMAGE model = LibreOpenVocab("grounding-dino-b")model.set_classes(["remote control", "school bus"]) # conf filtra por la puntuación del box, y text_threshold por la# puntuación de tokens de la frase decodificada. Ambos valen 0.25 por# defecto. Solo Grounding DINO acepta text_threshold; los demás fallan.result = model.predict(SAMPLE_IMAGE, conf=0.25, text_threshold=0.3)set_classes() recibe una lista no vacía de cadenas de etiqueta y se mantiene
hasta que se vuelve a llamar. Las etiquetas deben ser únicas una vez pasadas a
minúsculas y sin los artículos iniciales, así que "a bus" y "bus" no pueden
coexistir en un mismo vocabulario. Las frases de varias palabras son etiquetas
como cualquier otra, y cada familia convierte la lista en su propia entrada de
texto antes de tokenizar, así que "traffic cone" es una query distinta de
"cone".
Tres argumentos de predicción se comportan aquí de forma distinta que en un
detector nativo. imgsz= se rechaza, porque el procesador se encarga del
redimensionado en estas familias. augment=True se rechaza, ya que el aumento
de datos en test queda fuera del alcance del nivel. iou= solo aplica a la
familia cuyo procesador ejecuta su propia supresión; donde no se suprime nada,
pasarlo genera un aviso y se ignora.
Si no se define, conf toma el valor por defecto de la familia cargada en lugar
del 0.25 habitual de predict(), y ese valor por defecto no es el mismo en todo
el nivel. Defínelo explícitamente cuando compares dos familias sobre la misma
imagen.
track() falla en todo el nivel. Ejecuta predict() por frame en su lugar.
Consulta predicción para fuentes, streaming y manejo de
resultados.
Entrenamiento
Ninguna familia de este nivel se entrena dentro de LibreYOLO. train() falla:
haz el fine-tuning upstream y carga los pesos resultantes. El vocabulario que
pasas a set_classes() es el único ajuste que cambia lo que detecta un modelo
cargado.
Validación
No hay validador para este nivel, y val() falla. La validación de vocabulario
abierto necesita uno dedicado, porque el validador de detección estándar pasa
tensores de imagen directamente al modelo, mientras que estas familias requieren
entradas condicionadas por texto construidas junto a ellos.
Exportación
La exportación queda fuera del alcance del nivel y export() falla. Estos
modelos se ejecutan mediante predict() en PyTorch.