Move tests outside package (#104)
This commit is contained in:
49
tests/assets/dummy_model.yaml
Normal file
49
tests/assets/dummy_model.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
# Ultralytics, GPL-3.0 license
|
||||
|
||||
# Parameters
|
||||
nc: 80 # number of classes
|
||||
depth_multiple: 0.33 # model depth multiple
|
||||
width_multiple: 0.50 # layer channel multiple
|
||||
anchors:
|
||||
- [10,13, 16,30, 33,23] # P3/8
|
||||
- [30,61, 62,45, 59,119] # P4/16
|
||||
- [116,90, 156,198, 373,326] # P5/32
|
||||
|
||||
# YOLOv5 v6.0 backbone
|
||||
backbone:
|
||||
# [from, number, module, args]
|
||||
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
|
||||
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
|
||||
[-1, 3, C3, [128]],
|
||||
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
|
||||
[-1, 6, C3, [256]],
|
||||
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
|
||||
[-1, 9, C3, [512]],
|
||||
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
|
||||
[-1, 3, C3, [1024]],
|
||||
[-1, 1, SPPF, [1024, 5]], # 9
|
||||
]
|
||||
|
||||
# YOLOv5 v6.0 head
|
||||
head:
|
||||
[[-1, 1, Conv, [512, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 6], 1, Concat, [1]], # cat backbone P4
|
||||
[-1, 3, C3, [512, False]], # 13
|
||||
|
||||
[-1, 1, Conv, [256, 1, 1]],
|
||||
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
|
||||
[[-1, 4], 1, Concat, [1]], # cat backbone P3
|
||||
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
|
||||
|
||||
[-1, 1, Conv, [256, 3, 2]],
|
||||
[[-1, 14], 1, Concat, [1]], # cat head P4
|
||||
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
|
||||
|
||||
[-1, 1, Conv, [512, 3, 2]],
|
||||
[[-1, 10], 1, Concat, [1]], # cat head P5
|
||||
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
|
||||
|
||||
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
|
||||
]
|
||||
|
29
tests/data/dataloader/hyp_test.yaml
Normal file
29
tests/data/dataloader/hyp_test.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
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)
|
87
tests/data/dataloader/yolodetection.py
Normal file
87
tests/data/dataloader/yolodetection.py
Normal file
@ -0,0 +1,87 @@
|
||||
import cv2
|
||||
import hydra
|
||||
|
||||
from ultralytics.yolo.data import build_dataloader
|
||||
from ultralytics.yolo.utils import ROOT
|
||||
from ultralytics.yolo.utils.plotting import plot_images
|
||||
|
||||
DEFAULT_CONFIG = ROOT / "yolo/utils/configs/default.yaml"
|
||||
|
||||
|
||||
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)
|
125
tests/data/dataloader/yolopose.py
Normal file
125
tests/data/dataloader/yolopose.py
Normal file
@ -0,0 +1,125 @@
|
||||
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)
|
87
tests/data/dataloader/yolosegment.py
Normal file
87
tests/data/dataloader/yolosegment.py
Normal file
@ -0,0 +1,87 @@
|
||||
import cv2
|
||||
import hydra
|
||||
|
||||
from ultralytics.yolo.data import build_dataloader
|
||||
from ultralytics.yolo.utils import ROOT
|
||||
from ultralytics.yolo.utils.plotting import plot_images
|
||||
|
||||
DEFAULT_CONFIG = ROOT / "yolo/utils/configs/default.yaml"
|
||||
|
||||
|
||||
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)
|
32
tests/functional/test_loaders.py
Normal file
32
tests/functional/test_loaders.py
Normal file
@ -0,0 +1,32 @@
|
||||
from ultralytics.nn.tasks import DetectionModel
|
||||
from ultralytics.yolo.utils.checks import check_yaml
|
||||
|
||||
|
||||
def test_model_parser():
|
||||
cfg = check_yaml("../assets/dummy_model.yaml") # check YAML
|
||||
|
||||
# Create model
|
||||
model = DetectionModel(cfg)
|
||||
print(model)
|
||||
'''
|
||||
# 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()
|
73
tests/test_model.py
Normal file
73
tests/test_model.py
Normal file
@ -0,0 +1,73 @@
|
||||
import torch
|
||||
|
||||
from ultralytics.yolo import YOLO
|
||||
|
||||
|
||||
def test_model_forward():
|
||||
model = YOLO()
|
||||
model.new("yolov8n-seg.yaml")
|
||||
img = torch.rand(512 * 512 * 3).view(1, 3, 512, 512)
|
||||
model.forward(img)
|
||||
model(img)
|
||||
|
||||
|
||||
def test_model_info():
|
||||
model = YOLO()
|
||||
model.new("yolov8n.yaml")
|
||||
model.info()
|
||||
model.load("balloon-detect.pt")
|
||||
model.info(verbose=True)
|
||||
|
||||
|
||||
def test_model_fuse():
|
||||
model = YOLO()
|
||||
model.new("yolov8n.yaml")
|
||||
model.fuse()
|
||||
model.load("balloon-detect.pt")
|
||||
model.fuse()
|
||||
|
||||
|
||||
def test_visualize_preds():
|
||||
model = YOLO()
|
||||
model.load("balloon-segment.pt")
|
||||
model.predict(source="ultralytics/assets")
|
||||
|
||||
|
||||
def test_val():
|
||||
model = YOLO()
|
||||
model.load("balloon-segment.pt")
|
||||
model.val(data="coco128-seg.yaml", imgsz=32)
|
||||
|
||||
|
||||
def test_model_resume():
|
||||
model = YOLO()
|
||||
model.new("yolov8n-seg.yaml")
|
||||
model.train(epochs=1, imgsz=32, data="coco128-seg.yaml")
|
||||
try:
|
||||
model.resume(task="segment")
|
||||
except AssertionError:
|
||||
print("Successfully caught resume assert!")
|
||||
|
||||
|
||||
def test_model_train_pretrained():
|
||||
model = YOLO()
|
||||
model.load("balloon-detect.pt")
|
||||
model.train(data="coco128.yaml", epochs=1, imgsz=32)
|
||||
model.new("yolov8n.yaml")
|
||||
model.train(data="coco128.yaml", epochs=1, imgsz=32)
|
||||
img = torch.rand(512 * 512 * 3).view(1, 3, 512, 512)
|
||||
model(img)
|
||||
|
||||
|
||||
def test():
|
||||
test_model_forward()
|
||||
test_model_info()
|
||||
test_model_fuse()
|
||||
test_visualize_preds()
|
||||
test_val()
|
||||
test_model_resume()
|
||||
test_model_train_pretrained()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
Reference in New Issue
Block a user