Zum Inhalt springen

Eine schrittweise Anleitung zum Training von YOLO11 Modellen mit IBM Watsonx

Heutzutage werden skalierbare Computer-Vision-Lösungen immer häufiger eingesetzt und verändern die Art und Weise, wie wir mit visuellen Daten umgehen. Ein gutes Beispiel ist IBM Watsonx, eine fortschrittliche KI- und Datenplattform, die die Entwicklung, Bereitstellung und Verwaltung von KI-Modellen vereinfacht. Sie bietet eine komplette Suite für den gesamten KI-Lebenszyklus und eine nahtlose Integration mit IBM Cloud Services.

Sie können Ultralytics YOLO11 Modelle mit IBM Watsonx trainieren. Es ist eine gute Option für Unternehmen, die an effizientem Modelltraining, Feinabstimmung für bestimmte Aufgaben und Verbesserung der Modellleistung mit robusten Tools und einem benutzerfreundlichen Setup interessiert sind. In diesem Leitfaden führen wir Sie durch den Prozess des Trainings von YOLO11 mit IBM Watsonx, von der Einrichtung Ihrer Umgebung bis zur Auswertung Ihrer trainierten Modelle. Legen Sie los!

Was ist IBM Watsonx?

Watsonx ist die Cloud-basierte Plattform von IBM für kommerzielle generative KI und wissenschaftliche Daten. Die drei Komponenten von IBM Watsonx - watsonx.ai, watsonx.data und watsonx.governance - bilden zusammen eine durchgängige, vertrauenswürdige KI-Plattform, die KI-Projekte zur Lösung von Geschäftsproblemen beschleunigen kann. Sie bietet leistungsstarke Tools zum Erstellen, Trainieren und Bereitstellen von Machine-Learning-Modellen und erleichtert die Verbindung mit verschiedenen Datenquellen.

Überblick über IBM Watsonx

Die benutzerfreundliche Oberfläche und die kollaborativen Funktionen rationalisieren den Entwicklungsprozess und helfen bei der effizienten Verwaltung und Bereitstellung von Modellen. Ob für Computer Vision, Predictive Analytics, natürliche Sprachverarbeitung oder andere KI-Anwendungen, IBM Watsonx bietet die Werkzeuge und die Unterstützung, die für die Förderung von Innovationen erforderlich sind.

Hauptmerkmale von IBM Watsonx

IBM Watsonx besteht aus drei Hauptkomponenten: watsonx.ai, watsonx.data und watsonx.governance. Jede Komponente bietet Funktionen, die verschiedene Aspekte der KI und des Datenmanagements abdecken. Werfen wir einen genaueren Blick auf sie.

Watsonx.ai

Watsonx.ai bietet leistungsstarke Tools für die KI-Entwicklung und ermöglicht den Zugriff auf von IBM unterstützte benutzerdefinierte Modelle, Modelle von Drittanbietern wie Llama 3 und IBMs eigene Granite-Modelle. Es umfasst das Prompt Lab zum Experimentieren mit KI-Prompts, das Tuning Studio zur Verbesserung der Modellleistung mit gelabelten Daten und die Flows Engine zur Vereinfachung der Entwicklung generativer KI-Anwendungen. Außerdem bietet es umfassende Tools zur Automatisierung des Lebenszyklus von KI-Modellen und zur Anbindung an verschiedene APIs und Bibliotheken.

Watsonx.Daten

Watsonx.data unterstützt durch die IBM Storage Fusion HCI-Integration sowohl Cloud- als auch On-Premises-Bereitstellungen. Die benutzerfreundliche Konsole bietet einen zentralen Zugriff auf Daten in verschiedenen Umgebungen und erleichtert die Datenexploration mit gängigem SQL. Sie optimiert Arbeitslasten mit effizienten Abfrage-Engines wie Presto und Spark, beschleunigt Dateneinblicke mit einer KI-gestützten semantischen Schicht, umfasst eine Vektordatenbank für KI-Relevanz und unterstützt offene Datenformate für den einfachen Austausch von Analysen und KI-Daten.

Watsonx.governance

