Vorhersagequellen
Das Argument source wird klassifiziert, bevor etwas geöffnet wird. Ein Aufruf verarbeitet daher ein JPEG, einen Ordner, eine MP4-Datei, einen Webcam-Index, eine RTSP-URL, einen Bildschirmbereich oder eine Liste von Kameras.
Klassifizierung einer Quelle
classify_source untersucht den Wert in der folgenden Reihenfolge, bevor etwas geöffnet oder heruntergeladen wird. Die erste passende Regel gewinnt.
| Quelle | Interpretation |
|---|---|
"screen", "screen 1", "screen 1 100 200 512 256" | Bildschirmaufnahme |
Ein nicht negativer int oder eine Ziffernfolge, für die keine gleichnamige Datei existiert | Webcam |
Eine URL mit rtsp://, rtmp://, tcp:// oder udp:// | Netzwerkstream |
Eine http(s)://-URL, deren Pfad auf .m3u8 endet | Netzwerkstream |
| Eine YouTube-Seiten-URL | Netzwerkstream |
| Eine Liste oder ein Tupel, deren Einträge ausschließlich Live-Quellen oder Videos sind | Mehrere Live-Streams |
| Jede andere Liste oder jedes andere Tupel | Batch aus Bildern |
Ein Pfad mit der Endung .streams | Mehrere Live-Streams |
| Ein Pfad mit einer Videoendung | Videodatei |
| Ein vorhandenes Verzeichnis | Bilderordner |
| Alles andere | Einzelbild |
Eine Liste, die Live-Quellen mit Bildern mischt, löst TypeError aus. Ein negativer Webcam-Index löst ValueError aus.
Der Klassifikator greift nie auf das Netzwerk zu. Eine falsch geschriebene URL fällt daher erst beim Öffnen der Aufnahme und nicht beim Aufruf von predict auf.
Bilder
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") # Eine einzelne Bildquelle gibt ein Results-Objekt und keine Liste zurück.result = model(SAMPLE_IMAGE)print(len(result.boxes), "detections")import numpy as npfrom PIL import Image from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") pil_image = Image.open(SAMPLE_IMAGE)array = np.asarray(pil_image)raw_bytes = open(SAMPLE_IMAGE, "rb").read() # NumPy-Arrays gelten als BGR, sofern nicht anders angegeben; dieses ist RGB.result = model(array, color_format="rgb")print(type(array).__name__, len(result.boxes)) for source in (pil_image, raw_bytes): result = model(source) print(type(source).__name__, len(result.boxes))from pathlib import Pathfrom PIL import Image from libreyolo import LibreYOLO, SAMPLE_IMAGE folder = Path("sample_folder")folder.mkdir(exist_ok=True)image = Image.open(SAMPLE_IMAGE)for index in range(3): image.save(folder / f"frame_{index}.jpg") model = LibreYOLO("LibreYOLO9s.pt") # Ein Ordner gibt eine nach Pfad sortierte Liste mit einem Results-Objekt je Bild zurück.results = model(str(folder))print(len(results), "images")libreyolo predict model=LibreYOLO9s.pt \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgEine einzelne Bildquelle akzeptiert sieben Typen.
| Typ | Interpretation |
|---|---|
str oder pathlib.Path | Lokale Datei, http(s)://, s3:// oder gs:// |
PIL.Image.Image | Wird in RGB umgewandelt |
numpy.ndarray | 2D-Graustufen oder 3D-HWC beziehungsweise CHW in BGR-Reihenfolge; ein 4D-Array ist ein Batch |
torch.Tensor | CHW oder NCHW, als RGB gelesen; ein 4D-Tensor ist ein Batch |
bytes | Codierte Bilddaten |
io.BytesIO | Codierte Bilddaten |
Ein 4D-Array oder -Tensor liefert eine Liste mit einem Results pro Bild.
Vor der Vorverarbeitung wird alles in RGB umgewandelt. Nur bei NumPy-Arrays ist die Kanalreihenfolge mehrdeutig, daher steuert color_format sie. "auto" (der Standard) und "bgr" lesen das Array als BGR, in der Reihenfolge, die OpenCV liefert, und "rgb" lässt es unverändert, wie es ein aus einem PIL-Bild erzeugtes Array benötigt.
Gleitkomma-Arrays werden anhand ihres eigenen Wertebereichs skaliert. Werte bis einschließlich 1.0 werden mit 255 multipliziert, höhere Werte auf [0, 255] begrenzt. Bei einem RGBA-Array wird der Alphakanal entfernt.
Entfernte Pfade benötigen jeweils ein Paket. requests für http(s):// ist in der Basisinstallation enthalten, boto3 für s3:// und gcsfs für gs:// sind es nicht.
Tracking akzeptiert Bilder, nach Dateinamen sortierte Ordner, Listen, Tupel und verzögerte Bilditeratoren als aufeinanderfolgende Frames. Übergib fps=30.0 für die zeitliche Einordnung der Bildsequenz und color_format="auto" für die Interpretation der Eingabe. Siehe Tracking.
Ordner
Ein Verzeichnis wird rekursiv durchsucht und sortiert. Jede Datei mit einer der folgenden Endungen wird als Bild behandelt: .jpg, .jpeg, .png, .gif, .webp, .bmp, .tiff, .tif. Alles andere wird übersprungen. Ein leerer Ordner gibt eine leere Liste zurück, statt einen Fehler auszulösen.
Ordner und Listen sind die beiden Quelltypen, die batch akzeptieren. Bei unterstützten Familien wird damit je Gruppe ein gestapelter Vorwärtsdurchlauf ausgeführt. Weitere Informationen findest du unter Inferenzleistung.
Videodateien
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Ersetze clip.mp4 durch eine lokale Videodatei.for result in model("clip.mp4", stream=True): print(result.frame_idx, len(result.boxes))from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") for result in model("clip.mp4", stream=True, vid_stride=3, save=True): passEin Pfad gilt als Video, wenn seine Endung .3g2, .3gp, .asf, .avi, .dav, .f4v, .flv, .gif, .h264, .h265, .hevc, .m2ts, .m4v, .mkv, .mov, .mp4, .mpeg, .mpg, .mts, .mxf, .ogv, .ts, .vob, .wmv oder .webm lautet.
.gif steht in beiden Listen. Ein direkt an predict übergebener .gif-Pfad wird als Video geöffnet, weil die Videoprüfung zuerst erfolgt. Eine .gif-Datei in einem durchsuchten Ordner wird dagegen als Standbild geladen.
vid_stride verarbeitet jeden N-ten Frame und ist standardmäßig 1. Ohne stream=True wird das gesamte Video in eine Liste decodiert. Bei mehr als 500 Frames nach Anwendung des Stride erscheint eine Warnung mit dem Vorschlag, stream=True zu verwenden.
Jedes Results-Objekt eines Videos enthält frame_idx.
Die Videokodierung greift auf einen verfügbaren Codec zurück, wenn H.264 nicht geöffnet werden kann. Der Fallback wird auf INFO protokolliert und erst nach erfolgreicher Verwendung eines anderen Codecs je Codec und Bildfläche zwischengespeichert.
Webcams, Netzwerkstreams und YouTube
import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Webcam-Index 0. Live-Quellen enden nie, daher wird die Schleife begrenzt.for result in itertools.islice(model(0, stream=True), 100): print(result.frame_idx, len(result.boxes))import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")source = "rtsp://user:password@192.168.1.64:554/Streaming/Channels/101" for result in itertools.islice(model(source, stream=True), 100): print(result.frame_idx, len(result.boxes))Live-Quellen sind unbegrenzt und benötigen deshalb stream=True. Ohne dieses Argument löst predict ValueError aus, statt eine endlose Liste aufzubauen.
Frames werden in einem Hintergrundthread gelesen, einer je Aufnahme. Standardmäßig enthält die Warteschlange nur den neuesten Frame. Ist ein Modell langsamer als die Kamera, überspringt es dadurch Frames, statt immer weiter zurückzufallen. stream_buffer=True behält jeden aufgenommenen Frame. Das erhält alle Frames auf Kosten zunehmender Latenz.
Ein Webcam-Index ist ein int oder eine Ziffernfolge. Unter Windows wird die Aufnahme zuerst über das DirectShow-Backend geöffnet. Schlägt dies fehl, wird auf das Standard-Backend zurückgegriffen.
YouTube-Seiten-URLs werden ohne Download des Videos in eine direkte Medien-URL aufgelöst. Dafür ist yt-dlp erforderlich:
pip install "libreyolo[stream]"Stream-Labels werden vor der Protokollierung oder Verwendung als Dateiname bereinigt. Eine URL mit Zugangsdaten erscheint als user:***@host. Abfragezeichenfolgen werden aus direkten Stream-Labels entfernt, da sie häufig signierte URLs und Bearer-Tokens enthalten. Eine YouTube-Video-ID bleibt erhalten, da sie keine Zugangsdaten darstellt.
Mehrere Kameras gleichzeitig
import itertoolsfrom pathlib import Path from libreyolo import LibreYOLO Path("cameras.streams").write_text( "# one source per line, blank lines and comments are skipped\n" "rtsp://192.168.1.64:554/Streaming/Channels/101\n" "rtsp://192.168.1.65:554/Streaming/Channels/101\n", encoding="utf-8",) model = LibreYOLO("LibreYOLO9s.pt")for result in itertools.islice(model("cameras.streams", stream=True), 100): print(result.frame_idx, len(result.boxes))import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")cameras = [0, "rtsp://192.168.1.64:554/Streaming/Channels/101"] for result in itertools.islice(model(cameras, stream=True), 100): print(result.frame_idx, len(result.boxes))Eine .streams-Datei enthält eine Quelle pro Zeile. Leerzeilen und mit # beginnende Zeilen werden ignoriert. Jede übrige Zeile muss selbst ein Webcam-Index, Netzwerkstream, eine YouTube-URL oder ein Videodateipfad sein. Alles andere löst ValueError unter Angabe der Zeilennummer aus. Eine leere Datei löst einen Fehler aus, statt ohne Kameras zu starten.
Eine Liste oder ein Tupel aus Live-Quellen leistet dasselbe ohne Datei.
Jede Aufnahme erhält einen eigenen Thread. Die Frames aller Aufnahmen werden in einem Generator zusammengeführt. Jeder Durchgang fragt jeden aktiven Stream ab und gibt alle bereiten Frames aus. Eine langsame Kamera hält dadurch keine schnelle auf und Frames verschiedener Kameras werden ineinander verschachtelt. Ein beendeter Stream fällt aus der Rotation, während die übrigen fortgesetzt werden.
Bildschirmaufnahme
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Ohne stream=True wird ein einzelner Frame aufgenommen.result = model("screen")print(len(result.boxes), "detections")import itertools from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # "screen <monitor> <left> <top> <width> <height>"for result in itertools.islice(model("screen 1 100 200 512 256", stream=True), 50): print(len(result.boxes))Eine Bildschirmquelle besteht aus dem Wort screen, gefolgt von null, einer, vier oder fünf Ganzzahlen. Jede andere Anzahl löst ValueError aus.
| Form | Aufnahme |
|---|---|
"screen" | Alle Monitore zusammengeführt |
"screen 1" | Monitor 1 |
"screen 100 200 512 256" | Ein Bereich auf dem zusammengeführten Desktop |
"screen 1 100 200 512 256" | Ein Bereich auf Monitor 1 |
Die Bereichskoordinaten lauten left top width height relativ zur oberen linken Ecke des gewählten Monitors. Eine Bildschirmquelle meldet als Framerate 30 geteilt durch vid_stride. Mit dieser Rate wird ein gespeichertes Video geschrieben. Für die Aufnahme ist das Paket mss erforderlich:
pip install mssOhne stream=True nimmt eine Bildschirmquelle einen Frame auf und gibt ein einzelnes Results-Objekt zurück. Dies entspricht der Vorhersage für eine Bilddatei. Mit stream=True wird aufgenommen, bis die Schleife abgebrochen wird.
Rückgabewert von predict
Die Form des Rückgabewerts hängt von der Quelle und von stream ab.
| Quelle | stream=False | stream=True |
|---|---|---|
| Einzelbild | Ein Results-Objekt | Generator eines Results-Objekts |
| Bilderliste | Liste von Results | Generator |
| Ordner | Liste von Results | Generator |
| Videodatei | Liste von Results | Generator |
| Bildschirm | Ein Results-Objekt | Unbegrenzter Generator |
Webcam, Netzwerkstream, .streams | ValueError | Unbegrenzter Generator |
Ein Einzelbild gibt das Results-Objekt selbst zurück. Seine Indizierung wählt eine Erkennung und kein Bild aus. result[0] einer Einzelbildvorhersage ist daher die erste Box und nicht das erste Bild. Informationen zum Inhalt dieser Objekte findest du unter Arbeiten mit Ergebnissen.
Speicherort von save
save=True schreibt die annotierte Ausgabe in ein Laufverzeichnis, statt sie zurückzugeben.
Bilder werden unter einem automatisch hochgezählten Pfad wie runs/detect/predict, runs/detect/predict2 und so weiter gespeichert. Der Quelldateiname bleibt erhalten. Alle Bilder eines Prozesses landen im selben Verzeichnis. Enthalten zwei Eingabeordner denselben Dateinamen, überschreiben sie sich deshalb gegenseitig. Bilder im Arbeitsspeicher besitzen keinen wiederverwendbaren Namen. Ein einzelnes Bild wird als inference gespeichert, wiederholte Aufrufe überschreiben es also; eine Liste oder ein Batch wird als image0, image1 und so weiter nummeriert. Zwei Prozesse, die im selben Moment speichern, erhalten getrennte nummerierte Verzeichnisse, weil jeder Lauf sein Verzeichnis durch dessen Anlegen reserviert.
Video- und Live-Quellen werden als einzelne .mp4-Datei mit dem Namen der Quelle geschrieben.
output_path überschreibt das Verzeichnis. Ein Pfad mit Dateiendung wird als Datei behandelt, ein Pfad ohne Endung als Verzeichnis. output_file_format wählt die Codierung für Standbilder und akzeptiert jpg, png oder webp.
Nachdem ein Bild gespeichert wurde, wird der geschriebene Pfad außerdem als result.saved_path an das Ergebnis angehängt.