SSD检测几个小细节

之前感觉SSD很简单,这两天从头到尾把论文和源码都看了一下,发现之前很多细节都没掌握。

这篇文章只说一些之前遗漏的点,读者阅读有一定基础

[TOC]

一. 抛砖引玉的Faster-RCNN

1.1 候选框的作用

之前看Fast-RCNN代码对Selective Search的操作一直有很大的疑惑?

图1-1
image

<u>为什么一张图会分割成这样大大小小的区域?分割后有啥意义呢?</u>

  • 第一个问题很简单,使用了贪心算法图论方面的知识,区域合并等算法。
  • 第二个问题到后来才明白,是深度学习的学习成本的问题。。。
图1-2

看上图的resnet核心模块,就是降低了学习成本,使得网络更容易学习

下面这张图预测区域通过两次平移到达目标区域

图1-3

下面这张图预测区域先通过放大再做两次平移到达目标区域

图1-4

下面这张图通过多个预测区域对不同的目标进行预测

图1-5

通过上面的三幅图可以发现,回归的方式需要付出不同的代价

当然代价越低越容易回归,可以看我之前的文章EAST和改进的EAST,就是通过回归的代价不同,最后效果提升挺大的。

最后一幅图,通过打不同的回归点(Anchor),比盲目的回归效果好很多

那么我们怎么知道目标在哪?怎么打候选框(Anchor)呢?

图1-6

假设上图是一个4 * 4feature map,我们既然不知道实际目标在哪,那就以每个像素为中心生成很多个候选框

上面生成的候选框数量也就是4 * 4 * 2=32个

会不会觉得那么多框进行回归效率很低?

首先那么多框都是固定的,比如上图的32个,回归的时候SSD也考虑到了这些,hard sample才需要回归,easy sample是不需要回归的

1.2 下采样问题

  • RoIPooling
图1-7
img

这个比较简单了,就是一个让输出对称的pooling操作。

  • ROIAlign
图1-8

这个也比较简单,就是利用双线性差值对中心的坐标进行计算出来

二. SSD细节理解

2.1 六个LOSS

这是笔者没看源代码,比较糊涂的想法,问了其他在跑ssd的人也没回答出来。。。

图2-1

笔者大概画了一个上图,这个问题很简单,想不通就很麻烦。。。

  • 在六个feature回归六个图信息
  • 六个信息映射到原图大小
  • 六个原图大小的信息合并成一个图(一个图6个通道,和一个图RGB通道一样)

2.2 Anchor生成细节