Watsonx.governance erleichtert die Einhaltung von Vorschriften, indem es automatisch Änderungen der Vorschriften erkennt und Richtlinien durchsetzt. Es verknüpft Anforderungen mit internen Risikodaten und bietet aktuelle KI-Faktenblätter. Die Plattform unterstützt das Risikomanagement mit Warnmeldungen und Tools zur Erkennung von Problemen wie Verzerrungen und Abweichungen. Außerdem automatisiert sie die Überwachung und Dokumentation des KI-Lebenszyklus, organisiert die KI-Entwicklung mit einem Modellinventar und verbessert die Zusammenarbeit mit benutzerfreundlichen Dashboards und Reporting-Tools.

Wie man YOLO11 mit IBM Watsonx trainiert

Sie können IBM Watsonx verwenden, um Ihren YOLO11 Modell-Trainingsworkflow zu beschleunigen.

Voraussetzungen

Sie benötigen ein IBM Cloud-Konto, um ein watsonx.ai-Projekt zu erstellen, und Sie benötigen auch ein Kaggle-Konto, um den Datensatz zu laden.

Schritt 1: Richten Sie Ihre Umgebung ein

Zunächst müssen Sie ein IBM-Konto einrichten, um ein Jupyter-Notebook zu verwenden. Melden Sie sich bei watsonx.ai mit Ihrem IBM Cloud-Konto an.

Erstellen Sie dann ein watsonx.ai-Projekt und ein Jupyter Notebook.

Daraufhin wird eine Notebook-Umgebung geöffnet, in die Sie Ihren Datensatz laden können. Sie können den Code aus diesem Tutorial verwenden, um eine einfache Trainingsaufgabe für ein Objekterkennungsmodell zu bewältigen.

Schritt 2: Installieren und Importieren relevanter Bibliotheken

Als nächstes können Sie die erforderlichen Python Bibliotheken installieren und importieren.

Einrichtung

# Install the required packages
pip install torch torchvision torchaudio
pip install opencv-contrib-python-headless
pip install ultralytics==8.0.196

Detaillierte Anweisungen und bewährte Verfahren für den Installationsprozess finden Sie in unserem Ultralytics Installationshandbuch. Wenn Sie bei der Installation der erforderlichen Pakete für YOLO11 auf Schwierigkeiten stoßen, finden Sie in unserem Leitfaden für häufige Probleme Lösungen und Tipps.

Dann können Sie die benötigten Pakete importieren.

Relevante Bibliotheken importieren

# Import ultralytics
import ultralytics

ultralytics.checks()

# Import packages to retrieve and display image files

Schritt 3: Laden der Daten

Für dieses Tutorial werden wir einen auf Kaggle verfügbaren Datensatz zu Meeresabfällen verwenden. Mit diesem Datensatz werden wir ein YOLO11 Modell trainieren, um Müll und biologische Objekte in Unterwasserbildern zu erkennen und zu klassifizieren.

Wir können den Datensatz über die Kaggle-API direkt in das Notebook laden. Erstellen Sie zunächst ein kostenloses Kaggle-Konto. Sobald Sie ein Konto erstellt haben, müssen Sie einen API-Schlüssel generieren. Eine Anleitung zur Generierung Ihres Schlüssels finden Sie in der Kaggle-API-Dokumentation unter dem Abschnitt "API-Anmeldeinformationen".

Kopieren Sie Ihren Kaggle-Benutzernamen und Ihren API-Schlüssel und fügen Sie sie in den folgenden Code ein. Führen Sie dann den Code aus, um die API zu installieren und den Datensatz in Watsonx zu laden.

Einrichtung

# Install kaggle
pip install kaggle

Nachdem wir Kaggle installiert haben, können wir den Datensatz in Watsonx laden.

Laden der Daten

# Replace "username" string with your username
os.environ["KAGGLE_USERNAME"] = "username"
# Replace "apiKey" string with your key
os.environ["KAGGLE_KEY"] = "apiKey"

# Load dataset
os.system("kaggle datasets download atiqishrak/trash-dataset-icra19 --unzip")

# Store working directory path as work_dir
work_dir = os.getcwd()

# Print work_dir path
print(os.getcwd())

# Print work_dir contents
print(os.listdir(f"{work_dir}"))

# Print trash_ICRA19 subdirectory contents
print(os.listdir(f"{work_dir}/trash_ICRA19"))

Nach dem Laden des Datensatzes haben wir unser Arbeitsverzeichnis ausgedruckt und gespeichert. Wir haben auch den Inhalt unseres Arbeitsverzeichnisses ausgedruckt, um zu bestätigen, dass der Datensatz "trash_ICRA19" ordnungsgemäß geladen wurde.

