"""Some special pupropse layers for SSD.""" import keras.backend as K from keras.engine.topology import InputSpec from keras.engine.topology import Layer import numpy as np import tensorflow as tf class Normalize(Layer): """Normalization layer as described in ParseNet paper. # Arguments scale: Default feature scale. # Input shape 4D tensor with shape: `(samples, channels, rows, cols)` if dim_ordering=‘th‘ or 4D tensor with shape: `(samples, rows, cols, channels)` if dim_ordering=‘tf‘. # Output shape Same as input """ def __init__(self, scale, **kwargs): if K.image_dim_ordering() == ‘tf‘: self.axis = 3 else: self.axis = 1 self.scale = scale super(Normalize, self).__init__(**kwargs) def build(self, input_shape): self.input_spec = [InputSpec(shape=input_shape)] shape = (input_shape[self.axis],) init_gamma = self.scale * np.ones(shape) self.gamma = K.variable(init_gamma, name=‘{}_gamma‘.format(self.name)) self.trainable_weights = [self.gamma] def call(self, x, mask=None): output = K.l2_normalize(x, self.axis) output *= self.gamma return output #上面这个层就不多说了,在keras中自定义Layer中以及详细介绍了,下面还是说说那个产生default box的层吧 class PriorBox(Layer): """Generate the prior boxes of designated sizes and aspect ratios. # Arguments img_size: Size of the input image as tuple (w, h). min_size: Minimum box size in pixels. max_size: Maximum box size in pixels. aspect_ratios: List of aspect ratios of boxes. flip: Whether to consider reverse aspect ratios. variances: List of variances for x, y, w, h. clip: Whether to clip the prior‘s coordinates such that they are within [0, 1]. # Input shape 4D tensor with shape: `(samples, channels, rows, cols)` if dim_ordering=‘th‘ or 4D tensor with shape: `(samples, rows, cols, channels)` if dim_ordering=‘tf‘. # Output shape 3D tensor with shape: (samples, num_boxes, 8) """ def __init__(self, img_size, min_size, max_size=None, aspect_ratios=None, flip=True, variances=[0.1], clip=True, **kwargs): if K.image_dim_ordering() == ‘tf‘: self.waxis = 2 self.haxis = 1 else: self.waxis = 3 self.haxis = 2 self.img_size = img_size # print "self.img_size" # print self.img_size # print "self.img_siez" if min_size <= 0: raise Exception(‘min_size must be positive.‘) self.min_size = min_size self.max_size = max_size self.aspect_ratios = [1.0] if max_size: if max_size < min_size: raise Exception(‘max_size must be greater than min_size.‘) self.aspect_ratios.append(1.0) if aspect_ratios: for ar in aspect_ratios: if ar in self.aspect_ratios: continue self.aspect_ratios.append(ar) if flip: self.aspect_ratios.append(1.0 / ar) self.variances = np.array(variances) self.clip = True super(PriorBox, self).__init__(**kwargs) def get_output_shape_for(self, input_shape): # print "input_shape start" # print input_shape # print "input_shape end" num_priors_ = len(self.aspect_ratios) # print "-----------------------------------" # print num_priors layer_width = input_shape[self.waxis] # print layer_width layer_height = input_shape[self.haxis] # print layer_height # print "----------------------------------" num_boxes = num_priors_ * layer_width * layer_height # print (input_shape[0], num_boxes, 8) return (input_shape[0], num_boxes, 8) def call(self, x, mask=None): # print dir(x) if hasattr(x, ‘_keras_shape‘): input_shape = x._keras_shape # print "1" elif hasattr(K, ‘int_shape‘): input_shape = K.int_shape(x) # print "2" # print input_shape layer_width = input_shape[self.waxis] layer_height = input_shape[self.haxis] img_width = self.img_size[0] img_height = self.img_size[1] # print img_width,img_height,layer_width,layer_height # define prior boxes shapes box_widths = [] box_heights = [] # print self.min_size # print self.aspect_ratios for ar in self.aspect_ratios: if ar == 1 and len(box_widths) == 0: box_widths.append(self.min_size) box_heights.append(self.min_size) elif ar == 1 and len(box_widths) > 0: box_widths.append(np.sqrt(self.min_size * self.max_size)) box_heights.append(np.sqrt(self.min_size * self.max_size)) elif ar != 1: box_widths.append(self.min_size * np.sqrt(ar)) box_heights.append(self.min_size / np.sqrt(ar)) box_widths = 0.5 * np.array(box_widths) box_heights = 0.5 * np.array(box_heights) # print len(box_widths) # print len(box_heights) # define centers of prior boxes step_x = img_width / layer_width step_y = img_height / layer_height # print step_x,step_y # print img_width,img_height linx = np.linspace(0.5 * step_x, img_width - 0.5 * step_x, layer_width) liny = np.linspace(0.5 * step_y, img_height - 0.5 * step_y, layer_height) # print linx.shape,liny.shape centers_x, centers_y = np.meshgrid(linx, liny) centers_x = centers_x.reshape(-1, 1) centers_y = centers_y.reshape(-1, 1) # print centers_x.shape,centers_y.shape # define xmin, ymin, xmax, ymax of prior boxes num_priors_ = len(self.aspect_ratios) # print num_priors prior_boxes = np.concatenate((centers_x, centers_y), axis=1) # print prior_boxes.shape prior_boxes = np.tile(prior_boxes, (1, 2 * num_priors_)) # print prior_boxes.shape prior_boxes[:, ::4] -= box_widths prior_boxes[:, 1::4] -= box_heights prior_boxes[:, 2::4] += box_widths prior_boxes[:, 3::4] += box_heights prior_boxes[:, ::2] /= img_width prior_boxes[:, 1::2] /= img_height prior_boxes = prior_boxes.reshape(-1, 4) if self.clip: prior_boxes = np.minimum(np.maximum(prior_boxes, 0.0), 1.0) # define variances num_boxes = len(prior_boxes) if len(self.variances) == 1: variances = np.ones((num_boxes, 4)) * self.variances[0] elif len(self.variances) == 4: variances = np.tile(self.variances, (num_boxes, 1)) else: raise Exception(‘Must provide one or four variances.‘) prior_boxes = np.concatenate((prior_boxes, variances), axis=1) prior_boxes_tensor = K.expand_dims(K.variable(prior_boxes), 0) if K.backend() == ‘tensorflow‘: pattern = [tf.shape(x)[0], 1, 1] prior_boxes_tensor = tf.tile(prior_boxes_tensor, pattern) elif K.backend() == ‘theano‘: #TODO pass # print prior_boxes_tensor.shape return prior_boxes_tensor # print dir(PriorBox((300,300),100))
时间: 2024-11-10 00:57:37