priorbox.py 3.2 KB
Newer Older
R
Renwb1991 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
""" A custom layer for 'priorbox' which is used in ssd to generate prior box info
    Since the order of prior box is different between caffe and paddle,
    we use 'slice' and 'concate' ops to align them.
"""

from .register import register


def priorbox_shape(input_shapes, min_size, max_size=None, aspect_ratio=None):
    """ calculate the output shape of this layer using input shapes

    Args:
        @input_shapes (list of tuples): a list of input shapes

    Returns:
        @output_shape (list of num): a list of numbers represent the output shape
    """
    assert len(input_shapes) == 2, "invalid inputs for Priorbox[%s]" % (name)
    fc_shape = input_shapes[0]
    N = 1
    if not max_size == None:
        N += 1
    if not aspect_ratio == None:
        N += 2 * len(aspect_ratio)

    N_bbx = fc_shape[2] * fc_shape[3] * N
    output_shape = [1, 2, 4 * N_bbx]
    return output_shape


def priorbox_layer(inputs,
                   name,
                   min_size,
                   max_size=None,
S
SunAhong1993 已提交
35
                   aspect_ratio=1.0,
R
Renwb1991 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
                   variance=[0.1, 0.1, 0.2, 0.2],
                   flip=False,
                   clip=False,
                   step=0.0,
                   offset=0.5):
    """ build a layer of type 'Priorbox' using fluid

    Args:
        @inputs (list of variables): input fluid variables for this layer
        @name (str): name for this layer

    Returns:
        output (variable): output variable for this layer
    """
    import paddle.fluid as fluid

    assert len(inputs) == 2, "invalid inputs for Priorbox[%s]" % (name)
    input = inputs[0]
    image = inputs[1]
    steps = tuple(step) if type(step) is list or type(step) is tuple else (step,
                                                                           step)
    box, variance_ = fluid.layers.prior_box(
        input,
        image,
        min_size,
        max_size,
        aspect_ratio,
        variance,
        flip,
        clip,
        steps,
        offset,
        min_max_aspect_ratios_order=True)
    """
    #adjust layout when the output is not consistent with caffe's

    feat_shape = list(input.shape)
    H = feat_shape[2]
    W = feat_shape[3]
    box_tmp = fluid.layers.reshape(box, [H, W, -1, 4])
    nb_prior_bbx = int(box_tmp.shape[2])
    tensor_list = fluid.layers.split(box_tmp, nb_prior_bbx, 2)

    #TODO:
    #   current implementation for this layer is not efficient
    #   and we should fix this bug in future when Paddle support the same prior-box layout with Caffe
    index_list = [0]
    index_list = index_list * nb_prior_bbx
    index_offset = 0
    if max_size is not None:
        index_list[1] = -1
        index_offset = 1
    for ii in xrange(2 * len(aspect_ratio)):
        index_list[ii + 1 + index_offset] = ii + 1

    tensor_list_gathered = [tensor_list[ii] for ii in index_list]
    caffe_prior_bbx = fluid.layers.concat(tensor_list_gathered, axis=2)
    box = fluid.layers.reshape(caffe_prior_bbx, [1, 1, -1])
    """

    box = fluid.layers.reshape(box, [1, 1, -1])
    variance_ = fluid.layers.reshape(variance_, [1, 1, -1])
    output = fluid.layers.concat([box, variance_], axis=1)

    return output


register(kind='PriorBox', shape=priorbox_shape, layer=priorbox_layer)