Wenn Sie unter den Inhalten des Verzeichnisses "trash_ICRA19" sehen, wurde es erfolgreich geladen. Sie sollten drei Dateien/Ordner sehen: a config.yaml Datei, eine videos_for_testing Verzeichnis, und ein dataset Verzeichnis. Wir ignorieren das videos_for_testing Verzeichnis, Sie können es also gerne löschen.

Wir werden die Datei config.yaml und den Inhalt des Verzeichnisses dataset verwenden, um unser Objekterkennungsmodell zu trainieren. Hier ist ein Beispielbild aus unserem Datensatz für Meeresmüll.

Meeresabfälle mit Bounding Box

Schritt 4: Vorverarbeitung der Daten

Glücklicherweise sind alle Beschriftungen im Datensatz der Meeresabfälle bereits als YOLO .txt-Dateien formatiert. Wir müssen jedoch die Struktur der Verzeichnisse für Bilder und Beschriftungen neu anordnen, um unserem Modell die Verarbeitung der Bilder und Beschriftungen zu erleichtern. Im Moment hat das Verzeichnis unseres geladenen Datensatzes diese Struktur:

Verzeichnis der geladenen Datensätze

Die Modelle von YOLO erfordern jedoch standardmäßig getrennte Bilder und Beschriftungen in Unterverzeichnissen innerhalb der Aufteilung train/val/test. Wir müssen das Verzeichnis in die folgende Struktur umorganisieren:

Yolo Verzeichnisstruktur

Um das Verzeichnis des Datensatzes zu reorganisieren, können wir das folgende Skript ausführen:

Vorverarbeitung der Daten

# Function to reorganize dir
def organize_files(directory):
    for subdir in ["train", "test", "val"]:
        subdir_path = os.path.join(directory, subdir)
        if not os.path.exists(subdir_path):
            continue

        images_dir = os.path.join(subdir_path, "images")
        labels_dir = os.path.join(subdir_path, "labels")

        # Create image and label subdirs if non-existent
        os.makedirs(images_dir, exist_ok=True)
        os.makedirs(labels_dir, exist_ok=True)

        # Move images and labels to respective subdirs
        for filename in os.listdir(subdir_path):
            if filename.endswith(".txt"):
                shutil.move(os.path.join(subdir_path, filename), os.path.join(labels_dir, filename))
            elif filename.endswith(".jpg") or filename.endswith(".png") or filename.endswith(".jpeg"):
                shutil.move(os.path.join(subdir_path, filename), os.path.join(images_dir, filename))
            # Delete .xml files
            elif filename.endswith(".xml"):
                os.remove(os.path.join(subdir_path, filename))


if __name__ == "__main__":
    directory = f"{work_dir}/trash_ICRA19/dataset"
    organize_files(directory)

Als nächstes müssen wir die .yaml-Datei für den Datensatz ändern. Dies ist der Aufbau, den wir in unserer .yaml-Datei verwenden werden. Die Nummern der Klassen-IDs beginnen bei 0:

path: /path/to/dataset/directory # root directory for dataset
train: train/images # train images subdirectory
val: train/images # validation images subdirectory
test: test/images # test images subdirectory

# Classes
names:
    0: plastic
    1: bio
    2: rov

Führen Sie das folgende Skript aus, um den aktuellen Inhalt der Datei config.yaml zu löschen und durch den obigen Inhalt zu ersetzen, der unsere neue Verzeichnisstruktur des Datensatzes widerspiegelt. Stellen Sie sicher, dass Sie den work_dir-Teil des Stammverzeichnispfads in Zeile 4 durch Ihren eigenen Arbeitsverzeichnispfad ersetzen, den wir zuvor abgerufen haben. Belassen Sie die Definitionen der Unterverzeichnisse train, val und test. Ändern Sie auch nicht {work_dir} in Zeile 23 des Codes.

Bearbeiten Sie die .yaml-Datei

# Contents of new confg.yaml file
def update_yaml_file(file_path):
    data = {
        "path": "work_dir/trash_ICRA19/dataset",
        "train": "train/images",
        "val": "train/images",
        "test": "test/images",
        "names": {0: "plastic", 1: "bio", 2: "rov"},
    }

    # Ensures the "names" list appears after the sub/directories
    names_data = data.pop("names")
    with open(file_path, "w") as yaml_file:
        yaml.dump(data, yaml_file)
        yaml_file.write("\n")
        yaml.dump({"names": names_data}, yaml_file)


