RPN之生成anchors

看不懂anchor生成方法,就看不懂参数。

faster_rcnn的anchors生成

在这里我就不看faster_rcnn的anchors生成源代码了,我们用numpy自己去实现,在128*128大小的图片中生成anchors.

开始上代码

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

# %matplotlib inline

feature_map的大小是16,在faster_rcnn中feature_map是一张图片经过卷积后生成的。如这里输入128*128的图片卷积后16*16大小,也就等于在128*128的图片里平均找16*16个像素点,每个像素点都生成3*3个锚框,scales和ratios决定框的大小。

size_Y = 16
size_X = 16
rpn_stride = 8
scales = [8, 16, 32]
ratios = [0.5, 1, 2]

 

scales, ratios = np.meshgrid(scales, ratios)
scales, ratios = scales.flatten(), ratios.flatten()
scalesY = scales * np.sqrt(ratios) 
scalesX = scales / np.sqrt(ratios)

shiftX = np.arange(0, size_X) * rpn_stride
shiftY = np.arange(0, size_Y) * rpn_stride
shiftX, shiftY = np.meshgrid(shiftX, shiftY)
centerX, anchorX = np.meshgrid(shiftX, scalesX)
centerY, anchorY = np.meshgrid(shiftY, scalesY)
anchor_center = np.stack([centerY, centerX], axis=2).reshape(-1, 2)
anchor_size = np.stack([anchorY, anchorX], axis=2).reshape(-1, 2)
boxes = np.concatenate([anchor_center -  0.5*anchor_size, anchor_center +  0.5*anchor_size], axis=1)

建一个空白图片在上面显示anchors

plt.figure(figsize=(15, 15))
img = np.ones((150,150, 3))
plt.imshow(img)
Axs = plt.gca()
for i in range(anchors.shape[0]):
    box = anchors[i]
    rec = patches.Rectangle((box[0], box[1]), box[2]-box[0], box[3]-box[1], edgecolor='r', facecolor='none')
    Axs.add_patch(rec)

这个输出是经过修改scales=(1,2,4)后的结果,每个点3*3个框,修改后显示得更明显,scales影响着锚框的平均大小。

可以看到锚框最大的正方形也就是4*4的。当我们把scales调到(8, 16, 32)最大的正方形锚框是32*32,最小的是8*8。

这样当出现占满50%图片的物体时根本没办法框住,在mask_rcnn中对anchors的生成就有改进。

mask_rcnn的anchors生成

我们先看一下生成anchors的一点代码,参数输入:

t = generate_pyramid_anchors(
    (32, 64, 128, 256, 512),
    [0.5, 1, 2],
    [ [32,32],[16,16],[8,8],[4,4],[2,2]],
    # [[256, 256], [128, 128], [64, 64], [32, 32], [16, 16]],
    [4, 8, 16, 32, 64],
                1)

这里面还有一部分跳转,和前面faster_rcnn的生成方法一样的。

我们先看一下feature_shapes这个参数,是根据输入图片大小决定的,每个feature_map是固定的,因为这是网络结构卷积后每一层输出的feature_map大小,输入图片128*128得到[ [32,32],[16,16],[8,8],[4,4],[2,2]],输入1024*1024得到[[256, 256], [128, 128], [64, 64], [32, 32], [16, 16]],也就是分出5个feature_map的大小,对逐个feature_map进行anchors的生成。

可以看到对参数进行了5次循环。

def generate_pyramid_anchors(scales, ratios, feature_shapes, feature_strides,
                             anchor_stride):
  
    anchors = []
    for i in range(len(scales)): # (32, 64, 128, 256, 512)
        anchors.append(generate_anchors(scales[i], ratios, feature_shapes[i],
                                        feature_strides[i], anchor_stride))
    return np.concatenate(anchors, axis=0)

我们来看一下每次代入的参数和生成的anchors数量。

这里还是以128*128来进行。

整个运行生成4092个anchors。

把参数分解出来。

第一次循环参数:

生成anchors是(3072, 4) , 这里每个点只生成3个框,这个生成的最大正方形anchors是32*32。

scales = [32]
ratios = [0.25, 0.5, 1]
size_Y = size_X = 32
rpn_stride = 4

 这里用了前面的代码,复制就可以运行(加上上面的参数)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches

%matplotlib inline


scales, ratios = np.meshgrid(scales, ratios)
scales, ratios = scales.flatten(), ratios.flatten()
scalesY = scales * np.sqrt(ratios) 
scalesX = scales / np.sqrt(ratios)

shiftX = np.arange(0, size_X) * rpn_stride
shiftY = np.arange(0, size_Y) * rpn_stride
shiftX, shiftY = np.meshgrid(shiftX, shiftY)
centerX, anchorX = np.meshgrid(shiftX, scalesX)
centerY, anchorY = np.meshgrid(shiftY, scalesY)
anchor_center = np.stack([centerY, centerX], axis=2).reshape(-1, 2)
anchor_size = np.stack([anchorY, anchorX], axis=2).reshape(-1, 2)
boxes = np.concatenate([anchor_center -  0.5*anchor_size, anchor_center +  0.5*anchor_size], axis=1)

plt.figure(figsize=(15, 15))
img = np.ones((150,150, 3))
plt.imshow(img)
Axs = plt.gca()
for i in range(anchors.shape[0]):
    box = anchors[i]
    rec = patches.Rectangle((box[0], box[1]), box[2]-box[0], box[3]-box[1], edgecolor='r', facecolor='none')
    print((box[0], box[1]), box[2]-box[0], box[3]-box[1])
    Axs.add_patch(rec)

改了scalse生成的,可以看到每个点只生成3个anchors

第二次循环参数:

生成anchors是(768, 4), 这个生成的最大正方形anchors是64*64

scales = [64]
ratios = [0.25, 0.5, 1]
size_Y = size_X = 16
rpn_stride = 8

第三次循环参数:

生成anchors是(192, 4), 这个生成的最大正方形anchors是128*128

scales = [128]
ratios = [0.25, 0.5, 1]
size_Y = size_X = 8
rpn_stride = 16

第四次循环参数:

生成anchors是(48, 4), 这个生成的最大正方形anchors是256*256

scales = [256]
ratios = [0.25, 0.5, 1]
size_Y = size_X = 4
rpn_stride = 32

第五次循环参数:

生成anchors是(12, 4), 这个生成的最大正方形anchors是512*512

scales = [512]
ratios = [0.25, 0.5, 1]
size_Y = size_X = 2
rpn_stride = 64

我们可以看到3072+768+192+48+12=4092,前面faster_rcnn中生成anchors个数是2304个,这里明显多了,但我们发现第四次循环和第五次循环,生成的anchors大小都到256、512,可是图片大小也就128,我暂时的见解是后面这些框没必要生成,太大了。

 

rpn生成anchors粗劣看了生成结果:

当ratios =  [0.5, 1, 2]固定

scales = [128, 256, 512]

生成最小的框128*0.66=84

生成最大的框512/0.66=775

 

那么就可以得出:

图片大小128*128时 scales = [16, 32, 64]  合适

图片大小1024*1024时 scales = [128, 256, 512]  合适

图片大小512*512时 scales = [64, 128, 256] 合适

 

 

 

 

 

 

 

 

 

 

 

 

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值