Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/tensorflow_addons/losses/giou_loss.py: 25%
51 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Implements GIoU loss."""
17from typing import Optional
19import tensorflow as tf
20from typeguard import typechecked
22from tensorflow_addons.utils.keras_utils import LossFunctionWrapper
23from tensorflow_addons.utils.types import TensorLike
26@tf.keras.utils.register_keras_serializable(package="Addons")
27class GIoULoss(LossFunctionWrapper):
28 """Implements the GIoU loss function.
30 GIoU loss was first introduced in the
31 [Generalized Intersection over Union:
32 A Metric and A Loss for Bounding Box Regression]
33 (https://giou.stanford.edu/GIoU.pdf).
34 GIoU is an enhancement for models which use IoU in object detection.
36 Usage:
38 >>> gl = tfa.losses.GIoULoss()
39 >>> boxes1 = tf.constant([[4.0, 3.0, 7.0, 5.0], [5.0, 6.0, 10.0, 7.0]])
40 >>> boxes2 = tf.constant([[3.0, 4.0, 6.0, 8.0], [14.0, 14.0, 15.0, 15.0]])
41 >>> loss = gl(boxes1, boxes2)
42 >>> loss
43 <tf.Tensor: shape=(), dtype=float32, numpy=1.5041667>
45 Usage with `tf.keras` API:
47 >>> model = tf.keras.Model()
48 >>> model.compile('sgd', loss=tfa.losses.GIoULoss())
50 Args:
51 mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss.
52 """
54 @typechecked
55 def __init__(
56 self,
57 mode: str = "giou",
58 reduction: str = tf.keras.losses.Reduction.AUTO,
59 name: Optional[str] = "giou_loss",
60 ):
61 super().__init__(giou_loss, name=name, reduction=reduction, mode=mode)
64@tf.keras.utils.register_keras_serializable(package="Addons")
65def giou_loss(y_true: TensorLike, y_pred: TensorLike, mode: str = "giou") -> tf.Tensor:
66 """Implements the GIoU loss function.
68 GIoU loss was first introduced in the
69 [Generalized Intersection over Union:
70 A Metric and A Loss for Bounding Box Regression]
71 (https://giou.stanford.edu/GIoU.pdf).
72 GIoU is an enhancement for models which use IoU in object detection.
74 Args:
75 y_true: true targets tensor. The coordinates of the each bounding
76 box in boxes are encoded as [y_min, x_min, y_max, x_max].
77 y_pred: predictions tensor. The coordinates of the each bounding
78 box in boxes are encoded as [y_min, x_min, y_max, x_max].
79 mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss.
81 Returns:
82 GIoU loss float `Tensor`.
83 """
84 if mode not in ["giou", "iou"]:
85 raise ValueError("Value of mode should be 'iou' or 'giou'")
86 y_pred = tf.convert_to_tensor(y_pred)
87 if not y_pred.dtype.is_floating:
88 y_pred = tf.cast(y_pred, tf.float32)
89 y_true = tf.cast(y_true, y_pred.dtype)
90 giou = tf.squeeze(_calculate_giou(y_pred, y_true, mode))
92 return 1 - giou
95def _calculate_giou(b1: TensorLike, b2: TensorLike, mode: str = "giou") -> tf.Tensor:
96 """
97 Args:
98 b1: bounding box. The coordinates of the each bounding box in boxes are
99 encoded as [y_min, x_min, y_max, x_max].
100 b2: the other bounding box. The coordinates of the each bounding box
101 in boxes are encoded as [y_min, x_min, y_max, x_max].
102 mode: one of ['giou', 'iou'], decided to calculate GIoU or IoU loss.
104 Returns:
105 GIoU loss float `Tensor`.
106 """
107 zero = tf.convert_to_tensor(0.0, b1.dtype)
108 b1_ymin, b1_xmin, b1_ymax, b1_xmax = tf.unstack(b1, 4, axis=-1)
109 b2_ymin, b2_xmin, b2_ymax, b2_xmax = tf.unstack(b2, 4, axis=-1)
110 b1_width = tf.maximum(zero, b1_xmax - b1_xmin)
111 b1_height = tf.maximum(zero, b1_ymax - b1_ymin)
112 b2_width = tf.maximum(zero, b2_xmax - b2_xmin)
113 b2_height = tf.maximum(zero, b2_ymax - b2_ymin)
114 b1_area = b1_width * b1_height
115 b2_area = b2_width * b2_height
117 intersect_ymin = tf.maximum(b1_ymin, b2_ymin)
118 intersect_xmin = tf.maximum(b1_xmin, b2_xmin)
119 intersect_ymax = tf.minimum(b1_ymax, b2_ymax)
120 intersect_xmax = tf.minimum(b1_xmax, b2_xmax)
121 intersect_width = tf.maximum(zero, intersect_xmax - intersect_xmin)
122 intersect_height = tf.maximum(zero, intersect_ymax - intersect_ymin)
123 intersect_area = intersect_width * intersect_height
125 union_area = b1_area + b2_area - intersect_area
126 iou = tf.math.divide_no_nan(intersect_area, union_area)
127 if mode == "iou":
128 return iou
130 enclose_ymin = tf.minimum(b1_ymin, b2_ymin)
131 enclose_xmin = tf.minimum(b1_xmin, b2_xmin)
132 enclose_ymax = tf.maximum(b1_ymax, b2_ymax)
133 enclose_xmax = tf.maximum(b1_xmax, b2_xmax)
134 enclose_width = tf.maximum(zero, enclose_xmax - enclose_xmin)
135 enclose_height = tf.maximum(zero, enclose_ymax - enclose_ymin)
136 enclose_area = enclose_width * enclose_height
137 giou = iou - tf.math.divide_no_nan((enclose_area - union_area), enclose_area)
138 return giou