geo2ml
  1. Examples
  2. YOLOv8 workflow
  • geo2ml
  • Examples
    • Tabular data workflow
    • Unet workflow
    • COCO workflow
    • YOLOv8 workflow
  • Tabular data
    • Tabular data
  • Image data
    • Tiling
    • Coordinate transformations
    • Image data
    • Postprocessing
  • Plotting
  • CLI
    • Dataset creation

On this page

  • Install required dependencies
  • Create YOLO-format dataset
    • CLI
    • Python
  • Dataset structure
  • Create yolo.yaml for the dataset
  • Train the model
  • Report an issue
  1. Examples
  2. YOLOv8 workflow

YOLOv8 workflow

Example workflow for creating a YOLO-format dataset and training an object detection model with ultralytics
import rasterio as rio
import geopandas as gpd
from pathlib import Path
import rasterio.plot as rioplot
import matplotlib.pyplot as plt
path_to_data = Path('workflow_examples/')
train_raster = path_to_data/'104_28_Hiidenportti_Chunk1_orto.tif'
train_shp = path_to_data/'104_28_Hiidenportti_Chunk1_orto.geojson'
test_raster = path_to_data/'104_42_Hiidenportti_Chunk5_orto.tif'
test_shp = path_to_data/'104_42_Hiidenportti_Chunk5_orto.geojson'

Example data is RGB UAV imagery from Hiidenportti, and the task is to detect and segment different deadwood types. The reference data are annotated as polygons, and target column is layer.

Training area looks like this.

fig, axs = plt.subplots(1,2, dpi=150, figsize=(10,3))
with rio.open(train_raster) as src:
    rioplot.show(src, ax=axs[0])
train_gdf = gpd.read_file(train_shp)
train_gdf.plot(column='layer', ax=axs[1], cmap='seismic')
plt.suptitle('Train area')
plt.tight_layout()
plt.show()

And test area looks like this.

fig, axs = plt.subplots(1,2, dpi=150, figsize=(5,3))
with rio.open(test_raster) as src:
    rioplot.show(src, ax=axs[0])
test_gdf = gpd.read_file(test_shp)
test_gdf.plot(column='layer', ax=axs[1], cmap='seismic')
plt.suptitle('Test area')
plt.tight_layout()
plt.show()

Install required dependencies

ultralytics requires at least Python 3.8 and PyTorch 1.7. First install PyTorch according to instructions found here, then install ultralytics with pip install ultralytics.

Create YOLO-format dataset

In this example, the data are split into 320x320 pixel tiles with no overlap. Also set the min_bbox_area to 8 pixels so too small objects are discarded.

CLI

geo2ml_create_yolo_dataset \
example_data/workflow_examples/104_28_Hiidenportti_Chunk1_orto.tif \
example_data/workflow_examples/104_28_Hiidenportti_Chunk1_orto.geojson layer \
example_data/workflow_examples/yolo/train --gridsize_x 320 --gridsize_y 320 \
--ann_format polygon --min_bbox_area 8

geo2ml_create_yolo_dataset \
example_data/workflow_examples/104_42_Hiidenportti_Chunk5_orto.tif \
example_data/workflow_examples/104_42_Hiidenportti_Chunk5_orto.geojson layer \
example_data/workflow_examples/yolo/test --gridsize_x 320 --gridsize_y 320 \
--ann_format polygon --min_bbox_area 8

Python

from geo2ml.scripts.data import create_yolo_dataset
outpath = path_to_data/'yolo'

create_yolo_dataset(raster_path=train_raster, polygon_path=train_shp, target_column='layer',
                    outpath=outpath/'train', save_grid=False, gridsize_x=320, gridsize_y=320,
                    ann_format='polygon', min_bbox_area=8, allow_partial_data=True)

create_yolo_dataset(raster_path=test_raster, polygon_path=test_shp, target_column='layer',
                    outpath=outpath/'test', save_grid=False, gridsize_x=320, gridsize_y=320,
                    ann_format='polygon', min_bbox_area=8, allow_partial_data=True)

Dataset structure

Above creates the dataset to path_to_data/'yolo', so that it contains folders train and test. Both of these folders contain

  • folder images, which contains the tiled raster patches
  • folder vectors, which contain geojson-files corresponding to each file in images, if the location contains any annotations
  • folder labels, which contain the annotations in YOLO format
  • file yolo.yaml, which can be used as a template for the dataset description file

Create yolo.yaml for the dataset

Create a yolo.yaml file using the below template. Autogeneration for this might be added later.

# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3: list: [path/to_imgs1, path_to_imgs2, ..]
path: workflow_examples/yolo/ # dataset root dir 
train: train
val: test
test: test

# Classes
names:
  0: groundwood
  1: uprightwood

It is advisable to use absolute path as the path: variable, as ultralytics otherwise assumes that path is relative to the datasets_dir in your settings.

Train the model

from ultralytics import YOLO

As an example, train yolov8n-seg.pt for 30 epochs with 640x640px images and batch size of 4 (due to GPU constraints).

model = YOLO('yolov8n-seg.pt')
results = model.train(data=path_to_data/'yolo/yolo.yaml', epochs=30, imgsz=640, batch=4, 
                      optimizer='auto', project=path_to_data/'yolo/runs')
Ultralytics YOLOv8.0.180 🚀 Python-3.11.5 torch-2.0.1 CUDA:0 (NVIDIA RTX A2000 8GB Laptop GPU, 8192MiB)
engine/trainer: task=segment, mode=train, model=yolov8n-seg.pt, data=workflow_examples/yolo/yolo.yaml, epochs=30, patience=50, batch=4, imgsz=640, save=True, save_period=-1, cache=False, device=None, workers=8, project=workflow_examples/yolo/runs, name=None, exist_ok=False, pretrained=True, optimizer=auto, verbose=True, seed=0, deterministic=True, single_cls=False, rect=False, cos_lr=False, close_mosaic=10, resume=False, amp=True, fraction=1.0, profile=False, freeze=None, overlap_mask=True, mask_ratio=4, dropout=0.0, val=True, split=val, save_json=False, save_hybrid=False, conf=None, iou=0.7, max_det=300, half=False, dnn=False, plots=True, source=None, show=False, save_txt=False, save_conf=False, save_crop=False, show_labels=True, show_conf=True, vid_stride=1, stream_buffer=False, line_width=None, visualize=False, augment=False, agnostic_nms=False, classes=None, retina_masks=False, boxes=True, format=torchscript, keras=False, optimize=False, int8=False, dynamic=False, simplify=False, opset=None, workspace=4, nms=False, lr0=0.01, lrf=0.01, momentum=0.937, weight_decay=0.0005, warmup_epochs=3.0, warmup_momentum=0.8, warmup_bias_lr=0.1, box=7.5, cls=0.5, dfl=1.5, pose=12.0, kobj=1.0, label_smoothing=0.0, nbs=64, hsv_h=0.015, hsv_s=0.7, hsv_v=0.4, degrees=0.0, translate=0.1, scale=0.5, shear=0.0, perspective=0.0, flipud=0.0, fliplr=0.5, mosaic=1.0, mixup=0.0, copy_paste=0.0, cfg=None, tracker=botsort.yaml, save_dir=workflow_examples/yolo/runs/train2
Overriding model.yaml nc=80 with nc=2

                   from  n    params  module                                       arguments                     
  0                  -1  1       464  ultralytics.nn.modules.conv.Conv             [3, 16, 3, 2]                 
  1                  -1  1      4672  ultralytics.nn.modules.conv.Conv             [16, 32, 3, 2]                
  2                  -1  1      7360  ultralytics.nn.modules.block.C2f             [32, 32, 1, True]             
  3                  -1  1     18560  ultralytics.nn.modules.conv.Conv             [32, 64, 3, 2]                
  4                  -1  2     49664  ultralytics.nn.modules.block.C2f             [64, 64, 2, True]             
  5                  -1  1     73984  ultralytics.nn.modules.conv.Conv             [64, 128, 3, 2]               
  6                  -1  2    197632  ultralytics.nn.modules.block.C2f             [128, 128, 2, True]           
  7                  -1  1    295424  ultralytics.nn.modules.conv.Conv             [128, 256, 3, 2]              
  8                  -1  1    460288  ultralytics.nn.modules.block.C2f             [256, 256, 1, True]           
  9                  -1  1    164608  ultralytics.nn.modules.block.SPPF            [256, 256, 5]                 
 10                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 11             [-1, 6]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 12                  -1  1    148224  ultralytics.nn.modules.block.C2f             [384, 128, 1]                 
 13                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']          
 14             [-1, 4]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 15                  -1  1     37248  ultralytics.nn.modules.block.C2f             [192, 64, 1]                  
 16                  -1  1     36992  ultralytics.nn.modules.conv.Conv             [64, 64, 3, 2]                
 17            [-1, 12]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 18                  -1  1    123648  ultralytics.nn.modules.block.C2f             [192, 128, 1]                 
 19                  -1  1    147712  ultralytics.nn.modules.conv.Conv             [128, 128, 3, 2]              
 20             [-1, 9]  1         0  ultralytics.nn.modules.conv.Concat           [1]                           
 21                  -1  1    493056  ultralytics.nn.modules.block.C2f             [384, 256, 1]                 
 22        [15, 18, 21]  1   1004470  ultralytics.nn.modules.head.Segment          [2, 32, 64, [64, 128, 256]]   