Anchor的特征主要包括几个方面:ratio(长宽比例)、scale(面积开根号,也就是正方形边长)、step/stride(步长,也就是原图和feature的比例)

  • ratio:固定的包括几个{1,2,3,1/2,1/3},还有一个1是不同的面积scale
  • scale:通过不同的feature map计算出来的(因为不同的特征图肯定得设置不同大小的scale
  • step/stride:两个表示都是一个含义,不同的卷积核(步长、padding)生成的步长不同

一定要理解上面几个参数的含义,具体公式的计算就很简单了,读者可以自己跑一下源代码

def default_prior_box():
    mean_layer = []
    for k,f in enumerate(Config.feature_map):
        mean = []
        for i,j in product(range(f),repeat=2):
            f_k = Config.image_size/Config.steps[k]#当前feature map 的大小(通过步数重新计算)
            #anchor中心点坐标(cx / cy已经归一化操作)
            cx = (j+0.5)/f_k
            cy = (i+0.5)/f_k

            s_k = Config.sk[k]/Config.image_size
            mean += [cx,cy,s_k,s_k]

            s_k_prime = sqrt(s_k * Config.sk[k+1]/Config.image_size)
            mean += [cx,cy,s_k_prime,s_k_prime]
            for ar in Config.aspect_ratios[k]:
                mean += [cx, cy, s_k * sqrt(ar), s_k/sqrt(ar)]
                mean += [cx, cy, s_k / sqrt(ar), s_k * sqrt(ar)]
        if Config.use_cuda:
            mean = torch.Tensor(mean).cuda().view(Config.feature_map[k], Config.feature_map[k], -1).contiguous()
        else:
            mean = torch.Tensor(mean).view( Config.feature_map[k],Config.feature_map[k],-1).contiguous()
        mean.clamp_(max=1, min=0)
        mean_layer.append(mean)

2.3 Encode&&Decode

疑点:刚开始看网上说的:

  1. prior box是:(中心X,中心Y,宽,高)
  2. 实际边界是(中心X,中心Y,宽,高)
  3. 学习的参数是(中心X偏移,中心Y偏移,宽比例,高比例)

按照这个推理:
l^{cx}= b^{cx} - d^{cx}

l^{cy}= b^{cy} - d^{cy}

l^{w}= b^{w} / d^{w}

l^{h}= b^{h} / d^{h}

其中b代表实际框,d代表default boxl代表回归参数

而实际的表达式如下所示:
l^{cx}= (b^{cx} - d^{cx})/d^w

l^{cx}= (b^{cx} - d^{cx})/d^h

l^{w}= log(b^{w}/d^{w})

l^{h}= log(b^{h}/d^{h})

笔者认为不管回归什么东西,只要是一种映射关系即可

定义完LOSS,神经网络会帮我们完成这种表达式的关系

所以这里作者也是为了方便,所以使用了除以d,又使用log函数

2.4 负样本挖掘

有专门的论文会解释这类事件,笔者这里只关注SSD的做法

SSD生成8732prior box框,而实际的一张图中目标只有几个

图2-2

有无数个预先设定的框,而实际和目标相交大于阈值的框很少

假设直接进行回归操作?

所有的框都进行回归=正样本的框+负样本的框

因为后者占比非常大,LOSS基本由负样本控制,最后的训练的结果如下:

图2-3

目标能检测到,但是对于边界的处理非常不好,因为细节基本由负样本控制

SSD如何进行操作?

回归分为两个部分=位置回归+类别回归

  • 位置回归按照上述方式进行

  • 种类按照1 :3的方式进行

  1. 首先计算出种类的loss

  2. 把正样本的loss置0(正样本全部保留)

  3. 负样本进行排序,按照3倍的正样本保留(保留大的loss属于hard sample)

  4. 最后正负样本叠加

    loss_c = utils.log_sum_exp(batch_conf) - batch_conf.gather(1, target_conf.view(-1, 1))

    loss_c = loss_c.view(batch_num, -1)
    # 将正样本设定为0
    loss_c[pos] = 0

    # 将剩下的负样本排序,选出目标数量的负样本
    _, loss_idx = loss_c.sort(1, descending=True)
    _, idx_rank = loss_idx.sort(1)

    num_pos = pos.long().sum(1, keepdim=True)
    num_neg = torch.clamp(3*num_pos, max=pos.size(1)-1)

    # 提取出正负样本
    neg = idx_rank < num_neg.expand_as(idx_rank)
    pos_idx = pos.unsqueeze(2).expand_as(conf_data)
    neg_idx = neg.unsqueeze(2).expand_as(conf_data)

    conf_p = conf_data[(pos_idx+neg_idx).gt(0)].view(-1, Config.class_num)
    targets_weighted = target_conf[(pos+neg).gt(0)]
    loss_c = F.cross_entropy(conf_p, targets_weighted, size_average=False)
图2-4

图画的不好,因为正好叠合就看不到效果了

参考文献

https://arxiv.org/pdf/1512.02325.pdf

https://www.cnblogs.com/cmai/p/10080005.html

https://blog.csdn.net/u010167269/article/details/52563573

https://www.cnblogs.com/xuanyuyt/p/7222867.html#_label2

https://www.cnblogs.com/pacino12134/p/10353959.html

https://blog.csdn.net/u010712012/article/details/86555814

https://deepsense.ai/satellite-images-semantic-segmentation-with-deep-learning/

https://www.jianshu.com/p/8b7d7036d715

侵权请告知删除

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容