'Generates a collection of bounding boxes to be used as anchors.
The number of anchors generated for a single grid with shape MxM where we
place k boxes over each grid center is k*M^2 and thus the total number of
anchors is the sum over all grids. In our box_specs_list example
(see the constructor docstring), we would place two boxes over each grid
point on an 8x8 grid and three boxes over each grid point on a 4x4 grid and
thus end up with 2*8^2 + 3*4^2 = 176 anchors in total. The layout of the
output anchors follows the order of how the grid sizes and box_specs are
specified (with box_spec index varying the fastest, followed by width
index, then height index, then grid index).
Args:
feature_map_shape_list: list of pairs of convnet layer resolutions in the
format [(height_0, width_0), (height_1, width_1), ...]. For example,
setting feature_map_shape_list=[(8, 8), (7, 7)] asks for anchors that
correspond to an 8x8 layer followed by a 7x7 layer.
im_height: the height of the image to generate the grid for. If both
im_height and im_width are 1, the generated anchors default to
normalized coordinates, otherwise absolute coordinates are used for the
grid.
im_width: the width of the image to generate the grid for. If both
im_height and im_width are 1, the generated anchors default to
normalized coordinates, otherwise absolute coordinates are used for the
grid.
anchor_strides: list of pairs of strides (in y and x directions
respectively). For example, setting
anchor_strides=[(.25, .25), (.5, .5)] means that we want the anchors
corresponding to the first layer to be strided by .25 and those in the
second layer to be strided by .5 in both y and x directions. By
default, if anchor_strides=None, then they are set to be the reciprocal
of the corresponding grid sizes. The pairs can also be specified as
dynamic tf.int or tf.float numbers, e.g. for variable shape input
images.
anchor_offsets: list of pairs of offsets (in y and x directions
respectively). The offset specifies where we want the center of the
(0, 0)-th anchor to lie for each layer. For example, setting
anchor_offsets=[(.125, .125), (.25, .25)]) means that we want the
(0, 0)-th anchor of the first layer to lie at (.125, .125) in image
space and likewise that we want the (0, 0)-th anchor of the second
layer to lie at (.25, .25) in image space. By default, if
anchor_offsets=None, then they are set to be half of the corresponding
anchor stride. The pairs can also be specified as dynamic tf.int or
tf.float numbers, e.g. for variable shape input images.
Returns:
boxes: a BoxList holding a collection of N anchor boxes
Raises:
ValueError: if feature_map_shape_list, box_specs_list do not have the same
length.
ValueError: if feature_map_shape_list does not consist of pairs of
integers'

def _generate(self, feature_map_shape_list, im_height=1, im_width=1, anchor_strides=None, anchor_offsets=None):

    if (not (isinstance(feature_map_shape_list, list) and (len(feature_map_shape_list) == len(self._box_specs)))):
        raise ValueError('feature_map_shape_list    must    be    a    list    with    the    same    length    as    self._box_specs')
    if (not all([(isinstance(list_item, tuple) and (len(list_item) == 2)) for list_item in feature_map_shape_list])):
        raise ValueError('feature_map_shape_list    must    be    a    list    of    pairs.')
    if (not anchor_strides):
        anchor_strides = [((tf.to_float(im_height) / tf.to_float(pair[0])), (tf.to_float(im_width) / tf.to_float(pair[1]))) for pair in feature_map_shape_list]
    if (not anchor_offsets):
        anchor_offsets = [((0.5 * stride[0]), (0.5 * stride[1])) for stride in anchor_strides]
    for (arg, arg_name) in zip([anchor_strides, anchor_offsets], ['anchor_strides', 'anchor_offsets']):
        if (not (isinstance(arg, list) and (len(arg) == len(self._box_specs)))):
            raise ValueError(('%s    must    be    a    list    with    the    same    length    as    self._box_specs' % arg_name))
        if (not all([(isinstance(list_item, tuple) and (len(list_item) == 2)) for list_item in arg])):
            raise ValueError(('%s    must    be    a    list    of    pairs.' % arg_name))
    anchor_grid_list = []
    min_im_shape = tf.to_float(tf.minimum(im_height, im_width))
    base_anchor_size = (min_im_shape * self._base_anchor_size)
    for (grid_size, scales, aspect_ratios, stride, offset) in zip(feature_map_shape_list, self._scales, self._aspect_ratios, anchor_strides, anchor_offsets):
        anchor_grid_list.append(grid_anchor_generator.tile_anchors(grid_height=grid_size[0], grid_width=grid_size[1], scales=scales, aspect_ratios=aspect_ratios, base_anchor_size=base_anchor_size, anchor_stride=stride, anchor_offset=offset))
    concatenated_anchors = box_list_ops.concatenate(anchor_grid_list)
    num_anchors = concatenated_anchors.num_boxes_static()
    if (num_anchors is None):
        num_anchors = concatenated_anchors.num_boxes()
    if (self._clip_window is not None):
        clip_window = tf.multiply(tf.to_float([im_height, im_width, im_height, im_width]), self._clip_window)
        concatenated_anchors = box_list_ops.clip_to_window(concatenated_anchors, clip_window, filter_nonoverlapping=False)
        concatenated_anchors.set(tf.reshape(concatenated_anchors.get(), [num_anchors, 4]))
    stddevs_tensor = (0.01 * tf.ones([num_anchors, 4], dtype=tf.float32, name='stddevs'))
    concatenated_anchors.add_field('stddev', stddevs_tensor)
    return concatenated_anchors
