Helper function to create multiple random crop augmenters.

    Parameters
    ----------
    min_object_covered : float or list of float, default=0.1
        The cropped area of the image must contain at least this fraction of
        any bounding box supplied. The value of this parameter should be non-negative.
        In the case of 0, the cropped area does not need to overlap any of the
        bounding boxes supplied.
    min_eject_coverage : float or list of float, default=0.3
        The minimum coverage of cropped sample w.r.t its original size. With this
        constraint, objects that have marginal area after crop will be discarded.
    aspect_ratio_range : tuple of floats or list of tuple of floats, default=(0.75, 1.33)
        The cropped area of the image must have an aspect ratio = width / height
        within this range.
    area_range : tuple of floats or list of tuple of floats, default=(0.05, 1.0)
        The cropped area of the image must contain a fraction of the supplied
        image within in this range.
    max_attempts : int or list of int, default=50
        Number of attempts at generating a cropped/padded region of the image of the
        specified constraints. After max_attempts failures, return the original image.

    Examples
    --------
    >>> # An example of creating multiple random crop augmenters
    >>> min_object_covered = [0.1, 0.3, 0.5, 0.7, 0.9]  # use 5 augmenters
    >>> aspect_ratio_range = (0.75, 1.33)  # use same range for all augmenters
    >>> area_range = [(0.1, 1.0), (0.2, 1.0), (0.2, 1.0), (0.3, 0.9), (0.5, 1.0)]
    >>> min_eject_coverage = 0.3
    >>> max_attempts = 50
    >>> aug = mx.image.det.CreateMultiRandCropAugmenter(min_object_covered=min_object_covered,
            aspect_ratio_range=aspect_ratio_range, area_range=area_range,
            min_eject_coverage=min_eject_coverage, max_attempts=max_attempts,
            skip_prob=0)
    >>> aug.dumps()  # show some details

def CreateMultiRandCropAugmenter(min_object_covered=0.1, aspect_ratio_range=(0.75, 1.33),
                                 area_range=(0.05, 1.0), min_eject_coverage=0.3,
                                 max_attempts=50, skip_prob=0):
    """Helper function to create multiple random crop augmenters.

    Parameters
    ----------
    min_object_covered : float or list of float, default=0.1
        The cropped area of the image must contain at least this fraction of
        any bounding box supplied. The value of this parameter should be non-negative.
        In the case of 0, the cropped area does not need to overlap any of the
        bounding boxes supplied.
    min_eject_coverage : float or list of float, default=0.3
        The minimum coverage of cropped sample w.r.t its original size. With this
        constraint, objects that have marginal area after crop will be discarded.
    aspect_ratio_range : tuple of floats or list of tuple of floats, default=(0.75, 1.33)
        The cropped area of the image must have an aspect ratio = width / height
        within this range.
    area_range : tuple of floats or list of tuple of floats, default=(0.05, 1.0)
        The cropped area of the image must contain a fraction of the supplied
        image within in this range.
    max_attempts : int or list of int, default=50
        Number of attempts at generating a cropped/padded region of the image of the
        specified constraints. After max_attempts failures, return the original image.

    Examples
    --------
    >>> # An example of creating multiple random crop augmenters
    >>> min_object_covered = [0.1, 0.3, 0.5, 0.7, 0.9]  # use 5 augmenters
    >>> aspect_ratio_range = (0.75, 1.33)  # use same range for all augmenters
    >>> area_range = [(0.1, 1.0), (0.2, 1.0), (0.2, 1.0), (0.3, 0.9), (0.5, 1.0)]
    >>> min_eject_coverage = 0.3
    >>> max_attempts = 50
    >>> aug = mx.image.det.CreateMultiRandCropAugmenter(min_object_covered=min_object_covered,
            aspect_ratio_range=aspect_ratio_range, area_range=area_range,
            min_eject_coverage=min_eject_coverage, max_attempts=max_attempts,
            skip_prob=0)
    >>> aug.dumps()  # show some details

    """
    def align_parameters(params):
        """Align parameters as pairs"""
        out_params = []
        num = 1
        for p in params:
            if not isinstance(p, list):
                p = [p]
            out_params.append(p)
            num = max(num, len(p))
        # align for each param
        for k, p in enumerate(out_params):
            if len(p) != num:
                assert len(p) == 1
                out_params[k] = p * num
        return out_params

    aligned_params = align_parameters([min_object_covered, aspect_ratio_range, area_range,
                                       min_eject_coverage, max_attempts])
    augs = []
    for moc, arr, ar, mec, ma in zip(*aligned_params):
        augs.append(DetRandomCropAug(min_object_covered=moc, aspect_ratio_range=arr,
                                     area_range=ar, min_eject_coverage=mec, max_attempts=ma))
    return DetRandomSelectAug(augs, skip_prob=skip_prob)