if __name__ == "__main__":
    file_path = f"{work_dir}/trash_ICRA19/config.yaml"  # .yaml file path
    update_yaml_file(file_path)
    print(f"{file_path} updated successfully.")

Schritt 5: Trainieren des YOLO11 Modells

Führen Sie den folgenden Befehlszeilencode aus, um ein vortrainiertes Standardmodell YOLO11 fein abzustimmen.

Trainieren Sie das Modell YOLO11

!yolo task=detect mode=train data={work_dir}/trash_ICRA19/config.yaml model=yolo11n.pt epochs=2 batch=32 lr0=.04 plots=True

Im Folgenden werden die Parameter des Befehls "Modellschulung" näher betrachtet:

  • Aufgabe: Hier wird die Bildverarbeitungsaufgabe angegeben, für die Sie das angegebene YOLO Modell und den Datensatz verwenden.
  • Modus: Bezeichnet den Zweck, für den Sie das angegebene Modell und die Daten laden. Da wir ein Modell trainieren, wird es auf "trainieren" gesetzt. Später, wenn wir die Leistung unseres Modells testen, werden wir es auf "Vorhersage" setzen.
  • epochs: Damit wird die Anzahl der Durchläufe von YOLO11 durch den gesamten Datensatz begrenzt.
  • Stapel: Der numerische Wert legt die Größe der Trainingsstapel fest. Batches sind die Anzahl der Bilder, die ein Modell verarbeitet, bevor es seine Parameter aktualisiert.
  • lr0: Gibt die anfängliche Lernrate des Modells an.
  • Diagramme: Weist YOLO an, Diagramme der Trainings- und Bewertungsmetriken unseres Modells zu erstellen und zu speichern.

Ein detailliertes Verständnis des Modelltrainings und der besten Praktiken finden Sie in der AnleitungYOLO11 Model Training. Dieser Leitfaden hilft Ihnen, das Beste aus Ihren Experimenten herauszuholen und sicherzustellen, dass Sie YOLO11 effektiv nutzen.

Schritt 6: Testen Sie das Modell

Wir können nun Inferenzen durchführen, um die Leistung unseres fein abgestimmten Modells zu testen:

Testen Sie das Modell YOLO11

!yolo task=detect mode=predict source={work_dir}/trash_ICRA19/dataset/test/images model={work_dir}/runs/detect/train/weights/best.pt conf=0.5 iou=.5 save=True save_txt=True

Dieses kurze Skript erzeugt vorausgesagte Beschriftungen für jedes Bild in unserem Testsatz sowie neue Ausgabebilddateien, die den vorausgesagten Begrenzungsrahmen über das Originalbild legen.

Die vorhergesagten .txt-Beschriftungen für jedes Bild werden über die save_txt=True Argument und die Ausgabebilder mit Bounding-Box-Overlays werden durch das save=True Argument.
Der Parameter conf=0.5 weist das Modell an, alle Vorhersagen mit einem Konfidenzniveau von weniger als 50 % zu ignorieren.

Zum Schluss, iou=.5 weist das Modell an, Boxen der gleichen Klasse mit einer Überlappung von 50% oder mehr zu ignorieren. Dies trägt dazu bei, mögliche doppelte Boxen für dasselbe Objekt zu reduzieren.
können wir die Bilder mit vorhergesagten Bounding-Box-Überlagerungen laden, um zu sehen, wie unser Modell bei einer Handvoll Bilder abschneidet.

Vorhersagen anzeigen

# Show the first ten images from the preceding prediction task
for pred_dir in glob.glob(f"{work_dir}/runs/detect/predict/*.jpg")[:10]:
    img = Image.open(pred_dir)
    display(img)

Der obige Code zeigt zehn Bilder aus dem Testsatz mit ihren vorhergesagten Bounding Boxes an, begleitet von den Klassennamen und den Vertrauensstufen.

Schritt 7: Bewerten Sie das Modell

Wir können Visualisierungen der Präzision und des Recalls des Modells für jede Klasse erstellen. Diese Visualisierungen werden im Home-Verzeichnis unter dem Ordner train gespeichert. Der Präzisionswert wird in der Datei P_curve.png angezeigt:

