Dieser Bereich ist derzeit nur auf Englisch verfügbar.
Kerndokumentation
Experimentelle Stufe

LibreVLM

Richte ein Vision-Language-Modell auf ein Bild, übergib ihm eine Liste von Wörtern und erhalte Boxen zurück. LibreVLM verwandelt Qwen3-VL, Florence-2 und ähnliche Modelle in Open-Vocabulary-Objektdetektoren, die exakt dieselbe Results-API wie jedes andere LibreYOLO-Modell verwenden.

Einführung

Ein klassischer Detektor wird mit einer festen, in seinen Head eingebauten Klassenliste ausgeliefert. LibreVLM hebt diese Einschränkung auf. Es bindet moderne, auf Anweisungen abgestimmte Vision-Language-Modelle ein, fordert sie zur Ausgabe von Bounding Boxes auf, parst den generierten Text und gibt dasselbe Results-Objekt zurück, das du bereits für YOLO9 und RF-DETR nutzt. Die Klassenliste ist lediglich eine Liste von Wörtern, die du zur Laufzeit übergibst. Das Hinzufügen einer neuen Kategorie kostet daher nichts und funktioniert per Zero-Shot.

  • Offenes Vokabular. Erkenne "pink car", "license plate" oder "the small island", ohne je einen Head dafür zu trainieren.
  • Eine Factory, ein Vertrag. LibreVLM(...) gibt die standardmäßigen Results mit boxes.xyxy, boxes.cls und boxes.conf sowie .plot() und .save() zurück.
  • Austauschbare Backends. Sechs Modellfamilien hinter einem Alias-String, von Florence-2 mit 230M bis Qwen3-VL mit 8B.
  • Ein direkter Ausweg. chat() ermöglicht freie Fragen zu Bildern, wenn du mehr als Boxen brauchst.

Warum eine eigene Stufe und eine eigene Seite?

LibreVLM bleibt bewusst außerhalb der Closed-Vocabulary-Factory LibreYOLO(...) und ihrer .pt-Registry. Diese Modelle werden von Prompts gesteuert, arbeiten mit offenem Vokabular und geben synthetische Confidence aus. Deshalb erfüllen sie einen anderen Vertrag. Eine eigene Stufe hält die Kerndokumentation zur Erkennung übersichtlich und macht transparent, was tatsächlich gemessen wird.

Auf dem dev-Branch

LibreVLM befindet sich derzeit auf dem Branch dev und ist für das Release v1.3 vorgesehen. Es ist nicht Teil von v1.2.0. Die Stufe bietet ausschließlich Python-Inferenz: Training, Validierung, Export und ein CLI-Pfad fehlen noch, und die Confidence-Werte sind Platzhalter. Lies den Abschnitt Einschränkungen, bevor du darauf aufbaust.

Installation

LibreVLM ist über das optionale Extra vlm verfügbar. Es installiert eine aktuelle Version von transformers und die Hilfsbibliotheken, die einige Prozessoren benötigen. Ohne das Extra löst der Import einer VLM-Familie einen ImportError aus, der auf diese Stelle verweist.

bash
1pip install 'libreyolo[vlm]'

Die Gewichte werden bei der ersten Verwendung vom Hugging Face Hub in einen lokalen Ordner weights/ heruntergeladen. Einige Familien werden unter Nicht-OSI-Lizenzen ausgeliefert und protokollieren vor dem Download einmalig einen Hinweis. Für die größeren Backends wird eine GPU empfohlen, aber mit device="cpu" läuft jedes Modell auch auf der CPU.

Schnellstart

Erstelle ein Modell, gib die relevanten Wörter an und führe die Vorhersage aus. Das Standard-Backend ist Qwen3-VL-4B, der stärkste Detektor dieser Stufe unter Apache-2.0-Lizenz.

python
1from libreyolo import LibreVLM
2
3# Qwen3-VL-4B by default; weights autodownload on first use
4model = LibreVLM()
5
6# The vocabulary is just words. Any words.
7model.set_classes(["pink car", "wheel"])
8
9result = model.predict("street.jpg")
10
11print(result.boxes.xyxy) # pixel [x1, y1, x2, y2]
12print(result.boxes.cls) # ids into ["pink car", "wheel"]
13result.plot() # same drawing helpers as any LibreYOLO model
14result.save("out.jpg")

Das ist der gesamte Ablauf. Alles nach predict() verhält sich wie bei einem normalen Detektor, deshalb funktionieren vorhandener Visualisierungs-, Zuschneide- und Tracking-Code weiterhin.

Unterstützte Modelle

Wähle ein Backend über den Alias, den du an LibreVLM(...) übergibst. Ein allein stehender Familienname wird auf seine Standardgröße aufgelöst. Das allgemeine Standard-Backend ist qwen3-vl-4b. In der Praxis sind Qwen3-VL, LFM2-VL und Florence-2 die stärksten Detektoren.

