ultralytics 8.2.38 official YOLOv10 support (#13113)
Signed-off-by: Glenn Jocher <glenn.jocher@ultralytics.com> Co-authored-by: UltralyticsAssistant <web@ultralytics.com> Co-authored-by: Laughing-q <1185102784@qq.com> Co-authored-by: Glenn Jocher <glenn.jocher@ultralytics.com> Co-authored-by: Laughing <61612323+Laughing-q@users.noreply.github.com>
This commit is contained in:
parent
821e5fa477
commit
ffb46fd7fb
23 changed files with 785 additions and 32 deletions
|
|
@ -81,6 +81,7 @@ def benchmark(
|
|||
device = select_device(device, verbose=False)
|
||||
if isinstance(model, (str, Path)):
|
||||
model = YOLO(model)
|
||||
is_end2end = getattr(model.model.model[-1], "end2end", False)
|
||||
|
||||
y = []
|
||||
t0 = time.time()
|
||||
|
|
@ -96,14 +97,18 @@ def benchmark(
|
|||
assert MACOS or LINUX, "CoreML and TF.js export only supported on macOS and Linux"
|
||||
assert not IS_RASPBERRYPI, "CoreML and TF.js export not supported on Raspberry Pi"
|
||||
assert not IS_JETSON, "CoreML and TF.js export not supported on NVIDIA Jetson"
|
||||
assert not is_end2end, "End-to-end models not supported by CoreML and TF.js yet"
|
||||
if i in {3, 5}: # CoreML and OpenVINO
|
||||
assert not IS_PYTHON_3_12, "CoreML and OpenVINO not supported on Python 3.12"
|
||||
if i in {6, 7, 8, 9, 10}: # All TF formats
|
||||
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 TensorFlow exports not supported by onnx2tf yet"
|
||||
assert not is_end2end, "End-to-end models not supported by onnx2tf yet"
|
||||
if i in {11}: # Paddle
|
||||
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 Paddle exports not supported yet"
|
||||
assert not is_end2end, "End-to-end models not supported by PaddlePaddle yet"
|
||||
if i in {12}: # NCNN
|
||||
assert not isinstance(model, YOLOWorld), "YOLOWorldv2 NCNN exports not supported yet"
|
||||
assert not is_end2end, "End-to-end models not supported by NCNN yet"
|
||||
if "cpu" in device.type:
|
||||
assert cpu, "inference not supported on CPU"
|
||||
if "cuda" in device.type:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ GITHUB_ASSETS_NAMES = (
|
|||
+ [f"yolov8{k}-world.pt" for k in "smlx"]
|
||||
+ [f"yolov8{k}-worldv2.pt" for k in "smlx"]
|
||||
+ [f"yolov9{k}.pt" for k in "ce"]
|
||||
+ [f"yolov10{k}.pt" for k in "nsmblx"]
|
||||
+ [f"yolo_nas_{k}.pt" for k in "sml"]
|
||||
+ [f"sam_{k}.pt" for k in "bl"]
|
||||
+ [f"FastSAM-{k}.pt" for k in "sx"]
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ class KeypointLoss(nn.Module):
|
|||
class v8DetectionLoss:
|
||||
"""Criterion class for computing training losses."""
|
||||
|
||||
def __init__(self, model): # model must be de-paralleled
|
||||
def __init__(self, model, tal_topk=10): # model must be de-paralleled
|
||||
"""Initializes v8DetectionLoss with the model, defining model-related properties and BCE loss function."""
|
||||
device = next(model.parameters()).device # get model device
|
||||
h = model.args # hyperparameters
|
||||
|
|
@ -164,7 +164,7 @@ class v8DetectionLoss:
|
|||
|
||||
self.use_dfl = m.reg_max > 1
|
||||
|
||||
self.assigner = TaskAlignedAssigner(topk=10, num_classes=self.nc, alpha=0.5, beta=6.0)
|
||||
self.assigner = TaskAlignedAssigner(topk=tal_topk, num_classes=self.nc, alpha=0.5, beta=6.0)
|
||||
self.bbox_loss = BboxLoss(m.reg_max - 1, use_dfl=self.use_dfl).to(device)
|
||||
self.proj = torch.arange(m.reg_max, dtype=torch.float, device=device)
|
||||
|
||||
|
|
@ -714,3 +714,21 @@ class v8OBBLoss(v8DetectionLoss):
|
|||
b, a, c = pred_dist.shape # batch, anchors, channels
|
||||
pred_dist = pred_dist.view(b, a, 4, c // 4).softmax(3).matmul(self.proj.type(pred_dist.dtype))
|
||||
return torch.cat((dist2rbox(pred_dist, pred_angle, anchor_points), pred_angle), dim=-1)
|
||||
|
||||
|
||||
class E2EDetectLoss:
|
||||
"""Criterion class for computing training losses."""
|
||||
|
||||
def __init__(self, model):
|
||||
"""Initialize E2EDetectLoss with one-to-many and one-to-one detection losses using the provided model."""
|
||||
self.one2many = v8DetectionLoss(model, tal_topk=10)
|
||||
self.one2one = v8DetectionLoss(model, tal_topk=1)
|
||||
|
||||
def __call__(self, preds, batch):
|
||||
"""Calculate the sum of the loss for box, cls and dfl multiplied by batch size."""
|
||||
preds = preds[1] if isinstance(preds, tuple) else preds
|
||||
one2many = preds["one2many"]
|
||||
loss_one2many = self.one2many(one2many, batch)
|
||||
one2one = preds["one2one"]
|
||||
loss_one2one = self.one2one(one2one, batch)
|
||||
return loss_one2many[0] + loss_one2one[0], loss_one2many[1] + loss_one2one[1]
|
||||
|
|
|
|||
|
|
@ -64,8 +64,9 @@ def box_iou(box1, box2, eps=1e-7):
|
|||
(torch.Tensor): An NxM tensor containing the pairwise IoU values for every element in box1 and box2.
|
||||
"""
|
||||
|
||||
# NOTE: Need .float() to get accurate iou values
|
||||
# inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)
|
||||
(a1, a2), (b1, b2) = box1.unsqueeze(1).chunk(2, 2), box2.unsqueeze(0).chunk(2, 2)
|
||||
(a1, a2), (b1, b2) = box1.float().unsqueeze(1).chunk(2, 2), box2.float().unsqueeze(0).chunk(2, 2)
|
||||
inter = (torch.min(a2, b2) - torch.max(a1, b1)).clamp_(0).prod(2)
|
||||
|
||||
# IoU = inter / (area1 + area2 - inter)
|
||||
|
|
|
|||
|
|
@ -213,6 +213,9 @@ def non_max_suppression(
|
|||
if isinstance(prediction, (list, tuple)): # YOLOv8 model in validation model, output = (inference_out, loss_out)
|
||||
prediction = prediction[0] # select only inference output
|
||||
|
||||
if prediction.shape[-1] == 6: # end-to-end model
|
||||
return [pred[pred[:, 4] > conf_thres] for pred in prediction]
|
||||
|
||||
bs = prediction.shape[0] # batch size
|
||||
nc = nc or (prediction.shape[1] - 4) # number of classes
|
||||
nm = prediction.shape[1] - nc - 4 # number of masks
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue