def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ A wrapper function to generate anchors given different scales Also return the number of anchors in variable 'length' """ """生成anchor的预处理方法,generate_anchors方法就是直接产生各种大小的anchor box,generate_anchors_pre方法 是把每一个anchor box对应到原图上 feat_stride: 经过VGG或者ZF后特征图相对于原图的在长或者宽上的缩放倍数,也就是说height和width对应于特征图长宽 anchor_scales:anchor尺寸 anchor_ratios: anchor长宽比 """ anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] #A=9 # print("A:",A) shift_x = np.arange(0, width) * feat_stride shift_y = np.arange(0, height) * feat_stride shift_x, shift_y = np.meshgrid(shift_x, shift_y) shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() K = shifts.shape[0] # print("K:",K) # width changes faster, so here it is H, W, C anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose( (1, 0, 2)) anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) length = np.int32(anchors.shape[0]) return anchors, length
def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ A wrapper function to generate anchors given different scales Also return the number of anchors in variable 'length' """ # 根据规模和比例,产生基础的9个anchor,大小为8,16,32,所以乘以缩放比例,就变成了128,256,512 anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] # A = 9 # 生成X和Y偏移量 shift_x = np.arange(0, width) * feat_stride shift_y = np.arange(0, height) * feat_stride shift_x, shift_y = np.meshgrid(shift_x, shift_y) shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() K = shifts.shape[0] # width * height # width changes faster, so here it is H, W, C anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose( (1, 0, 2)) anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) length = np.int32(anchors.shape[0]) return anchors, length
def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ A wrapper function to generate anchors given different scales Also return the number of anchors in variable 'length' """ anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] # A = 9 shift_x = np.arange(0, width) * feat_stride shift_y = np.arange(0, height) * feat_stride shift_x, shift_y = np.meshgrid(shift_x, shift_y) shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() K = shifts.shape[0] # 1872 # width changes faster, so here it is H, W, C anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose( (1, 0, 2)) anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) length = np.int32(anchors.shape[0]) # print("anchors", anchors.shape, height*feat_stride) anchors_dis = np.zeros((K * A, 3)) anchors_dis[:, 0] = ((anchors[:, 2] + anchors[:, 0]) / 2 - width * feat_stride / 2) * 0.01234 # x对应距离 anchors_dis[:, 1] = (anchors[:, 3] + anchors[:, 1]) * 0.0008963 # y对应距离 0.13349 anchors_dis[:, 2] = (375 - anchors[:, 3]) * 0.13349 # z 以米为单位 anchors_dis = anchors_dis.astype(np.float32, copy=False) # print(anchors_dis) return anchors, anchors_dis, length # anchors (16848, 4) anchors_dis (16848, 3)
def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): #anchor_ratios = 2 w:h = 1:2 """ A wrapper function to generate anchors given different scales Also return the number of anchors in variable 'length' """ anchors = generate_anchors( ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) #9个基本框,以后通过feet_stride调节,现在只生成一个基本框 A = anchors.shape[0] shift_x = np.arange(0, width) * feat_stride #中心点的位置,,看看能不能做点文章 shift_y = np.arange( 0, height) * feat_stride #尝试传递上一个中心点坐标,推算下一个中心点坐标,从而减少anchor生成的数目 shift_x, shift_y = np.meshgrid(shift_x, shift_y) shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() K = shifts.shape[0] # width changes faster, so here it is H, W, C anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose( (1, 0, 2)) anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) length = np.int32(anchors.shape[0]) return anchors, length
def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ Return anchors and its length. A wrapper function to generate anchors given different scales Also return the number of anchors in variable 'length' 将anchor从特征图上映射到原图上 Parameters ---------- height, width: int32 anchor的高度、宽度; feat_stride: list 放大倍数,VGG16时,feat_stride=[16, ]; anchor_scales, anchor_ratios: float anchor大小和宽高比的设定值 Returns ------- anchors : ndarray 映射到原图上的anchor,shape=((number of anchors) x width x height, 4) length : int32 anchors.shape[0] = (number of anchors) x width x height """ anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] # A = anchor的数量 = len(anchor_ritio) * len(anchor_scale) = 9 # 将特征图的宽、高以16倍延申至原图:经VGG16后得到的特征图大小缩小了16倍,故延申以还原 shift_x = np.arange(0, width) * feat_stride # shift_x = [0, 1*16, ……, width*16], shape=[width, ] shift_y = np.arange(0, height) * feat_stride # shift_y = [0, 1*16, ……, height*16], shape=[height, ] # 生成原图网格点 shift_x, shift_y = np.meshgrid(shift_x, shift_y) # 将shift_x, shift_y生成形状相同的矩阵, 形为(height, width) shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() # 将shift_x, shift_y拉平后堆叠,然后转置 # shift_x(), shift_y.ravel(): (width*height, ); shifts: (4, width*height)^T = (width*height, 4) K = shifts.shape[0] # K = width x height # width changes faster, so here it is H, W, C anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose( (1, 0, 2)) # shape = [K, A, 4], K = H x W, A = 9 anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) length = np.int32(anchors.shape[0]) # length = (number of anchors) x width x height return anchors, length
def _anchor_component(self, size_level1, size_level2, size_level3): anchors_level1, anchors_level2, anchors_level3 = generate_anchors(size_level1, size_level2, size_level3, self._feat_stride) if cfg.NUM_ANCHORS_LEVEL1 != 0: self._anchors_level1 = torch.from_numpy(anchors_level1) if cfg.NUM_ANCHORS_LEVEL2 != 0: self._anchors_level2 = torch.from_numpy(anchors_level2) if cfg.NUM_ANCHORS_LEVEL3 != 0: self._anchors_level3 = torch.from_numpy(anchors_level3)
def generate_anchors_pre_tf(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ A wrapper function to generate anchors given different scales and image sizes in tensorflow. Note, since `anchor_scales` and `anchor_ratios` is in practice always the same, the generate 'base anchors' are static and does we only need to implement the shifts part in tensorflow which is depending on the image size. Parameters: ----------- height: tf.Tensor The hight of the current image as a tensor. width: tf.Tensor The width of the current image as a tensor. feat_stride: tf.Tensor or scalar The stride used for the shifts. anchor_scales: list The scales to use for the anchors. This is a static parameter and can currently not be runtime dependent. anchor_ratios: list The ratios to use for the anchors. This is a static parameter and can currently not be runtime dependent. Returns: -------- anchors: tf.Tensor 2D tensor containing all anchors, it has the shape (n, 4). length: tf.Tensor A tensor containing the length 'n' of the anchors. """ anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) # Calculate all shifts shift_x = tf.range(0, width * feat_stride, feat_stride) shift_y = tf.range(0, height * feat_stride, feat_stride) shift_x, shift_y = tf.meshgrid(shift_x, shift_y) shift_x = tf.reshape(shift_x, [-1, 1]) shift_y = tf.reshape(shift_y, [-1, 1]) shifts = tf.concat((shift_x, shift_y, shift_x, shift_y), 1) # Combine all base anchors with all shifts anchors = anchors[tf.newaxis] + tf.transpose(shifts[tf.newaxis], (1, 0, 2)) anchors = tf.cast(tf.reshape(anchors, (-1, 4)), tf.float32) length = tf.shape(anchors)[0] return anchors, length
def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] shift_x = np.arange(0, width) * feat_stride shift_y = np.arange(0, height) * feat_stride shift_x, shift_y = np.meshgrid(shift_x, shift_y) shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() K = shifts.shape[0] # width changes faster, so here it is H, W, C anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose((1, 0, 2)) anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) length = np.int32(anchors.shape[0]) return anchors, length
def generate_anchors_pre_tf(height, width, feat_stride=16, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): shift_x = tf.range(width) * feat_stride # width shift_y = tf.range(height) * feat_stride # height shift_x, shift_y = tf.meshgrid(shift_x, shift_y) sx = tf.reshape(shift_x, shape=(-1,)) sy = tf.reshape(shift_y, shape=(-1,)) shifts = tf.transpose(tf.stack([sx, sy, sx, sy])) K = tf.multiply(width, height) shifts = tf.transpose(tf.reshape(shifts, shape=[1, K, 4]), perm=(1, 0, 2)) anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] anchor_constant = tf.constant(anchors.reshape((1, A, 4)), dtype=tf.int32) length = K * A anchors_tf = tf.reshape(tf.add(anchor_constant, shifts), shape=(length, 4)) return tf.cast(anchors_tf, dtype=tf.float32), length
def generate_anchors_pre(height, width, feat_stride, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ A wrapper function to generate anchors given different scales Also return the number of anchors in variable 'length' """ anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] #9 shift_x = np.arange(0, width) * feat_stride #feature map上的点对应回原输入图片的坐标 shift_y = np.arange(0, height) * feat_stride shift_x, shift_y = np.meshgrid(shift_x, shift_y) # np.reval()和np.flatten()两者的功能是一致的,将多维数组降为一维 # 但两者的区别是no.flatten()返回的是一份拷贝,对拷贝做的修改不影响原始数组,而np.reval()返回的是视图,修改时会影响原数组 shifts = np.vstack((shift_x.ravel(), shift_y.ravel(), shift_x.ravel(), shift_y.ravel())).transpose() K = shifts.shape[0] # width changes faster, so here it is H, W, C #anchors坐标加上加上各个中心点的坐标,即得到各个中心点产生的所有anchors的坐标 anchors = anchors.reshape((1, A, 4)) + shifts.reshape((1, K, 4)).transpose((1, 0, 2)) anchors = anchors.reshape((K * A, 4)).astype(np.float32, copy=False) #一个点产生的9个anchor连在一起 length = np.int32(anchors.shape[0]) return anchors, length
def generate_anchors_pre_tf(height, width, feat_stride=16, anchor_scales=(8, 16, 32), anchor_ratios=(0.5, 1, 2)): """ 根据feature map的尺寸来计算该feature map所有像素点(像素点的选取顺序是从第一行开始自左到右的方向,处理完一行后自上到下进入下一行)对应 到原始图片上的所有anchors。每个对应的anchors的个数由anchor_scales和anchor_ratios决定,比如anchor_scales有8,16,32三种扩大倍数, anchor_ratios有0.5,1,2三种纵横比,则对应feature map每个点,映射回原始图片的感受野后的中心点,会生成3 × 3中组合,比如0.5纵横比会组合 8,16,32三种扩大倍数,所以对于每个点有9个anchors。 Args: height: feature map的高 width: feature map的宽 feat_stride: 从原始图片到该feature map总共缩小的倍数,由每层的stride决定 anchor_scales: anchors的扩大倍数 anchor_ratios: anchors的纵横比 Returns: feature map所有像素点对应到原始图中的anchors """ """ 首先获取feature map所有点对应到原始图片的点的坐标,x原始 = x(feature map) * feat_stride, y原始 = x(feature map) * feat_stride. 比如3 × 3的feature map对应到原始图片中所有的坐标点shifts如下: Out[133]: array([[[ 0, 0, 0, 0]], [[16, 0, 16, 0]], [[32, 0, 32, 0]], [[ 0, 16, 0, 16]], [[16, 16, 16, 16]], [[32, 16, 32, 16]], [[ 0, 32, 0, 32]], [[16, 32, 16, 32]], [[32, 32, 32, 32]]], dtype=int32) 能看到第一列和第三列一致,第二列和第四列一致。一二列就组成了所有原始图中的点,增加三四列是为了方便计算anchor,因为一个anchor用左上角坐标 和右下角坐标来表示。 """ shift_x = tf.range(width) * feat_stride # width shift_y = tf.range(height) * feat_stride # height shift_x, shift_y = tf.meshgrid(shift_x, shift_y) sx = tf.reshape(shift_x, shape=(-1, )) sy = tf.reshape(shift_y, shape=(-1, )) shifts = tf.transpose(tf.stack([sx, sy, sx, sy])) K = tf.multiply(width, height) shifts = tf.transpose(tf.reshape(shifts, shape=[1, K, 4]), perm=(1, 0, 2)) """ 依据一个16 × 16的base anchor生成9个anchors(由scales和ratios组成),anchor_constant如下: array([[ -84., -40., 99., 55.], 0.5纵横比,8倍扩大 [-176., -88., 191., 103.], 0.5纵横比,16倍扩大 [-360., -184., 375., 199.], 0.5纵横比,32倍扩大 [ -56., -56., 71., 71.], 1.0纵横比,8倍扩大 [-120., -120., 135., 135.], 1.0纵横比,16倍扩大 [-248., -248., 263., 263.], 1.0纵横比,32倍扩大 [ -36., -80., 51., 95.], 2.0纵横比,8倍扩大 [ -80., -168., 95., 183.], 2.0纵横比,16倍扩大 [-168., -344., 183., 359.]]) 2.0纵横比,32倍扩大 """ anchors = generate_anchors(ratios=np.array(anchor_ratios), scales=np.array(anchor_scales)) A = anchors.shape[0] anchor_constant = tf.constant(anchors.reshape((1, A, 4)), dtype=tf.int32) """ 让shifts与anchor_constant相加组成feature map对应到原始图片中的anchors。 在这里发现上边生成的shifts实际并非anchors的中心点。而是中心点偏左上一些的点。 总共anchors个数为: 像素点数K × 每个点的anchors数A """ length = K * A anchors_tf = tf.reshape(tf.add(anchor_constant, shifts), shape=(length, 4)) return tf.cast(anchors_tf, dtype=tf.float32), length