From 14dbfeab57cb042908b4ad3da43fcf3c05938dec Mon Sep 17 00:00:00 2001 From: Kayzwer <68285002+Kayzwer@users.noreply.github.com> Date: Fri, 1 Mar 2024 19:27:58 +0800 Subject: [PATCH] Optimize function calls to method calls (#8507) Co-authored-by: UltralyticsAssistant Co-authored-by: Glenn Jocher --- ultralytics/utils/loss.py | 4 +-- ultralytics/utils/metrics.py | 70 ++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/ultralytics/utils/loss.py b/ultralytics/utils/loss.py index 271403e0..5c991990 100644 --- a/ultralytics/utils/loss.py +++ b/ultralytics/utils/loss.py @@ -137,10 +137,10 @@ class KeypointLoss(nn.Module): def forward(self, pred_kpts, gt_kpts, kpt_mask, area): """Calculates keypoint loss factor and Euclidean distance loss for predicted and actual keypoints.""" - d = (pred_kpts[..., 0] - gt_kpts[..., 0]) ** 2 + (pred_kpts[..., 1] - gt_kpts[..., 1]) ** 2 + d = (pred_kpts[..., 0] - gt_kpts[..., 0]).pow(2) + (pred_kpts[..., 1] - gt_kpts[..., 1]).pow(2) kpt_loss_factor = kpt_mask.shape[1] / (torch.sum(kpt_mask != 0, dim=1) + 1e-9) # e = d / (2 * (area * self.sigmas) ** 2 + 1e-9) # from formula - e = d / (2 * self.sigmas) ** 2 / (area + 1e-9) / 2 # from cocoeval + e = d / (2 * self.sigmas).pow(2) / (area + 1e-9) / 2 # from cocoeval return (kpt_loss_factor.view(-1, 1) * ((1 - torch.exp(-e)) * kpt_mask)).mean() diff --git a/ultralytics/utils/metrics.py b/ultralytics/utils/metrics.py index 17c0782b..85f53944 100644 --- a/ultralytics/utils/metrics.py +++ b/ultralytics/utils/metrics.py @@ -116,10 +116,12 @@ def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-7 cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1) # convex (smallest enclosing box) width ch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1) # convex height if CIoU or DIoU: # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1 - c2 = cw**2 + ch**2 + eps # convex diagonal squared - rho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2) ** 2 + (b2_y1 + b2_y2 - b1_y1 - b1_y2) ** 2) / 4 # center dist ** 2 + c2 = cw.pow(2) + ch.pow(2) + eps # convex diagonal squared + rho2 = ( + (b2_x1 + b2_x2 - b1_x1 - b1_x2).pow(2) + (b2_y1 + b2_y2 - b1_y1 - b1_y2).pow(2) + ) / 4 # center dist**2 if CIoU: # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47 - v = (4 / math.pi**2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2) + v = (4 / math.pi**2) * ((w2 / h2).atan() - (w1 / h1).atan()).pow(2) with torch.no_grad(): alpha = v / (v - iou + (1 + eps)) return iou - (rho2 / c2 + v * alpha) # CIoU @@ -162,12 +164,12 @@ def kpt_iou(kpt1, kpt2, area, sigma, eps=1e-7): Returns: (torch.Tensor): A tensor of shape (N, M) representing keypoint similarities. """ - d = (kpt1[:, None, :, 0] - kpt2[..., 0]) ** 2 + (kpt1[:, None, :, 1] - kpt2[..., 1]) ** 2 # (N, M, 17) + d = (kpt1[:, None, :, 0] - kpt2[..., 0]).pow(2) + (kpt1[:, None, :, 1] - kpt2[..., 1]).pow(2) # (N, M, 17) sigma = torch.tensor(sigma, device=kpt1.device, dtype=kpt1.dtype) # (17, ) kpt_mask = kpt1[..., 2] != 0 # (N, 17) - e = d / (2 * sigma) ** 2 / (area[:, None, None] + eps) / 2 # from cocoeval + e = d / (2 * sigma).pow(2) / (area[:, None, None] + eps) / 2 # from cocoeval # e = d / ((area[None, :, None] + eps) * sigma) ** 2 / 2 # from formula - return (torch.exp(-e) * kpt_mask[:, None]).sum(-1) / (kpt_mask.sum(-1)[:, None] + eps) + return ((-e).exp() * kpt_mask[:, None]).sum(-1) / (kpt_mask.sum(-1)[:, None] + eps) def _get_covariance_matrix(boxes): @@ -181,13 +183,13 @@ def _get_covariance_matrix(boxes): (torch.Tensor): Covariance metrixs corresponding to original rotated bounding boxes. """ # Gaussian bounding boxes, ignore the center points (the first two columns) because they are not needed here. - gbbs = torch.cat((torch.pow(boxes[:, 2:4], 2) / 12, boxes[:, 4:]), dim=-1) + gbbs = torch.cat((boxes[:, 2:4].pow(2) / 12, boxes[:, 4:]), dim=-1) a, b, c = gbbs.split(1, dim=-1) - return ( - a * torch.cos(c) ** 2 + b * torch.sin(c) ** 2, - a * torch.sin(c) ** 2 + b * torch.cos(c) ** 2, - a * torch.cos(c) * torch.sin(c) - b * torch.sin(c) * torch.cos(c), - ) + cos = c.cos() + sin = c.sin() + cos2 = cos.pow(2) + sin2 = sin.pow(2) + return a * cos2 + b * sin2, a * sin2 + b * cos2, (a - b) * cos * sin def probiou(obb1, obb2, CIoU=False, eps=1e-7): @@ -208,26 +210,21 @@ def probiou(obb1, obb2, CIoU=False, eps=1e-7): a2, b2, c2 = _get_covariance_matrix(obb2) t1 = ( - ((a1 + a2) * (torch.pow(y1 - y2, 2)) + (b1 + b2) * (torch.pow(x1 - x2, 2))) - / ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)) + eps) + ((a1 + a2) * (y1 - y2).pow(2) + (b1 + b2) * (x1 - x2).pow(2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps) ) * 0.25 - t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)) + eps)) * 0.5 + t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps)) * 0.5 t3 = ( - torch.log( - ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2))) - / (4 * torch.sqrt((a1 * b1 - torch.pow(c1, 2)).clamp_(0) * (a2 * b2 - torch.pow(c2, 2)).clamp_(0)) + eps) - + eps - ) - * 0.5 - ) - bd = t1 + t2 + t3 - bd = torch.clamp(bd, eps, 100.0) - hd = torch.sqrt(1.0 - torch.exp(-bd) + eps) + ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2)) + / (4 * ((a1 * b1 - c1.pow(2)).clamp_(0) * (a2 * b2 - c2.pow(2)).clamp_(0)).sqrt() + eps) + + eps + ).log() * 0.5 + bd = (t1 + t2 + t3).clamp(eps, 100.0) + hd = (1.0 - (-bd).exp() + eps).sqrt() iou = 1 - hd if CIoU: # only include the wh aspect ratio part w1, h1 = obb1[..., 2:4].split(1, dim=-1) w2, h2 = obb2[..., 2:4].split(1, dim=-1) - v = (4 / math.pi**2) * (torch.atan(w2 / h2) - torch.atan(w1 / h1)).pow(2) + v = (4 / math.pi**2) * ((w2 / h2).atan() - (w1 / h1).atan()).pow(2) with torch.no_grad(): alpha = v / (v - iou + (1 + eps)) return iou - v * alpha # CIoU @@ -255,21 +252,16 @@ def batch_probiou(obb1, obb2, eps=1e-7): a2, b2, c2 = (x.squeeze(-1)[None] for x in _get_covariance_matrix(obb2)) t1 = ( - ((a1 + a2) * (torch.pow(y1 - y2, 2)) + (b1 + b2) * (torch.pow(x1 - x2, 2))) - / ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)) + eps) + ((a1 + a2) * (y1 - y2).pow(2) + (b1 + b2) * (x1 - x2).pow(2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps) ) * 0.25 - t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2)) + eps)) * 0.5 + t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps)) * 0.5 t3 = ( - torch.log( - ((a1 + a2) * (b1 + b2) - (torch.pow(c1 + c2, 2))) - / (4 * torch.sqrt((a1 * b1 - torch.pow(c1, 2)).clamp_(0) * (a2 * b2 - torch.pow(c2, 2)).clamp_(0)) + eps) - + eps - ) - * 0.5 - ) - bd = t1 + t2 + t3 - bd = torch.clamp(bd, eps, 100.0) - hd = torch.sqrt(1.0 - torch.exp(-bd) + eps) + ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2)) + / (4 * ((a1 * b1 - c1.pow(2)).clamp_(0) * (a2 * b2 - c2.pow(2)).clamp_(0)).sqrt() + eps) + + eps + ).log() * 0.5 + bd = (t1 + t2 + t3).clamp(eps, 100.0) + hd = (1.0 - (-bd).exp() + eps).sqrt() return 1 - hd