YOLOv8n-seg summary: 261 layers, 3264006 parameters, 3263990 gradients

Transferred 381/417 items from pretrained weights
TensorBoard: Start with 'tensorboard --logdir workflow_examples/yolo/runs/train2', view at http://localhost:6006/
Freezing layer 'model.22.dfl.conv.weight'
AMP: running Automatic Mixed Precision (AMP) checks with YOLOv8n...
Downloading https://github.com/ultralytics/assets/releases/download/v0.0.0/yolov8n.pt to 'yolov8n.pt'...
100%|██████████████████████████████████████████████████████████████| 6.23M/6.23M [00:04<00:00, 1.59MB/s]
AMP: checks passed ✅
train: Scanning /mnt/d/Users/E1005164/geo2ml/nbs/workflow_examples/yolo/train/labels... 296 images, 79 b
train: New cache created: /mnt/d/Users/E1005164/geo2ml/nbs/workflow_examples/yolo/train/labels.cache
val: Scanning /mnt/d/Users/E1005164/geo2ml/nbs/workflow_examples/yolo/test/labels... 118 images, 22 back
val: New cache created: /mnt/d/Users/E1005164/geo2ml/nbs/workflow_examples/yolo/test/labels.cache
Plotting labels to workflow_examples/yolo/runs/train2/labels.jpg... 
optimizer: 'optimizer=auto' found, ignoring 'lr0=0.01' and 'momentum=0.937' and determining best 'optimizer', 'lr0' and 'momentum' automatically... 
optimizer: AdamW(lr=0.001667, momentum=0.9) with parameter groups 66 weight(decay=0.0), 77 weight(decay=0.0005), 76 bias(decay=0.0)
Image sizes 640 train, 640 val
Using 4 dataloader workers
Logging results to workflow_examples/yolo/runs/train2
Starting training for 30 epochs...

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       1/30      1.02G      1.954      2.929      3.966      1.645         10        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.708     0.0661      0.132     0.0589       0.68     0.0572      0.117     0.0378

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       2/30      1.01G      1.857      2.211      3.052      1.532         12        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.491      0.335      0.374      0.178      0.483      0.321      0.347      0.151

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       3/30      0.96G      1.853       2.11      2.738      1.529         13        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.384      0.358       0.32       0.18      0.419      0.323      0.306      0.144

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       4/30     0.963G      1.843      2.023      2.641       1.52          5        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.539      0.368      0.389      0.201      0.531      0.365      0.371      0.178

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       5/30     0.963G      1.768      2.081      2.491      1.503         19        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.424      0.461      0.417      0.229       0.44      0.437      0.404      0.195

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       6/30     0.963G      1.782      2.009       2.36      1.543          9        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.446      0.463      0.443       0.24      0.453      0.465      0.438      0.191

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       7/30     0.958G      1.814      1.953       2.39      1.505          7        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.583      0.467      0.475      0.254      0.571      0.463       0.46      0.212

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       8/30     0.963G      1.719      1.826      2.307      1.479         20        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.571      0.416      0.439      0.231      0.542      0.417      0.427      0.209

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
       9/30     0.963G      1.711      1.799      2.372      1.478          3        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.494       0.43      0.437      0.251      0.473      0.409      0.401      0.197

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      10/30     0.963G      1.666       1.89      1.923      1.421         10        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.486      0.506      0.469      0.264      0.533      0.485      0.467      0.227

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      11/30     0.963G      1.729      1.813       2.12      1.482          5        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.486      0.495      0.481      0.263      0.477      0.481      0.462      0.224

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      12/30      0.96G       1.76      1.738      2.119      1.484          6        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575        0.6      0.535      0.557      0.309      0.592      0.522      0.538      0.266

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      13/30     0.971G      1.665      1.688      2.004       1.43         15        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.608      0.537      0.538      0.302      0.603       0.53      0.516      0.254

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      14/30     0.958G      1.654      1.766      1.967      1.398          6        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.644       0.53      0.583       0.33      0.646      0.532      0.581      0.282

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      15/30     0.958G      1.606      1.675      1.869      1.414          8        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.527      0.504      0.517      0.271      0.549      0.452      0.472      0.212

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      16/30     0.958G      1.541      1.722      1.738      1.385         10        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.532      0.544      0.533      0.308      0.526      0.542      0.503      0.244

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      17/30      0.96G      1.539      1.672      1.794      1.372         10        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.587      0.478      0.521       0.29      0.608      0.472       0.52      0.251

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      18/30     0.956G      1.516      1.637      1.752      1.349          9        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.464      0.516      0.459      0.271      0.451      0.501      0.445      0.228

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      19/30     0.958G      1.516      1.776      1.713      1.333          8        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575       0.61       0.57      0.579      0.346      0.616      0.534      0.552      0.282

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      20/30     0.956G      1.502      1.645       1.67      1.339          2        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575       0.54      0.468      0.505      0.304      0.548      0.464      0.493      0.242
Closing dataloader mosaic

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      21/30     0.958G      1.421      1.339      1.935       1.34          5        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.602      0.554      0.566       0.33      0.602      0.531      0.543       0.27

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      22/30     0.956G      1.466      1.358      1.722      1.363          5        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.644      0.617      0.636      0.377      0.639      0.604      0.616       0.31

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      23/30     0.958G       1.41      1.325      1.667      1.329          6        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.641      0.583      0.596      0.356      0.639      0.575       0.58      0.288

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      24/30     0.958G      1.373      1.287      1.697      1.285         10        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.665      0.534        0.6      0.355      0.663       0.53      0.581      0.289

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      25/30     0.956G      1.437      1.277      1.644      1.309          8        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.628       0.56      0.571      0.344      0.607      0.532      0.552      0.274

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      26/30     0.956G      1.387      1.257      1.554      1.293          1        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.564      0.578      0.581      0.356      0.549      0.562       0.56      0.288

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      27/30     0.956G      1.339      1.293      1.522      1.303          5        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.571      0.576      0.583      0.358      0.562      0.563      0.561      0.285

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      28/30     0.956G       1.32      1.255      1.451      1.252          2        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575       0.65      0.541        0.6      0.368      0.635      0.544      0.585      0.293

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      29/30     0.954G      1.338      1.191      1.559      1.277          4        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.639      0.561      0.612      0.364      0.613      0.562      0.594      0.298

      Epoch    GPU_mem   box_loss   seg_loss   cls_loss   dfl_loss  Instances       Size
      30/30     0.956G      1.298      1.234      1.599      1.246          5        640: 100%|█████████
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.661      0.557       0.59      0.358      0.652       0.55       0.57       0.29

30 epochs completed in 0.349 hours.
Optimizer stripped from workflow_examples/yolo/runs/train2/weights/last.pt, 6.8MB
Optimizer stripped from workflow_examples/yolo/runs/train2/weights/best.pt, 6.8MB

Validating workflow_examples/yolo/runs/train2/weights/best.pt...
Ultralytics YOLOv8.0.180 🚀 Python-3.11.5 torch-2.0.1 CUDA:0 (NVIDIA RTX A2000 8GB Laptop GPU, 8192MiB)
YOLOv8n-seg summary (fused): 195 layers, 3258454 parameters, 0 gradients
                 Class     Images  Instances      Box(P          R      mAP50  mAP50-95)     Mask(P     
                   all        140        575      0.644      0.617      0.636      0.378      0.636      0.609      0.617       0.31
            groundwood        140        446      0.571      0.529      0.532      0.291      0.564      0.522      0.496      0.203
           uprightwood        140        129      0.716      0.705       0.74      0.464      0.708      0.696      0.738      0.418
Speed: 1.3ms preprocess, 23.2ms inference, 0.0ms loss, 1.7ms postprocess per image
Results saved to workflow_examples/yolo/runs/train2
  • Report an issue