Präzision Konfidenzkurve

Das Diagramm zeigt einen exponentiellen Anstieg der Genauigkeit, wenn das Konfidenzniveau des Modells für Vorhersagen steigt. Allerdings hat sich die Modellgenauigkeit nach zwei Epochen noch nicht auf ein bestimmtes Konfidenzniveau eingependelt.

Das Abrufdiagramm (R_curve.png) zeigt einen umgekehrten Trend:

Rückruf-Konfidenzkurve

Im Gegensatz zur Präzision bewegt sich der Recall in die entgegengesetzte Richtung und zeigt einen größeren Recall bei Instanzen mit geringerem Vertrauen und einen geringeren Recall bei Instanzen mit höherem Vertrauen. Dies ist ein treffendes Beispiel für den Zielkonflikt zwischen Präzision und Recall bei Klassifizierungsmodellen.

Schritt 8: Berechnung von Schnittpunkt über Union

Sie können die Vorhersagegenauigkeit messen, indem Sie den IoU zwischen einer vorhergesagten Bounding Box und einer Ground Truth Bounding Box für dasselbe Objekt berechnen. Weitere Einzelheiten finden Sie in der IBM-Anleitung zum Training YOLO11.

Zusammenfassung

Wir haben die wichtigsten Funktionen von IBM Watsonx kennengelernt und erfahren, wie man mit IBM Watsonx ein YOLO11 Modell trainiert. Wir haben auch gesehen, wie IBM Watsonx Ihre KI-Workflows mit fortschrittlichen Tools für die Modellerstellung, Datenverwaltung und Compliance verbessern kann.

Weitere Einzelheiten zur Verwendung finden Sie in der offiziellen IBM Watsonx-Dokumentation.

Besuchen Sie auch die SeiteUltralytics mit dem Integrationsleitfaden, um mehr über verschiedene spannende Integrationen zu erfahren.

FAQ

Wie trainiere ich ein YOLO11 Modell mit IBM Watsonx?

Gehen Sie folgendermaßen vor, um ein YOLO11 Modell mit IBM Watsonx zu trainieren:

  1. Richten Sie Ihre Umgebung ein: Erstellen Sie ein IBM Cloud-Konto und richten Sie ein Watsonx.ai-Projekt ein. Verwenden Sie ein Jupyter Notebook für Ihre Programmierumgebung.
  2. Bibliotheken installieren: Installieren Sie die notwendigen Bibliotheken wie torch, opencvund ultralytics.
  3. Daten laden: Verwenden Sie die Kaggle-API, um Ihren Datensatz in Watsonx zu laden.
  4. Daten vorverarbeiten: Organisieren Sie Ihren Datensatz in der gewünschten Verzeichnisstruktur und aktualisieren Sie die .yaml Konfigurationsdatei.
  5. Das Modell trainieren: Verwenden Sie die Befehlszeilenschnittstelle YOLO , um Ihr Modell mit spezifischen Parametern zu trainieren, wie z. B. epochs, batch sizeund learning rate.
  6. Testen und Auswerten: Führen Sie die Inferenz aus, um das Modell zu testen und seine Leistung anhand von Kennzahlen wie Präzision und Wiedererkennung zu bewerten.

Detaillierte Anweisungen finden Sie in unserem YOLO11 Modellschulungsleitfaden.

Was sind die Hauptmerkmale von IBM Watsonx für das Training von KI-Modellen?

IBM Watsonx bietet mehrere wichtige Funktionen für das Training von KI-Modellen:

  • Watsonx.ai: Bietet Tools für die KI-Entwicklung, einschließlich Zugriff auf von IBM unterstützte benutzerdefinierte Modelle und Modelle von Drittanbietern wie Llama 3. Es umfasst das Prompt Lab, Tuning Studio und Flows Engine für ein umfassendes KI-Lebenszyklusmanagement.
  • Watsonx.data: Unterstützt Cloud- und On-Premises-Implementierungen und bietet zentralisierten Datenzugriff, effiziente Abfrage-Engines wie Presto und Spark sowie eine KI-gestützte semantische Schicht.
  • Watsonx.governance: Automatisiert die Einhaltung von Vorschriften, verwaltet Risiken mit Warnmeldungen und bietet Tools zur Erkennung von Problemen wie Verzerrungen und Abweichungen. Es umfasst auch Dashboards und Reporting-Tools für die Zusammenarbeit.