FamilieAliasnameGrößen (Parameter)LizenzHinweise
Qwen3-VLqwen3-vl-2b / -4b / -8b2B / 4B / 8BApache-2.0Standard und stärkstes Modell. Als Einstieg empfohlen.
LFM2-VLlfm2-vl-450m / -1.6b450M / 1.6BLFM Open LicenseFür das Edge dimensioniert, überraschend starker kleiner Detektor. Hinweis erforderlich.
InternVL3internvl3-1b / -2b / -8b1B / 2B / 8BQwen LicenseGutes Grounding bei 8B, kleine Größen sind schwach. Hinweis erforderlich.
Florence-2florence-2-base / -large0.23B / 0.77BMITSpeziell entwickeltes Grounding-Modell. Enge Boxen, kein chat().
SmolVLM2smolvlm2-500m / -2.2b500M / 2.2BApache-2.0Winzig und schnell, aber schwächerer Detektor. Gut für schnelle Versuche.
Kosmos-2kosmos-2~1.6BMITGrounder aus dem Jahr 2023. Gröbere Boxen, kein chat().

Auswahl eines Backends

  • Beste Qualität: qwen3-vl-8b oder qwen3-vl-4b (Standard).
  • Enge Boxen, kleiner Ressourcenbedarf: florence-2-large.
  • Edge / CPU: lfm2-vl-450m oder smolvlm2-500m.
  • Vollständig permissive Lizenz: jede Größe von Qwen3-VL, SmolVLM2, Florence-2 oder Kosmos-2.

Lizenzierung

Qwen3-VL und SmolVLM2 stehen unter Apache-2.0, Florence-2 und Kosmos-2 unter MIT. LFM2-VL und InternVL3 tragen Nicht-OSI-Lizenzen und geben vor dem ersten Download einmalig einen Hinweis aus, damit du eine informierte Entscheidung zur kommerziellen Nutzung treffen kannst.

Festlegen des Vokabulars

Das Vokabular ist das Herzstück der Open-Vocabulary-Erkennung. Rufe set_classes() mit einer Liste von Label-Strings auf. Die Einstellung bleibt bestehen: Sie gilt für jeden späteren Aufruf von predict() und track(), bis du sie erneut setzt. Die Methode gibt self zurück und lässt sich daher verketten.

python
1# Sticky and chainable
2model = LibreVLM("qwen3-vl-2b").set_classes(["person", "dog", "cat"])
3
4# Set it once at construction instead
5model = LibreVLM("lfm2-vl-450m", names=["boat"], device="cpu")
6
7# Re-set any time to change what you are looking for
8model.set_classes(["a red car", "a blue truck"])

Labels können beliebige Wortgruppen sein. Sie müssen unabhängig von Groß- und Kleinschreibung eindeutig sein, und du musst eine Liste statt eines einzelnen Strings übergeben. Wenn du set_classes() nie aufrufst, greift das Modell auf das COCO-80-Vokabular zurück. So liefert auch ein allein stehendes predict() ein sinnvolles Ergebnis.

Vorhersage

predict() und der gleichwertige Aufruf model(...) akzeptieren dieselben Quelltypen wie jeder LibreYOLO-Detektor: einen Pfad, ein PIL-Bild, ein NumPy-Array, eine URL, einen Ordner oder ein Video. stream=True und track() funktionieren ebenfalls.

python
1result = model.predict(
2 source="image.jpg", # path | PIL | ndarray | URL | folder | video
3 conf=0.25, # see note below: scoring is synthetic
4 classes=[0], # optional: keep only these vocabulary ids
5 max_det=300,
6)

Rückgabeform

Du erhältst das standardmäßige Results-Objekt zurück, genau wie bei einem Closed-Vocabulary-Detektor:

FeldForm / TypBedeutung
result.boxes.xyxyN x 4Pixel-Boxen [x1, y1, x2, y2], auf das Originalbild skaliert.
result.boxes.clsNKlassen-IDs, die dein set_classes()-Vokabular indizieren.
result.boxes.confNSynthetische Confidence: 1.0 für jede Box (siehe Einschränkungen).
result.plot() / .save()-Die üblichen Hilfsfunktionen zum Zeichnen und Speichern.

Intern parst LibreVLM die Modellausgabe tolerant, einschließlich Markdown-Blöcken, verstreuter Prosa, doppelter Boxen und abgeschnittener Arrays. Es ordnet Freitext-Labels wieder deinen Klassen-IDs zu und verwirft jedes Label, das nicht in deinem Vokabular enthalten ist. Dieser letzte Schritt lässt einen freien Generator wie einen Closed-Set-Detektor arbeiten.

Beispiele

Ein Objekt mit einer bestimmten Farbe erkennen

python
1from libreyolo import LibreVLM
2
3model = LibreVLM("qwen3-vl-4b")
4model.set_classes(["red car"])
5
6result = model.predict("parking_lot.jpg")
7print(f"Found {len(result.boxes.cls)} red car(s)")
8result.save("red_cars.jpg")

Enge Boxen mit Florence-2

