Decodes encoded boxes with respect to anchors. Args: encoded_boxes: A [..., 4] float tensor with encoded boxes. anchors: A [..., 4] float tensor containing anchors. Anchors must be broadcastable to `boxes` and of the form [ymin, xmin, ymax, xmax].
(self, *, encoded_boxes: Tensor, anchors: Tensor)
| 103 | return encoded_boxes |
| 104 | |
| 105 | def decode(self, *, encoded_boxes: Tensor, anchors: Tensor) -> Tensor: |
| 106 | """Decodes encoded boxes with respect to anchors. |
| 107 | |
| 108 | Args: |
| 109 | encoded_boxes: A [..., 4] float tensor with encoded boxes. |
| 110 | anchors: A [..., 4] float tensor containing anchors. Anchors must be broadcastable to |
| 111 | `boxes` and of the form [ymin, xmin, ymax, xmax]. |
| 112 | |
| 113 | Returns: |
| 114 | A [..., 4] float tensor containing decoded boxes of the form [ymin, xmin, ymax, xmax]. |
| 115 | """ |
| 116 | # pylint: disable=invalid-name |
| 117 | cfg = self.config |
| 118 | encoded_boxes = encoded_boxes.astype(anchors.dtype) |
| 119 | dy = encoded_boxes[..., 0:1] |
| 120 | dx = encoded_boxes[..., 1:2] |
| 121 | dh = encoded_boxes[..., 2:3] |
| 122 | dw = encoded_boxes[..., 3:4] |
| 123 | |
| 124 | dy /= cfg.weights[0] |
| 125 | dx /= cfg.weights[1] |
| 126 | dh /= cfg.weights[2] |
| 127 | dw /= cfg.weights[3] |
| 128 | |
| 129 | if cfg.clip_boxes == BoxClipMethod.MaxHW: |
| 130 | dh = jnp.minimum(dh, BBOX_XFORM_CLIP) |
| 131 | dw = jnp.minimum(dw, BBOX_XFORM_CLIP) |
| 132 | elif cfg.clip_boxes == BoxClipMethod.MinMaxYXHW: |
| 133 | dy = jax.lax.clamp(-BBOX_XFORM_CLIP_EXP, dy, BBOX_XFORM_CLIP_EXP) |
| 134 | dx = jax.lax.clamp(-BBOX_XFORM_CLIP_EXP, dx, BBOX_XFORM_CLIP_EXP) |
| 135 | dh = jax.lax.clamp(-BBOX_XFORM_CLIP, dh, BBOX_XFORM_CLIP) |
| 136 | dw = jax.lax.clamp(-BBOX_XFORM_CLIP, dw, BBOX_XFORM_CLIP) |
| 137 | |
| 138 | anchor_ymin = anchors[..., 0:1] |
| 139 | anchor_xmin = anchors[..., 1:2] |
| 140 | anchor_ymax = anchors[..., 2:3] |
| 141 | anchor_xmax = anchors[..., 3:4] |
| 142 | anchor_h = anchor_ymax - anchor_ymin |
| 143 | anchor_w = anchor_xmax - anchor_xmin |
| 144 | anchor_yc = anchor_ymin + 0.5 * anchor_h |
| 145 | anchor_xc = anchor_xmin + 0.5 * anchor_w |
| 146 | |
| 147 | decoded_boxes_yc = dy * anchor_h + anchor_yc |
| 148 | decoded_boxes_xc = dx * anchor_w + anchor_xc |
| 149 | decoded_boxes_h = jnp.exp(dh) * anchor_h |
| 150 | decoded_boxes_w = jnp.exp(dw) * anchor_w |
| 151 | |
| 152 | decoded_boxes_ymin = decoded_boxes_yc - 0.5 * decoded_boxes_h |
| 153 | decoded_boxes_xmin = decoded_boxes_xc - 0.5 * decoded_boxes_w |
| 154 | decoded_boxes_ymax = decoded_boxes_ymin + decoded_boxes_h |
| 155 | decoded_boxes_xmax = decoded_boxes_xmin + decoded_boxes_w |
| 156 | |
| 157 | decoded_boxes = jnp.concatenate( |
| 158 | [decoded_boxes_ymin, decoded_boxes_xmin, decoded_boxes_ymax, decoded_boxes_xmax], |
| 159 | axis=-1, |
| 160 | ) |
| 161 | # pylint: enable=invalid-name |
| 162 | return decoded_boxes |