def _apply_multi_bbox_augmentation(image, bboxes, prob, aug_func,
                                   func_changes_bbox, *args):
    """Applies aug_func to the image for each bbox in bboxes.

    Args:
        image: 3D uint8 Tensor.
        bboxes: 2D Tensor that is a list of the bboxes in the image. Each bbox
            has 4 elements (min_y, min_x, max_y, max_x) of type float.
        prob: Float that is the probability of applying aug_func to a specific
            bounding box within the image.
        aug_func: Augmentation function that will be applied to the
            subsections of image indicated by the bbox values in bboxes.
        func_changes_bbox: Boolean. Does augmentation_func return bbox in addition
            to image.
        *args: Additional parameters that will be passed into augmentation_func
            when it is called.

    Returns:
        A modified version of image, where each bbox location in the image will
        have augmentation_func applied to it if it is chosen to be called with
        probability prob independently across all bboxes. Also the final
        bboxes are returned that will be unchanged if func_changes_bbox is set to
        false and if true, the new altered ones will be returned.
    """
    # Will keep track of the new altered bboxes after aug_func is repeatedly
    # applied. The -1 values are a dummy value and this first Tensor will be
    # removed upon appending the first real bbox.
    new_bboxes = np.array(_INVALID_BOX)

    # If the bboxes are empty, then just give it _INVALID_BOX. The result
    # will be thrown away.
    bboxes = np.array((_INVALID_BOX)) if bboxes.size == 0 else bboxes

    assert bboxes.shape[1] == 4, "bboxes.shape[1] must be 4!!!!"

    # pylint:disable=g-long-lambda
    # pylint:disable=line-too-long
    wrapped_aug_func = lambda _image, bbox, _new_bboxes: _apply_bbox_augmentation_wrapper(_image, bbox, _new_bboxes, prob, aug_func, func_changes_bbox, *args)
    # pylint:enable=g-long-lambda
    # pylint:enable=line-too-long

    # Setup the while_loop.
    num_bboxes = bboxes.shape[0]  # We loop until we go over all bboxes.
    idx = 0  # Counter for the while loop.

    # Conditional function when to end the loop once we go over all bboxes
    # images_and_bboxes contain (_image, _new_bboxes)
    def cond(_idx, _images_and_bboxes):
        return _idx < num_bboxes

    # Shuffle the bboxes so that the augmentation order is not deterministic if
    # we are not changing the bboxes with aug_func.
    # if not func_changes_bbox:
    #     print(bboxes)
    #     loop_bboxes = np.take(bboxes,np.random.permutation(bboxes.shape[0]),axis=0)
    #     print(loop_bboxes)
    # else:
    #     loop_bboxes = bboxes
    # we can not shuffle the bbox because it does not contain class information here
    loop_bboxes = deepcopy(bboxes)

    # Main function of while_loop where we repeatedly apply augmentation on the
    # bboxes in the image.
    # pylint:disable=g-long-lambda
    body = lambda _idx, _images_and_bboxes: [
            _idx + 1, wrapped_aug_func(_images_and_bboxes[0],
                                         loop_bboxes[_idx],
                                         _images_and_bboxes[1])]
    while (cond(idx, (image, new_bboxes))):
        idx, (image, new_bboxes) = body(idx, (image, new_bboxes))

    # Either return the altered bboxes or the original ones depending on if
    # we altered them in anyway.
    if func_changes_bbox:
        final_bboxes = new_bboxes
    else:
        final_bboxes = bboxes
    return image, final_bboxes
Applies aug_func to the image for each bbox in bboxes.

    Args:
        image: 3D uint8 Tensor.
        bboxes: 2D Tensor that is a list of the bboxes in the image. Each bbox
            has 4 elements (min_y, min_x, max_y, max_x) of type float.
        prob: Float that is the probability of applying aug_func to a specific
            bounding box within the image.
        aug_func: Augmentation function that will be applied to the
            subsections of image indicated by the bbox values in bboxes.
        func_changes_bbox: Boolean. Does augmentation_func return bbox in addition
            to image.
        *args: Additional parameters that will be passed into augmentation_func
            when it is called.

    Returns:
        A modified version of image, where each bbox location in the image will
        have augmentation_func applied to it if it is chosen to be called with
        probability prob independently across all bboxes. Also the final
        bboxes are returned that will be unchanged if func_changes_bbox is set to
        false and if true, the new altered ones will be returned.
    
ppdet/data/transform/autoaugment_utils.py