Tensorflow SSD实现与理解

1. 论文解读

1.1 模型特点

多个feature map作为目标检测的输入;通过卷积获得目标检测的得分和位置偏移;默认窗和纵横比,feature map上的每一个cell产生默认bounding box,feature map上产生的box与其周边的box相对位置是固定的,在每个cell上我们预测偏移和得分,针对每个box我们需要计算c个类别的得分,4个位置offset,因此需要(c+4)k个filter,因此feature map = mxnxp的输出为(c+4)kmn。

2.1 训练特点

  • 匹配策略
    Ground Truth与default box计算IOU,之后设置IOU > 0.5认为匹配。
  • 目标函数
    包含定位loc loss和类别conf loss:
    ssd loss
    其中N代表default box与GT匹配的个数,if N =0,loss = 0. loc loss 为smooth L1 loss,类似与FasterRCNN,如下:
    Smooth L1
    loc loss
    其中l为predict box,g为GT box,Xi,jP = {1,0},表示第i个default box与第j个GT box匹配,且类别为P;cx,cy表示default box的center offset,

conf loss
需要注意的是负样本的选取(论文中Hard negative mining部分),什么是hard negative mining,主要是为了降低假阳性即背景被识别成目标,粘一段百度的回答:对于目标检测中我们会事先标记处ground truth,然后再算法中会生成一系列proposal,这些proposal有跟标记的ground truth重合的也有没重合的,那么重合度(IOU)超过一定阈值(通常0.5)的则认定为是正样本,以下的则是负样本。然后扔进网络中训练。However,这也许会出现一个问题那就是正样本的数量远远小于负样本,这样训练出来的分类器的效果总是有限的,会出现许多false positive,把其中得分较高的这些false positive当做所谓的Hard negative,既然mining出了这些Hard negative,就把这些扔进网络再训练一次,从而加强分类器判别假阳性的能力。
注这部分连接原文:https://blog.csdn.net/qq_37541097/article/details/80917536

  • 尺度和default box纵横比的选择
    多个feature map预测搞定尺度问题,不同层每个cell的感受野不同;每一个目标检测层生成default box的方法为:每个cell 产生一个固定大小,固定比例的default box,这里的default box的大小对应的事原图上的大小比例。
  • 数据增广
    针对每个图片随机采用如下措施:
    使用原图
    取图像切片使目标的IOU介于:0.1:0.2:0.9
    随机切片;

2. 网络结构

vsd文件在github:SSD 网络结构

2.1 特征提取卷积层

VGG16为backbone网络,如下图:
VGG16

第17层卷积,即block6 为dilated convolution,rate = 6,,kernel= 3*3,kernel_num = 1024.

依次为rate=1,2,4的dilated convolution
采用网络结构中的:‘block4’, ‘block7’, ‘block8’, ‘block9’, ‘block10’, 'block11’作为ssd_multi_box的输入,如下图:
SSD add layer

2.2 anchor_box产生

  • anchor_sizes的产生
    paper中有两个超参数:Smin = 0.2;Smax = 0.9,表示所有的目标检测层中,最(前)大的层用来预测原图大小0.2尺度的目标,最小(后)层用来预测原图大小0.9尺度的目标,其他的层介于Smin~Smax之间的目标;因此通过下式计算得到每个层对应的Smin和Smax
    step计算
    这里论文与代码有一点不同,论文中的描述k=6,代码m=5. 这里还有一些向下取整的操作:
    取整计算过程
    得出:S = [0.2,0.37,0.54,0.71,0.88,1.05]
    因此得出6个区间片段:[0.1=0.5Smin*, 0.2],[0.2,0.37],[0.37,0.54],[0.54.0.71],[0.71,0.88],[0.88,1.05]
    按照比例映射到原图中anchor_sizes: = S300 ,得出anchor_size:
    [30, 60], [60,111],[111,162],[162,213],[213,264],[264,315];
    第一层这里的min_sizes我考虑应该是作者给的一个 超参数:0.5Smin
    min(high,width)*,对第一层单独设置了一下。

