import os import gdown from glob import glob import cv2 from PIL import Image, ImageDraw, ImageFont from IPython.display import display from ultralytics import YOLO import matplotlib.pyplot as plt import matplotlib.patches as patches # Download Dataset - Download and unpack a dataset consisting of a train, val and test split. Trees are labeled (using the YOLO format). gdown.cached_download("https://drive.google.com/file/d/1xkh8RYp15c0N4A9HFvcBeSmxhWaH5Ynw/view?usp=sharing", "sorted_images_YOLO_formatted.zip", fuzzy=True, postprocess=gdown.extractall) # Setting up the Framework - create a setup file named yolov8.yaml containing required parameters %%writefile sorted_images_YOLO_formatted/data/yolov8.yaml # Train/val/test sets path: sorted_images_YOLO_formatted/data/ # dataset root dir train: train # train images (relative to 'path') val: val # val images (relative to 'path') test: test # test images (optional) # number of classes nc: 2 # class names names: ['Großer Laubbaum', 'Kleiner Laubbaum'] # Training - Train the model on the train dataset. yolov8n.pt refers to the smallest model size # Load a pretrained model model = YOLO("yolov8n.pt") # Train the model results = model.train(data="sorted_images_YOLO_formatted/data/yolov8.yaml", epochs=300, imgsz=200, cache=False) # Model evaluation - Evaluate the model performance on the validation dataset # Validate the model metrics = model.val(split='val') metrics.box.map # map50-95 metrics.box.map50 # map50 metrics.box.map75 # map75 metrics.box.maps # a list contains map50-95 of each category # Display performance metrics display(Image.open('runs/detect/train/results.png')) display(Image.open('runs/detect/train2/confusion_matrix_normalized.png')) display(Image.open('runs/detect/train2/F1_curve.png')) display(Image.open('runs/detect/train2/labels_correlogram.jpg')) display(Image.open('runs/detect/train2/labels.jpg')) display(Image.open('runs/detect/train/P_curve.png')) display(Image.open('runs/detect/train/PR_curve.png')) display(Image.open('runs/detect/train/R_curve.png')) # Model Inference # We use the model for inference on a list of images. # First, we load the model checkpoint with the best performance. # Load trained model model = YOLO('runs/detect/train2/weights/best.pt') # load a custom trained model # Export the model #model.export(format='torchscript') # model.export(format='onnx',simplify=True) # We define a list of images on which we will apply the model to identify trees. #imagefiles = [ # "/content/ObjectDetectionDataset/data/test/513278_5404358_Base_A62_Luftbild_2021_EPSG25832.png", # "/content/ObjectDetectionDataset/data/test/513278_5404407_Base_A62_Luftbild_2021_EPSG25832.png", # "/content/ObjectDetectionDataset/data/test/513278_5404553_Base_A62_Luftbild_2021_EPSG25832.png" # ] # Run batched inference on a list of images #results = model.predict(imagefiles) # Neue Methodik um alle Bilder aus /content/ObjectDetectionDataset/data/test vom Modell untersuchen zu lassen # Verzeichnis mit den Testbildern test_directory = "sorted_images_YOLO_formatted/data/test/" imagefiles = glob(os.path.join(test_directory, "*.png")) # Modellvorhersagen ausführen results = model.predict(imagefiles) # Benutzerdefinierte Farben für die Klassen (basierend auf meinem ursprünglichen Skript) class_colors = { 'Großer Laubbaum': 'red', 'Kleiner Laubbaum': 'orange' } # Klassen-IDs und Klassennamen zuordnen class_names = ['Großer Laubbaum', 'Kleiner Laubbaum'] # Following 2 Options of how to display the output: # 1: Output with 200x200 pixels - save files to predictions/ directory - no readablie labels from PIL import Image, ImageDraw, ImageFont import os # Ergebnisverzeichnis für die Vorhersagen erstellen, falls es nicht existiert os.makedirs('predictions/', exist_ok=True) # Benutzerdefinierte Farben für die Klassen class_colors = { 'Großer Laubbaum': 'red', 'Kleiner Laubbaum': 'orange' } # Vorhersagen plotten und Farben anpassen for i, result in enumerate(results): # Bild laden img = Image.open(imagefiles[i]) # Bild um 50 % größer skalieren img = img.resize((int(img.width * 1.5), int(img.height * 1.5))) draw = ImageDraw.Draw(img) # Bounding-Boxen und Klassen plotten for box in result.boxes: # Koordinaten der Bounding-Box xmin, ymin, xmax, ymax = box.xyxy[0].numpy() # Anpassung der Koordinaten an das skalierte Bild xmin, ymin, xmax, ymax = [coord * 1.5 for coord in [xmin, ymin, xmax, ymax]] # Klassennamen anhand der Klassen-ID holen class_id = int(box.cls) class_name = class_names[class_id] # Bounding-Box zeichnen mit der Farbe aus dem Farbschema draw.rectangle([xmin, ymin, xmax, ymax], outline=class_colors[class_name], width=3) # Bild ohne weißen Hintergrund und Achsen speichern img.save(os.path.join('predictions', os.path.split(imagefiles[i])[1])) print(f"Processed: {imagefiles[i]}") # 2: Output with 200x200 pixels - save files to predictions/ directory - readable labels from PIL import Image, ImageDraw, ImageFont import os # Ergebnisverzeichnis für die Vorhersagen erstellen, falls es nicht existiert os.makedirs('predictions/', exist_ok=True) # Benutzerdefinierte Farben für die Klassen class_colors = { 'Großer Laubbaum': 'red', 'Kleiner Laubbaum': 'orange', 'Großer Nadelbaum': 'darkgreen', 'Kleiner Nadelbaum': 'lightgreen', 'Busch/Hecke (Laub/Hartlaub)': 'purple', 'Busch/Hecke (Nadel)': 'cornflowerblue', 'Unbekannt': 'white' } # Schriftart und -größe festlegen (falls verfügbar) try: font = ImageFont.truetype("arial.ttf", 40) # Verwende Arial mit Größe 20 except IOError: font = ImageFont.load_default() # Fallback auf Standard-Schriftart # Vorhersagen plotten und Farben anpassen for i, result in enumerate(results): # Bild laden img = Image.open(imagefiles[i]) # Bild um 50 % größer skalieren img = img.resize((int(img.width * 1.5), int(img.height * 1.5))) draw = ImageDraw.Draw(img) # Bounding-Boxen und Klassen plotten for box in result.boxes: # Koordinaten der Bounding-Box xmin, ymin, xmax, ymax = box.xyxy[0].numpy() # Anpassung der Koordinaten an das skalierte Bild xmin, ymin, xmax, ymax = [coord * 1.5 for coord in [xmin, ymin, xmax, ymax]] # Klassennamen anhand der Klassen-ID holen class_id = int(box.cls) class_name = class_names[class_id] # Bounding-Box zeichnen mit der Farbe aus dem Farbschema draw.rectangle([xmin, ymin, xmax, ymax], outline=class_colors[class_name], width=2) # Größe des Textes berechnen mit textbbox (ersetzt textsize) text_bbox = draw.textbbox((xmin, ymin), class_name, font=font) text_width = text_bbox[2] - text_bbox[0] text_height = text_bbox[3] - text_bbox[1] # Hintergrund für den Text (halbtransparent) text_background = (xmin, ymin - text_height, xmin + text_width, ymin) draw.rectangle(text_background, fill=(200, 200, 200, 128)) # Schwarzer halbtransparenter Hintergrund # Klassennamen über die Bounding-Box schreiben draw.text((xmin, ymin - text_height), class_name, font=font, fill="red") # Weißer Text # Bild ohne weißen Hintergrund und Achsen speichern img.save(os.path.join('predictions', os.path.split(imagefiles[i])[1])) print(f"Processed: {imagefiles[i]}") # Export of labels as .txt def yolo_format(class_id, xmin, ymin, xmax, ymax, img_width, img_height): x_center = (xmin + xmax) / 2.0 / img_width y_center = (ymin + ymax) / 2.0 / img_height width = (xmax - xmin) / img_width height = (ymax - ymin) / img_height return f"{class_id} {x_center} {y_center} {width} {height}" def save_yolo_labels(results, output_dir): if not os.path.exists(output_dir): os.makedirs(output_dir) for i, result in enumerate(results): boxes = result.boxes # Extract boxes from result img_width, img_height = result.orig_shape # Get the original image shape image_path = result.path image_id = os.path.splitext(os.path.basename(image_path))[0] with open(os.path.join(output_dir, f"{image_id}.txt"), 'w') as f: for box in boxes: class_id = int(box.cls) xmin, ymin, xmax, ymax = box.xyxy[0].numpy() # Extract box coordinates yolo_line = yolo_format( class_id, xmin, ymin, xmax, ymax, img_width, img_height ) f.write(yolo_line + '\n') # Run batched inference on all images in the test directory results = model.predict(imagefiles) # Save the YOLO labels output_dir = 'predictions' save_yolo_labels(results, output_dir) # Display results #display all predictions result_directory = "predictions" # Get a list of all image files in the result directory resultimages = glob(os.path.join(result_directory, "*.png")) for image in resultimages: display(Image.open(image))