class_docstr: Crop an image randomly with bounding box constraints.
  
  Please check `mx.gluon.contrib.data.transforms.bbox.utils.bbox_random_crop_with_constraints`
  for implementation details.
  
  Parameters
  ----------
  p : float
      The probability to preceed with random cropping logic.
  min_scale : float
      The minimum ratio between a cropped region and the original image.
      The default value is :obj:`0.3`.
  max_scale : float
      The maximum ratio between a cropped region and the original image.
      The default value is :obj:`1`.
  max_aspect_ratio : float
      The maximum aspect ratio of cropped region.
      The default value is :obj:`2`.
  constraints : iterable of tuples
      An iterable of constraints.
      Each constraint should be :obj:`(min_iou, max_iou)` format.
      If means no constraint if set :obj:`min_iou` or :obj:`max_iou` to :obj:`None`.
      If this argument defaults to :obj:`None`, :obj:`((0.1, None), (0.3, None),
      (0.5, None), (0.7, None), (0.9, None), (None, 1))` will be used.
  max_trial : int
      Maximum number of trials for each constraint before exit no matter what.
  
  Inputs:
      - **data**: input tensor with (Hi x Wi x C) shape.
      - **bbox**: input tensor with shape (N, 4+) where N is the number of bounding boxes.
          The second axis represents attributes of the bounding box.
          Specifically, these are :math:`(x_{min}, y_{min}, x_{max}, y_{max})`,
          we allow additional attributes other than coordinates, which stay intact
          during bounding box transformations.
  
  Outputs:
      - **out**: Cropped image with shape (H x W x C)
      - **bbox**: Cropped bounding boxes with shape :obj:`(M, 4+)` where M <= N.
          Tuple of length 4 as :math:`(x_{min}, y_{min}, x_{max}, y_{max})`.
code: def forward(self, img, bbox):
      if random.random() > self.p:
          return img, bbox
      im_size = (img.shape[-2], img.shape[-3])
      new_bbox, crop = bbox_random_crop_with_constraints(
          bbox.asnumpy(), im_size, **self._args
      )
      if crop == (0, 0, im_size[0], im_size[1]):
          return img, bbox
      if is_np_array():
          new_img = npx.image.crop(
              img, x=crop[0], y=crop[1], width=crop[2], height=crop[3]
          )
          new_bbox = np.array(new_bbox)
      else:
          new_img = nd.image.crop(
              img, x=crop[0], y=crop[1], width=crop[2], height=crop[3]
          )
          new_bbox = nd.array(new_bbox)
      return new_img, new_bbox
  
imports: import random
  from .......base import numeric_types
  from ......block import Block
  from .......util import is_np_array
  from .......None import ndarray, numpy_extension, numpy
  from .utils import _check_bbox_shape, bbox_crop, bbox_translate
  from .utils import bbox_resize, bbox_random_crop_with_constraints
label_desc: Use image node_id 2 for calling the ImageBboxRandomCropWithConstraints obj's underlying member method code with example usage: obj.forward(img, bbox) and returns: new_img,  new_bbox, img,  bbox, img,  bbox