作者的原始代码:

import math
min_dim = 300
# conv4_3 ==> 38 x 38
# fc7 ==> 19 x 19
# conv6_2 ==> 10 x 10
# conv7_2 ==> 5 x 5
# conv8_2 ==> 3 x 3
# conv9_2 ==> 1 x 1
mbox_source_layers = ['conv4_3', 'fc7', 'conv6_2', 'conv7_2', 'conv8_2', 'conv9_2']
min_ratio = 20
max_ratio = 90
step = int(math.floor((max_ratio - min_ratio) / (len(mbox_source_layers) - 2)))
min_sizes = []
max_sizes = []
for ratio in xrange(min_ratio, max_ratio + 1, step):
  min_sizes.append(min_dim * ratio / 100.)
  max_sizes.append(min_dim * (ratio + step) / 100.)
  print(min_sizes)
  print(max_sizes)
min_sizes = [min_dim * 10 / 100.] + min_sizes
max_sizes = [min_dim * 20 / 100.] + max_sizes
steps = [8, 16, 32, 64, 100, 300],对于feature map一个格反应到原图的步进。
aspect_ratios = [[2], [2, 3], [2, 3], [2, 3], [2], [2]]
print(min_sizes)
print(max_sizes)
#https://blog.csdn.net/xunan003/article/details/79186162

在tensorflow的代码中:
anchor_size_bound设置的为smin=0.15,smax=0.9;steps = 0.75/4 = 0.1875;
得出:S = [0.15,0.3375,0.525,0.7125,0.9,1.275]
得出区间片段:(保留2位小数有效数字向下取floor计算)
[0.075 = 0.5Smin*, 0.15],[0.15, 0.03375],…
因此得出:
tf
[anchor_sizes=[(21., 45.),
(45., 99.),
(99., 153.),
(153., 207.),
(207., 261.),
(261., 315.)],

  • anchor_ratio
    anchor_ratios=[[2, .5],
    [2, .5, 3, 1./3],
    [2, .5, 3, 1./3],
    [2, .5, 3, 1./3],
    [2, .5],
    [2, .5]],
    在每一个特征提取层,生成一个边长为min_size和sqrt(min_sizemax_size)的正方形box;针对每个ratio,生成一个[sqrt(ratio)min_size, 1/sqrt(ratio)min_size]和[1/sqrt(ratio)min_size, sqrt(ratio)min_size]的长方形。
    SSD anchor
    anchor_num
    由以上两部分可以得出:
    我们都知道SSD默认框从6层卷积层输出的特征图中产生,分别为conv4_3、fc7、conv6_2、conv7_2、conv8_2、conv9_2。这6个特征层产生的特征图的大小分别为38
    38、19
    19、10
    10、5
    5、3
    3、1
    1。每个nn大小的特征图中有nn个中心点,每个中心点产生k个默认框,六层中每层的每个中心点产生的k分别为4、6、6、6、4、4。所以6层中的每层取一个特征图共产生38384+19196+10106+556+334+114=8732个默认框。

3. TensorFlow 实现

TensorFlow的实现代码来自:https://github.com/balancap/SSD-Tensorflow, 小弟作为代码的搬运工,也在我的git上复制了一份,并封装了两个分别调用图片和camera的接口,代码地址:https://github.com/ZhangChuann/go_elife/tree/master/AI_Demo/ssd。
本文代码运行基于TensorFlow 1.8.0, G{U为GTX 970M, 显存2G。

3.1 运行图片检测

source activate tensorflow
cd go_elife/AI_Demo/ssd
python img_demo.py -i demo/dog.jpg

运行效果:
img_ssd

3.2 运行camera检测

python video_demo.py

运行效果:
camera_ssd

4. NANO计算量评估,理论计算

5. NVIDIA NANO嵌入式实现

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值