python
1# Florence-2 is a purpose-built grounder: very tight pixel boxes.
2model = LibreVLM("florence-2-large")
3model.set_classes(["a red car", "license plate"])
4
5result = model.predict("car.jpg")
6result.plot()

Dynamisch nach einer einzelnen Klasse filtern

python
1model = LibreVLM("qwen3-vl-2b").set_classes(["person", "dog", "cat"])
2
3# classes= filters the configured vocabulary by id
4people_only = model.predict("street.jpg", classes=[0])

Mit einem integrierten Beispielbild auf der CPU ausführen

python
1from libreyolo import LibreVLM, SAMPLE_IMAGE
2
3model = LibreVLM("lfm2-vl-450m", device="cpu")
4# No set_classes() -> falls back to the COCO-80 vocabulary
5result = model.predict(SAMPLE_IMAGE)
6print(model.names[result.boxes.cls[0]]) # e.g. "person"

Batches, Ordner und Videos

python
1model = LibreVLM().set_classes(["forklift", "pallet"])
2
3# A whole folder
4for result in model.predict("warehouse_frames/", stream=True):
5 result.save()
6
7# A video file (frames are processed one at a time)
8model.predict("warehouse.mp4", save=True)

Roher Chat

Manchmal brauchst du das Modell statt des Detektors. Die Chat-Template-Familien stellen chat() bereit. Die Methode nimmt ein Bild und einen freien Prompt entgegen und gibt den dekodierten Text unverändert zurück. Nutze sie zum Zählen, für Bildbeschreibungen oder für schnelle visuelle Fragen.

python
1model = LibreVLM("qwen3-vl-4b")
2
3answer = model.chat("harbor.jpg", "How many boats are docked? Answer with a number.")
4print(answer)

chat() ist für die Chat-Template-Familien Qwen3-VL, LFM2-VL, SmolVLM2 und InternVL3 verfügbar. Florence-2 und Kosmos-2 sind Task-Token-Grounder und lösen NotImplementedError aus. Nutze mit ihnen predict().

Unterschiede zwischen den Backends

Jede Familie gibt dieselben Results zurück, erreicht sie aber auf einem anderen Weg. Das ist selten wichtig, erklärt jedoch das Verhalten einiger Backends. Die Chat-Familien werden zur Ausgabe eines JSON-Arrays von Boxen aufgefordert, während die Grounder spezielle Task-Tokens verwenden.

FamiliePrompt-SteuerungKoordinatenraumchat()
Qwen3-VLJSON-Box-Prompt0 bis 1000, neu skaliertJa
LFM2-VLJSON-Box-PromptAuf 0 bis 1 normalisiertJa
SmolVLM2JSON-Box-PromptAuf 0 bis 1 normalisiertJa
InternVL3JSON-Box-Prompt0 bis 1000, neu skaliertJa
Florence-2Task-TokenNative PixelNein
Kosmos-2Grounding-PromptNormalisiert, neu skaliertNein

Bei den Chat-Familien kannst du den Erkennungs-Prompt mit dem Konstruktorargument prompt= überschreiben und die Generierungslänge mit max_new_tokens= begrenzen. Gerät und Datentyp werden automatisch bestimmt: bf16 oder fp16 unter CUDA, fp32 auf der CPU.

Einschränkungen

LibreVLM ist leistungsfähig, aber noch jung. Wenn du die Grenzen vorab kennst, vermeidest du spätere Überraschungen.

  • Synthetische Confidence. Jede Box erhält den Wert 1.0. Der Filter conf= verhält sich daher nach dem Alles-oder-nichts-Prinzip statt wie ein echter Schwellenwert.
  • Keine mAP / Validierung. val() löst einen Fehler aus, weil synthetische Werte die COCO-mAP irreführend machen würden.
  • Kein Training oder Export. train() und export() lösen Fehler aus. Führe stattdessen Upstream ein Fine-Tuning des VLM durch und lade die daraus entstandenen Gewichte.
  • Eingeschränktes Tracking. track() läuft, aber einheitliche Werte setzen die Wiederherstellungsstufe des Trackers für niedrige Confidence außer Kraft.
  • Jeweils ein Bild. In v1 läuft die Generierung sequenziell, deshalb bringen größere Werte für batch= keinen Geschwindigkeitsvorteil.
  • Nur Python-API. Die CLI libreyolo löst VLM-Aliasse noch nicht auf.

Stärken

Nutze LibreVLM, wenn die Klassenmenge offen ist, sich häufig ändert oder sich vorab nur schwer labeln lässt: für schnelles Prototyping, Long-Tail- oder seltene Kategorien und Workflows nach dem Muster „Finde das Objekt, das ich in Worten beschreibe“. Wenn du kalibrierte Confidence, Durchsatz oder ein ausrollbares Artefakt brauchst, trainiere ein Closed-Vocabulary-Modell wie YOLO9 oder RF-DETR aus der Kerndokumentation.

Nur Inferenzdev-Branch / Zielversion v1.3Quellcode auf GitHub