diff --git a/README.md b/README.md
index d4993b6..ac3ecaa 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
[![Ultralytics CI](https://github.com/ultralytics/ultralytics/actions/workflows/ci.yaml/badge.svg)](https://github.com/ultralytics/ultralytics/actions/workflows/ci.yaml)
-### Install
+## Install
```bash
pip install ultralytics
@@ -38,10 +38,39 @@ model = YOLO("yolov8n.yaml") # create a new model from scratch
model = YOLO(
"yolov8n.pt"
) # load a pretrained model (recommended for best training results)
-results = model.train(data="coco128.yaml", epochs=100, imgsz=640, ...)
+results = model.train(data="coco128.yaml", epochs=100, imgsz=640)
results = model.val()
results = model.predict(source="bus.jpg")
success = model.export(format="onnx")
```
+## Models
+
+| Model | size
(pixels) | mAPval
50-95 | Speed
CPU
(ms) | Speed
T4 GPU
(ms) | params
(M) | FLOPs
(B) |
+| ------------------------------------------------------------------------------------------------ | --------------------- | -------------------- | ------------------------- | ---------------------------- | ------------------ | ----------------- |
+| [YOLOv5n](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5n.pt) | 640 | 28.0 | - | - | **1.9** | **4.5** |
+| [YOLOv6n](url) | 640 | 35.9 | - | - | 4.3 | 11.1 |
+| **[YOLOv8n](url)** | 640 | **37.5** | - | - | 3.2 | 8.9 |
+| | | | | | | |
+| [YOLOv5s](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5s.pt) | 640 | 37.4 | - | - | 7.2 | 16.5 |
+| [YOLOv6s](url) | 640 | 43.5 | - | - | 17.2 | 44.2 |
+| **[YOLOv8s](url)** | 640 | **44.7** | - | - | 11.2 | 28.8 |
+| | | | | | | |
+| [YOLOv5m](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5m.pt) | 640 | 45.4 | - | - | 21.2 | 49.0 |
+| [YOLOv6m](url) | 640 | 49.5 | - | - | 34.3 | 82.2 |
+| **[YOLOv8m](url)** | 640 | **50.3** | - | - | 25.9 | 79.3 |
+| | | | | | | |
+| [YOLOv5l](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5l.pt) | 640 | 49.0 | - | - | 46.5 | 109.1 |
+| [YOLOv6l](url) | 640 | 52.5 | - | - | 58.5 | 144.0 |
+| [YOLOv7](url) | 640 | 51.2 | - | - | 36.9 | 104.7 |
+| **[YOLOv8l](url)** | 640 | **52.8** | - | - | 43.7 | 165.7 |
+| | | | | | | |
+| [YOLOv5x](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5x.pt) | 640 | 50.7 | - | - | 86.7 | 205.7 |
+| [YOLOv7-X](url) | 640 | 52.9 | - | - | 71.3 | 189.9 |
+| **[YOLOv8x](url)** | 640 | **53.7** | - | - | 68.2 | 258.5 |
+| | | | | | | |
+| [YOLOv5x6](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5x6.pt) | 1280 | 55.0 | - | - | 140.7 | 839.2 |
+| [YOLOv7-E6E](url) | 1280 | 56.8 | - | - | 151.7 | 843.2 |
+| **[YOLOv8x6](https://github.com/ultralytics/yolov5/releases/download/v6.2/yolov5x6.pt)**
+TTA | 1280 | -
- | -
- | -
- | 97.4 | 1047.2
- |
+
If you're looking to modify YOLO for R&D or to build on top of it, refer to [Using Trainer](<>) Guide on our docs.
diff --git a/tests/check_flops.py b/tests/check_flops.py
deleted file mode 100644
index fd2bbd3..0000000
--- a/tests/check_flops.py
+++ /dev/null
@@ -1,15 +0,0 @@
-from ultralytics import YOLO
-from ultralytics.yolo.utils import ROOT
-
-if __name__ == "__main__":
- for m in list((ROOT / 'yolo/v8/models').rglob('*.yaml')):
- try:
- YOLO(m.name, verbose=True)
- except Exception as e:
- print(f'ERROR for {m}: {e}')
-
- # n vs n-seg: 8.9GFLOPs vs 12.8GFLOPs, 3.16M vs 3.6M. ch[0] // 4 (11.9GFLOPs, 3.39M)
- # s vs s-seg: 28.8GFLOPs vs 44.4GFLOPs, 11.1M vs 12.9M. ch[0] // 4 (39.5GFLOPs, 11.7M)
- # m vs m-seg: 79.3GFLOPs vs 113.8GFLOPs, 25.9M vs 29.5M. ch[0] // 4 (103.GFLOPs, 27.1M)
- # l vs l-seg: 165.7GFLOPs vs 226.3GFLOPs, 43.7M vs 49.6M. ch[0] // 4 (207GFLOPs, 45.7M)
- # x vs x-seg: 258.5GFLOPs vs 353.0GFLOPs, 68.3M vs 77.5M. ch[0] // 4 (324GFLOPs, 71.4M)
diff --git a/tests/data/dataloader/hyp_test.yaml b/tests/data/dataloader/hyp_test.yaml
deleted file mode 100644
index de6ae73..0000000
--- a/tests/data/dataloader/hyp_test.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-lr0: 0.001 # initial learning rate (SGD=1E-2, Adam=1E-3)
-lrf: 0.01 # final OneCycleLR learning rate (lr0 * lrf)
-momentum: 0.937 # SGD momentum/Adam beta1
-weight_decay: 0.0005 # optimizer weight decay 5e-4
-warmup_epochs: 3.0 # warmup epochs (fractions ok)
-warmup_momentum: 0.8 # warmup initial momentum
-warmup_bias_lr: 0.1 # warmup initial bias lr
-box: 0.05 # box loss gain
-cls: 0.5 # cls loss gain
-cls_pw: 1.0 # cls BCELoss positive_weight
-obj: 1.0 # obj loss gain (scale with pixels)
-obj_pw: 1.0 # obj BCELoss positive_weight
-iou_t: 0.20 # IoU training threshold
-anchor_t: 4.0 # anchor-multiple threshold
-# anchors: 3 # anchors per output layer (0 to ignore)
-fl_gamma: 0.0 # focal loss gamma (efficientDet default gamma=1.5)
-hsv_h: 0.015 # image HSV-Hue augmentation (fraction)
-hsv_s: 0.7 # image HSV-Saturation augmentation (fraction)
-hsv_v: 0.4 # image HSV-Value augmentation (fraction)
-degrees: 0.0 # image rotation (+/- deg)
-translate: 0.1 # image translation (+/- fraction)
-scale: 0.5 # image scale (+/- gain)
-shear: 0.0 # image shear (+/- deg)
-perspective: 0.0 # image perspective (+/- fraction), range 0-0.001
-flipud: 0.0 # image flip up-down (probability)
-fliplr: 0.5 # image flip left-right (probability)
-mosaic: 1.0 # image mosaic (probability)
-mixup: 0.0 # image mixup (probability)
-copy_paste: 0.5 # segment copy-paste (probability)
diff --git a/tests/data/dataloader/yolodetection.py b/tests/data/dataloader/yolodetection.py
deleted file mode 100644
index eb03ac3..0000000
--- a/tests/data/dataloader/yolodetection.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import cv2
-import hydra
-
-from ultralytics.yolo.data import build_dataloader
-from ultralytics.yolo.utils import DEFAULT_CONFIG
-from ultralytics.yolo.utils.plotting import plot_images
-
-
-class Colors:
- # Ultralytics color palette https://ultralytics.com/
- def __init__(self):
- # hex = matplotlib.colors.TABLEAU_COLORS.values()
- hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
- '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
- self.palette = [self.hex2rgb(f'#{c}') for c in hexs]
- self.n = len(self.palette)
-
- def __call__(self, i, bgr=False):
- c = self.palette[int(i) % self.n]
- return (c[2], c[1], c[0]) if bgr else c
-
- @staticmethod
- def hex2rgb(h): # rgb order (PIL)
- return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
-
-
-colors = Colors() # create instance for 'from utils.plots import colors'
-
-
-def plot_one_box(x, img, color=None, label=None, line_thickness=None):
- import random
-
- # Plots one bounding box on image img
- tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
- color = color or [random.randint(0, 255) for _ in range(3)]
- c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
- cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
- if label:
- tf = max(tl - 1, 1) # font thickness
- t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
- c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
- cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # filled
- cv2.putText(
- img,
- label,
- (c1[0], c1[1] - 2),
- 0,
- tl / 3,
- [225, 255, 255],
- thickness=tf,
- lineType=cv2.LINE_AA,
- )
-
-
-@hydra.main(version_base=None, config_path=str(DEFAULT_CONFIG.parent), config_name=DEFAULT_CONFIG.name)
-def test(cfg):
- cfg.task = "detect"
- cfg.mode = "train"
- dataloader, _ = build_dataloader(
- cfg=cfg,
- batch_size=4,
- img_path="/d/dataset/COCO/coco128-seg/images",
- stride=32,
- label_path=None,
- mode=cfg.mode,
- )
-
- for d in dataloader:
- images = d["img"]
- cls = d["cls"].squeeze(-1)
- bboxes = d["bboxes"]
- paths = d["im_file"]
- batch_idx = d["batch_idx"]
- result = plot_images(images, batch_idx, cls, bboxes, paths=paths)
-
- cv2.imshow("p", result)
- if cv2.waitKey(0) == ord("q"):
- break
-
-
-if __name__ == "__main__":
- test()
- # test(augment=True, rect=False)
- # test(augment=False, rect=True)
- # test(augment=False, rect=False)
diff --git a/tests/data/dataloader/yolopose.py b/tests/data/dataloader/yolopose.py
deleted file mode 100644
index e56b3bb..0000000
--- a/tests/data/dataloader/yolopose.py
+++ /dev/null
@@ -1,125 +0,0 @@
-import cv2
-import numpy as np
-from omegaconf import OmegaConf
-
-from ultralytics.yolo.data import build_dataloader
-
-
-class Colors:
- # Ultralytics color palette https://ultralytics.com/
- def __init__(self):
- # hex = matplotlib.colors.TABLEAU_COLORS.values()
- hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
- '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
- self.palette = [self.hex2rgb(f'#{c}') for c in hexs]
- self.n = len(self.palette)
-
- def __call__(self, i, bgr=False):
- c = self.palette[int(i) % self.n]
- return (c[2], c[1], c[0]) if bgr else c
-
- @staticmethod
- def hex2rgb(h): # rgb order (PIL)
- return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
-
-
-colors = Colors() # create instance for 'from utils.plots import colors'
-
-
-def plot_one_box(x, img, keypoints=None, color=None, label=None, line_thickness=None):
- import random
-
- # Plots one bounding box on image img
- tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
- color = color or [random.randint(0, 255) for _ in range(3)]
- c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
- cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
- if label:
- tf = max(tl - 1, 1) # font thickness
- t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
- c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
- cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # filled
- cv2.putText(
- img,
- label,
- (c1[0], c1[1] - 2),
- 0,
- tl / 3,
- [225, 255, 255],
- thickness=tf,
- lineType=cv2.LINE_AA,
- )
- if keypoints is not None:
- plot_keypoint(img, keypoints, color, tl)
-
-
-def plot_keypoint(img, keypoints, color, tl):
- num_l = len(keypoints)
- # clors = [(255, 0, 0),(0, 255, 0),(0, 0, 255),(255, 255, 0),(0, 255, 255)]
- # clors = [[random.randint(0, 255) for _ in range(3)] for _ in range(num_l)]
- for i in range(num_l):
- point_x = int(keypoints[i][0])
- point_y = int(keypoints[i][1])
- cv2.circle(img, (point_x, point_y), tl + 3, color, -1)
-
-
-with open("ultralytics/tests/data/dataloader/hyp_test.yaml") as f:
- hyp = OmegaConf.load(f)
-
-
-def test(augment, rect):
- dataloader, _ = build_dataloader(
- img_path="/d/dataset/COCO/images/val2017",
- imgsz=640,
- label_path=None,
- cache=False,
- hyp=hyp,
- augment=augment,
- prefix="",
- rect=rect,
- batch_size=4,
- stride=32,
- pad=0.5,
- use_segments=False,
- use_keypoints=True,
- )
-
- for d in dataloader:
- idx = 1 # show which image inside one batch
- img = d["img"][idx].numpy()
- img = np.ascontiguousarray(img.transpose(1, 2, 0))
- ih, iw = img.shape[:2]
- # print(img.shape)
- bidx = d["batch_idx"]
- cls = d["cls"][bidx == idx].numpy()
- bboxes = d["bboxes"][bidx == idx].numpy()
- bboxes[:, [0, 2]] *= iw
- bboxes[:, [1, 3]] *= ih
- keypoints = d["keypoints"][bidx == idx]
- keypoints[..., 0] *= iw
- keypoints[..., 1] *= ih
- # print(keypoints, keypoints.shape)
- # print(d["im_file"])
-
- for i, b in enumerate(bboxes):
- x, y, w, h = b
- x1 = x - w / 2
- x2 = x + w / 2
- y1 = y - h / 2
- y2 = y + h / 2
- c = int(cls[i][0])
- # print(x1, y1, x2, y2)
- plot_one_box([int(x1), int(y1), int(x2), int(y2)],
- img,
- keypoints=keypoints[i],
- label=f"{c}",
- color=colors(c))
- cv2.imshow("p", img)
- if cv2.waitKey(0) == ord("q"):
- break
-
-
-if __name__ == "__main__":
- test(augment=True, rect=False)
- test(augment=False, rect=True)
- test(augment=False, rect=False)
diff --git a/tests/data/dataloader/yolosegment.py b/tests/data/dataloader/yolosegment.py
deleted file mode 100644
index 8daf406..0000000
--- a/tests/data/dataloader/yolosegment.py
+++ /dev/null
@@ -1,85 +0,0 @@
-import cv2
-import hydra
-
-from ultralytics.yolo.data import build_dataloader
-from ultralytics.yolo.utils import DEFAULT_CONFIG
-from ultralytics.yolo.utils.plotting import plot_images
-
-
-class Colors:
- # Ultralytics color palette https://ultralytics.com/
- def __init__(self):
- # hex = matplotlib.colors.TABLEAU_COLORS.values()
- hexs = ('FF3838', 'FF9D97', 'FF701F', 'FFB21D', 'CFD231', '48F90A', '92CC17', '3DDB86', '1A9334', '00D4BB',
- '2C99A8', '00C2FF', '344593', '6473FF', '0018EC', '8438FF', '520085', 'CB38FF', 'FF95C8', 'FF37C7')
- self.palette = [self.hex2rgb(f'#{c}') for c in hexs]
- self.n = len(self.palette)
-
- def __call__(self, i, bgr=False):
- c = self.palette[int(i) % self.n]
- return (c[2], c[1], c[0]) if bgr else c
-
- @staticmethod
- def hex2rgb(h): # rgb order (PIL)
- return tuple(int(h[1 + i:1 + i + 2], 16) for i in (0, 2, 4))
-
-
-colors = Colors() # create instance for 'from utils.plots import colors'
-
-
-def plot_one_box(x, img, color=None, label=None, line_thickness=None):
- import random
-
- # Plots one bounding box on image img
- tl = line_thickness or round(0.002 * (img.shape[0] + img.shape[1]) / 2) + 1 # line/font thickness
- color = color or [random.randint(0, 255) for _ in range(3)]
- c1, c2 = (int(x[0]), int(x[1])), (int(x[2]), int(x[3]))
- cv2.rectangle(img, c1, c2, color, thickness=tl, lineType=cv2.LINE_AA)
- if label:
- tf = max(tl - 1, 1) # font thickness
- t_size = cv2.getTextSize(label, 0, fontScale=tl / 3, thickness=tf)[0]
- c2 = c1[0] + t_size[0], c1[1] - t_size[1] - 3
- cv2.rectangle(img, c1, c2, color, -1, cv2.LINE_AA) # filled
- cv2.putText(
- img,
- label,
- (c1[0], c1[1] - 2),
- 0,
- tl / 3,
- [225, 255, 255],
- thickness=tf,
- lineType=cv2.LINE_AA,
- )
-
-
-@hydra.main(version_base=None, config_path=str(DEFAULT_CONFIG.parent), config_name=DEFAULT_CONFIG.name)
-def test(cfg):
- cfg.task = "segment"
- cfg.mode = "train"
- dataloader, _ = build_dataloader(
- cfg=cfg,
- batch_size=4,
- img_path="/d/dataset/COCO/coco128-seg/images",
- stride=32,
- label_path=None,
- mode=cfg.mode,
- )
-
- for d in dataloader:
- images = d["img"]
- masks = d["masks"]
- cls = d["cls"].squeeze(-1)
- bboxes = d["bboxes"]
- paths = d["im_file"]
- batch_idx = d["batch_idx"]
- result = plot_images(images, batch_idx, cls, bboxes, masks, paths=paths)
- cv2.imshow("p", result)
- if cv2.waitKey(0) == ord("q"):
- break
-
-
-if __name__ == "__main__":
- test()
- # test(augment=True, rect=False)
- # test(augment=False, rect=True)
- # test(augment=False, rect=False)
diff --git a/tests/functional/test_loaders.py b/tests/functional/test_loaders.py
deleted file mode 100644
index 84b0d76..0000000
--- a/tests/functional/test_loaders.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from ultralytics.nn.tasks import DetectionModel
-from ultralytics.yolo.utils.checks import check_yaml
-
-
-def test_model_parser():
- cfg = check_yaml("yolov8n.yaml") # check YAML
-
- # Create model
- model = DetectionModel(cfg)
- model.info()
- '''
- # Options
- if opt.line_profile: # profile layer by layer
- model(im, profile=True)
-
- elif opt.profile: # profile forward-backward
- results = profile(input=im, ops=[model], n=3)
-
- elif opt.test: # test all models
- for cfg in Path(ROOT / 'models').rglob('yolo*.yaml'):
- try:
- _ = Model(cfg)
- except Exception as e:
- print(f'Error in {cfg}: {e}')
-
- else: # report fused model summary
- model.fuse()
- '''
-
-
-if __name__ == "__main__":
- test_model_parser()
diff --git a/tests/tests_cli.py b/tests/test_cli.py
similarity index 71%
rename from tests/tests_cli.py
rename to tests/test_cli.py
index b6b053c..9687ce5 100644
--- a/tests/tests_cli.py
+++ b/tests/test_cli.py
@@ -1,6 +1,10 @@
import os
+from pathlib import Path
-from ultralytics.yolo.utils import ROOT
+from ultralytics.yolo.utils import ROOT, SETTINGS
+
+MODEL = Path(SETTINGS['weights_dir']) / 'yolov8n.pt'
+CFG = 'yolov8n.yaml'
def test_checks():
@@ -9,7 +13,7 @@ def test_checks():
# Train checks ---------------------------------------------------------------------------------------------------------
def test_train_detect():
- os.system('yolo mode=train task=detect model=yolov8n.yaml data=coco128.yaml imgsz=32 epochs=1')
+ os.system(f'yolo mode=train task=detect model={MODEL} data=coco128.yaml imgsz=32 epochs=1')
def test_train_segment():
@@ -22,7 +26,7 @@ def test_train_classify():
# Val checks -----------------------------------------------------------------------------------------------------------
def test_val_detect():
- os.system('yolo mode=val task=detect model=yolov8n.pt data=coco128.yaml imgsz=32 epochs=1')
+ os.system(f'yolo mode=val task=detect model={MODEL} data=coco128.yaml imgsz=32 epochs=1')
def test_val_segment():
@@ -35,7 +39,7 @@ def test_val_classify():
# Predict checks -------------------------------------------------------------------------------------------------------
def test_predict_detect():
- os.system(f"yolo mode=predict model=yolov8n.pt source={ROOT / 'assets'}")
+ os.system(f"yolo mode=predict model={MODEL} source={ROOT / 'assets'}")
def test_predict_segment():
@@ -48,7 +52,7 @@ def test_predict_classify():
# Export checks --------------------------------------------------------------------------------------------------------
def test_export_detect_torchscript():
- os.system('yolo mode=export model=yolov8n.pt format=torchscript')
+ os.system(f'yolo mode=export model={MODEL} format=torchscript')
def test_export_segment_torchscript():
diff --git a/tests/tests.py b/tests/test_python.py
similarity index 91%
rename from tests/tests.py
rename to tests/test_python.py
index e7a22fe..571a466 100644
--- a/tests/tests.py
+++ b/tests/test_python.py
@@ -1,9 +1,11 @@
+from pathlib import Path
+
import torch
from ultralytics import YOLO
-from ultralytics.yolo.utils import ROOT
+from ultralytics.yolo.utils import ROOT, SETTINGS
-MODEL = ROOT / 'weights/yolov8n.pt'
+MODEL = Path(SETTINGS['weights_dir']) / 'yolov8n.pt'
CFG = 'yolov8n.yaml'
@@ -95,6 +97,11 @@ def test_export_paddle():
model.export(format='paddle')
+def test_all_model_yamls():
+ for m in list((ROOT / 'yolo/v8/models').rglob('*.yaml')):
+ YOLO(m.name)
+
+
# def run_all_tests(): # do not name function test_...
# pass
#
diff --git a/ultralytics/nn/tasks.py b/ultralytics/nn/tasks.py
index f1b4fcb..5243129 100644
--- a/ultralytics/nn/tasks.py
+++ b/ultralytics/nn/tasks.py
@@ -142,7 +142,7 @@ class DetectionModel(BaseModel):
# YOLOv5 detection model
def __init__(self, cfg='yolov8n.yaml', ch=3, nc=None, verbose=True): # model, input channels, number of classes
super().__init__()
- self.yaml = cfg if isinstance(cfg, dict) else yaml_load(check_yaml(cfg)) # cfg dict
+ self.yaml = cfg if isinstance(cfg, dict) else yaml_load(check_yaml(cfg), append_filename=True) # cfg dict
# Define model
ch = self.yaml['ch'] = self.yaml.get('ch', ch) # input channels
diff --git a/ultralytics/yolo/data/utils.py b/ultralytics/yolo/data/utils.py
index 25554e9..85f8821 100644
--- a/ultralytics/yolo/data/utils.py
+++ b/ultralytics/yolo/data/utils.py
@@ -201,7 +201,7 @@ def check_dataset_yaml(data, autodownload=True):
extract_dir, autodownload = data.parent, False
# Read yaml (optional)
if isinstance(data, (str, Path)):
- data = yaml_load(data) # dictionary
+ data = yaml_load(data, append_filename=True) # dictionary
# Checks
for k in 'train', 'val', 'names':
diff --git a/ultralytics/yolo/engine/exporter.py b/ultralytics/yolo/engine/exporter.py
index 49a9742..dc457a0 100644
--- a/ultralytics/yolo/engine/exporter.py
+++ b/ultralytics/yolo/engine/exporter.py
@@ -67,7 +67,7 @@ import torch
import ultralytics
from ultralytics.nn.modules import Detect, Segment
-from ultralytics.nn.tasks import ClassificationModel, DetectionModel, SegmentationModel, attempt_load_weights
+from ultralytics.nn.tasks import ClassificationModel, DetectionModel, SegmentationModel
from ultralytics.yolo.configs import get_config
from ultralytics.yolo.data.dataloaders.stream_loaders import LoadImages
from ultralytics.yolo.data.utils import check_dataset
@@ -154,7 +154,7 @@ class Exporter:
# Load PyTorch model
self.device = select_device(self.args.device or 'cpu')
if self.args.half:
- if self.device.type == 'cpu' or not coreml:
+ if self.device.type == 'cpu' and not coreml:
LOGGER.info('half=True only compatible with GPU or CoreML export, i.e. use device=0 or format=coreml')
self.args.half = False
assert not self.args.dynamic, '--half not compatible with --dynamic, i.e. use either --half or --dynamic'
@@ -769,17 +769,22 @@ class Exporter:
def export(cfg):
cfg.model = cfg.model or "yolov8n.yaml"
cfg.format = cfg.format or "torchscript"
- exporter = Exporter(cfg)
-
- model = None
- if isinstance(cfg.model, (str, Path)):
- if Path(cfg.model).suffix == '.yaml':
- model = DetectionModel(cfg.model)
- elif Path(cfg.model).suffix == '.pt':
- model = attempt_load_weights(cfg.model, fuse=True)
- else:
- TypeError(f'Unsupported model type {cfg.model}')
- exporter(model=model)
+
+ # exporter = Exporter(cfg)
+ #
+ # model = None
+ # if isinstance(cfg.model, (str, Path)):
+ # if Path(cfg.model).suffix == '.yaml':
+ # model = DetectionModel(cfg.model)
+ # elif Path(cfg.model).suffix == '.pt':
+ # model = attempt_load_weights(cfg.model, fuse=True)
+ # else:
+ # TypeError(f'Unsupported model type {cfg.model}')
+ # exporter(model=model)
+
+ from ultralytics import YOLO
+ model = YOLO(cfg.model)
+ model.export(**cfg)
if __name__ == "__main__":
diff --git a/ultralytics/yolo/engine/model.py b/ultralytics/yolo/engine/model.py
index b4ba821..ddb1187 100644
--- a/ultralytics/yolo/engine/model.py
+++ b/ultralytics/yolo/engine/model.py
@@ -64,7 +64,7 @@ class YOLO:
verbose (bool): display model info on load
"""
cfg = check_yaml(cfg) # check YAML
- cfg_dict = yaml_load(cfg) # model dict
+ cfg_dict = yaml_load(cfg, append_filename=True) # model dict
self.task = guess_task_from_head(cfg_dict["head"][-1][-2])
self.ModelClass, self.TrainerClass, self.ValidatorClass, self.PredictorClass = \
self._guess_ops_from_task(self.task)
@@ -183,7 +183,7 @@ class YOLO:
overrides.update(kwargs)
if kwargs.get("cfg"):
LOGGER.info(f"cfg file passed. Overriding default params with {kwargs['cfg']}.")
- overrides = yaml_load(check_yaml(kwargs["cfg"]))
+ overrides = yaml_load(check_yaml(kwargs["cfg"]), append_filename=True)
overrides["task"] = self.task
overrides["mode"] = "train"
if not overrides.get("data"):
diff --git a/ultralytics/yolo/engine/validator.py b/ultralytics/yolo/engine/validator.py
index ed6fa60..055599d 100644
--- a/ultralytics/yolo/engine/validator.py
+++ b/ultralytics/yolo/engine/validator.py
@@ -157,7 +157,8 @@ class BaseValidator:
self.run_callbacks('on_val_end')
if self.training:
model.float()
- return {**stats, **trainer.label_loss_items(self.loss.cpu() / len(self.dataloader), prefix="val")}
+ results = {**stats, **trainer.label_loss_items(self.loss.cpu() / len(self.dataloader), prefix="val")}
+ return {k: round(float(v), 5) for k, v in results.items()} # return results as 5 decimal place floats
else:
self.logger.info('Speed: %.1fms pre-process, %.1fms inference, %.1fms loss, %.1fms post-process per image' %
self.speed)
diff --git a/ultralytics/yolo/utils/__init__.py b/ultralytics/yolo/utils/__init__.py
index 593311f..4940eaa 100644
--- a/ultralytics/yolo/utils/__init__.py
+++ b/ultralytics/yolo/utils/__init__.py
@@ -3,6 +3,7 @@ import inspect
import logging.config
import os
import platform
+import subprocess
import sys
import tempfile
import threading
@@ -171,6 +172,18 @@ def is_dir_writeable(dir_path: str) -> bool:
return False
+def get_git_root_dir():
+ """
+ Determines whether the current file is part of a git repository and if so, returns the repository root directory.
+ If the current file is not part of a git repository, returns None.
+ """
+ try:
+ output = subprocess.run(["git", "rev-parse", "--git-dir"], capture_output=True, check=True)
+ return Path(output.stdout.strip().decode('utf-8')).parent # parent/.git
+ except subprocess.CalledProcessError:
+ return None
+
+
def get_default_args(func):
# Get func() default arguments
signature = inspect.signature(func)
@@ -311,13 +324,13 @@ def yaml_save(file='data.yaml', data=None):
yaml.safe_dump({k: str(v) if isinstance(v, Path) else v for k, v in data.items()}, f, sort_keys=False)
-def yaml_load(file='data.yaml', append_filename=True):
+def yaml_load(file='data.yaml', append_filename=False):
"""
Load YAML data from a file.
Args:
file (str, optional): File name. Default is 'data.yaml'.
- append_filename (bool): Add the YAML filename to the YAML dictionary. Default is True.
+ append_filename (bool): Add the YAML filename to the YAML dictionary. Default is False.
Returns:
dict: YAML data and file name.
@@ -339,14 +352,13 @@ def get_settings(file=USER_CONFIG_DIR / 'settings.yaml'):
"""
from ultralytics.yolo.utils.torch_utils import torch_distributed_zero_first
- git_install = not is_pip_package()
+ root = get_git_root_dir() or Path('') # not is_pip_package()
defaults = {
- 'datasets_dir': str(ROOT / 'datasets') if git_install else 'datasets', # default datasets directory.
- 'weights_dir': str(ROOT / 'weights') if git_install else 'weights', # default weights directory.
- 'runs_dir': str(ROOT / 'runs') if git_install else 'runs', # default runs directory.
+ 'datasets_dir': str(root / 'datasets'), # default datasets directory.
+ 'weights_dir': str(root / 'weights'), # default weights directory.
+ 'runs_dir': str(root / 'runs'), # default runs directory.
'sync': True, # sync analytics to help with YOLO development
- 'uuid': uuid.getnode(), # device UUID to align analytics
- 'yaml_file': str(file)} # setting YAML file path
+ 'uuid': uuid.getnode()} # device UUID to align analytics
with torch_distributed_zero_first(RANK):
if not file.exists():
diff --git a/ultralytics/yolo/utils/callbacks/hub.py b/ultralytics/yolo/utils/callbacks/hub.py
index f4cf68f..1fadcbc 100644
--- a/ultralytics/yolo/utils/callbacks/hub.py
+++ b/ultralytics/yolo/utils/callbacks/hub.py
@@ -18,13 +18,7 @@ def on_pretrain_routine_end(trainer):
def on_fit_epoch_end(trainer):
session = getattr(trainer, 'hub_session', None)
if session:
- # Upload metrics after val end
- metrics = trainer.metrics
- for k, v in metrics.items():
- if isinstance(v, torch.Tensor):
- metrics[k] = v.item()
-
- session.metrics_queue[trainer.epoch] = json.dumps(metrics) # json string
+ session.metrics_queue[trainer.epoch] = json.dumps(trainer.metrics) # json string
if time() - session.t['metrics'] > session.rate_limits['metrics']:
session.upload_metrics()
session.t['metrics'] = time() # reset timer
diff --git a/ultralytics/yolo/utils/checks.py b/ultralytics/yolo/utils/checks.py
index e50becb..2d97d56 100644
--- a/ultralytics/yolo/utils/checks.py
+++ b/ultralytics/yolo/utils/checks.py
@@ -153,7 +153,7 @@ def check_python(minimum: str = '3.7.0') -> bool:
@TryExcept()
-def check_requirements(requirements=ROOT / 'requirements.txt', exclude=(), install=True, cmds=''):
+def check_requirements(requirements=ROOT.parent / 'requirements.txt', exclude=(), install=True, cmds=''):
# Check installed dependencies meet YOLOv5 requirements (pass *.txt file or list of packages or single package str)
prefix = colorstr('red', 'bold', 'requirements:')
check_python() # check python version
diff --git a/ultralytics/yolo/v8/detect/val.py b/ultralytics/yolo/v8/detect/val.py
index fa69306..27ae5a1 100644
--- a/ultralytics/yolo/v8/detect/val.py
+++ b/ultralytics/yolo/v8/detect/val.py
@@ -19,7 +19,7 @@ class DetectionValidator(BaseValidator):
def __init__(self, dataloader=None, save_dir=None, pbar=None, logger=None, args=None):
super().__init__(dataloader, save_dir, pbar, logger, args)
- self.data_dict = yaml_load(check_file(self.args.data)) if self.args.data else None
+ self.data_dict = yaml_load(check_file(self.args.data), append_filename=True) if self.args.data else None
self.is_coco = False
self.class_map = None
self.targets = None