import torch


def bbox_transform_inv(boxes, delta):
    """ Inverse Bounding Box Transform
    from deltas and proposal boxes to predicted boxes
    Args:
        boxes: [N, 4] torch.Tensor (xywh)
        delta: [N, 4] torch.Tensor (xywh)
    Return:
        pred: [N, 4] torch.Tensor (xyxy)
    """
    pred_boxes = torch.zeros_like(boxes)
    pred_x = boxes[:, 0] + boxes[:, 2] * delta[:, 0]
    pred_y = boxes[:, 1] + boxes[:, 3] * delta[:, 1]
    pred_w = boxes[:, 2] * torch.exp(delta[:, 2])
    pred_h = boxes[:, 3] * torch.exp(delta[:, 3])

    pred_boxes[:, 0] = pred_x - 0.5 * pred_w
    pred_boxes[:, 1] = pred_y - 0.5 * pred_h
    pred_boxes[:, 2] = pred_x + 0.5 * pred_w
    pred_boxes[:, 3] = pred_y + 0.5 * pred_h

    return pred_boxes