Weitere Informationen finden Sie in der offiziellen Dokumentation zu IBM Watsonx.

Warum sollte ich IBM Watsonx für das Training von Ultralytics YOLO11 Modellen verwenden?

IBM Watsonx ist eine ausgezeichnete Wahl für das Training von Ultralytics YOLO11 Modellen, da es eine umfassende Suite von Tools bietet, die den KI-Lebenszyklus rationalisieren. Zu den wichtigsten Vorteilen gehören:

  • Skalierbarkeit: Skalieren Sie Ihr Modelltraining einfach mit IBM Cloud Services.
  • Integration: Nahtlose Integration mit verschiedenen Datenquellen und APIs.
  • Benutzerfreundliches Interface: Vereinfacht den Entwicklungsprozess durch eine kollaborative und intuitive Schnittstelle.
  • Erweiterte Tools: Zugriff auf leistungsstarke Tools wie Prompt Lab, Tuning Studio und Flows Engine zur Verbesserung der Modellleistung.

Erfahren Sie mehr über Ultralytics YOLO11 und wie Sie Modelle mit IBM Watsonx trainieren können, erfahren Sie in unserem Integrationsleitfaden.

Wie kann ich meinen Datensatz für das YOLO11 Training auf IBM Watsonx vorverarbeiten?

So bereiten Sie Ihren Datensatz für das YOLO11 Training auf IBM Watsonx vor:

  1. Organisieren Sie die Verzeichnisse: Stellen Sie sicher, dass Ihr Datensatz der Verzeichnisstruktur YOLO folgt, mit separaten Unterverzeichnissen für Bilder und Beschriftungen innerhalb der Aufteilung train/val/test.
  2. .yaml-Datei aktualisieren: Ändern Sie die .yaml Konfigurationsdatei, um die neue Verzeichnisstruktur und die Klassennamen wiederzugeben.
  3. Vorverarbeitungsscript ausführen: Verwenden Sie ein Python Skript, um Ihren Datensatz zu reorganisieren und die .yaml Datei entsprechend.

Hier finden Sie ein Beispielskript zum Organisieren Ihres Datensatzes:

import os
import shutil


def organize_files(directory):
    for subdir in ["train", "test", "val"]:
        subdir_path = os.path.join(directory, subdir)
        if not os.path.exists(subdir_path):
            continue

        images_dir = os.path.join(subdir_path, "images")
        labels_dir = os.path.join(subdir_path, "labels")

        os.makedirs(images_dir, exist_ok=True)
        os.makedirs(labels_dir, exist_ok=True)

        for filename in os.listdir(subdir_path):
            if filename.endswith(".txt"):
                shutil.move(os.path.join(subdir_path, filename), os.path.join(labels_dir, filename))
            elif filename.endswith(".jpg") or filename.endswith(".png") or filename.endswith(".jpeg"):
                shutil.move(os.path.join(subdir_path, filename), os.path.join(images_dir, filename))


if __name__ == "__main__":
    directory = f"{work_dir}/trash_ICRA19/dataset"
    organize_files(directory)

Weitere Einzelheiten finden Sie in unserem Leitfaden für die Datenvorverarbeitung.

Was sind die Voraussetzungen für das Training eines YOLO11 Modells auf IBM Watsonx?

Bevor Sie mit dem Training eines YOLO11 Modells auf IBM Watsonx beginnen, sollten Sie sicherstellen, dass Sie die folgenden Voraussetzungen erfüllen:

  • IBM Cloud-Konto: Erstellen Sie ein Konto auf IBM Cloud, um auf Watsonx.ai zuzugreifen.
  • Kaggle-Konto: Um Datensätze zu laden, benötigen Sie ein Kaggle-Konto und einen API-Schlüssel.
  • Jupyter Notebook: Richten Sie eine Jupyter Notebook-Umgebung innerhalb von Watsonx.ai für die Codierung und das Modelltraining ein.

Weitere Informationen zum Einrichten Ihrer Umgebung finden Sie in unserem Ultralytics Installationsleitfaden.

📅 Erstellt vor 3 Monaten ✏️ Aktualisiert vor 1 Monat

Kommentare