单阶段多层检测器:SSD (理论及Pytorch代码详解)

  • 数据增强:SSD在数据部分做了充分的数据增强工作,包括光学变换与几何变换等,极大限度地扩充了数据集的丰富性,从而有效提升了模型的检测精度。

  • 网络骨架:SSD在原始VGGNet的基础上,进一步延伸了4个卷积模块,最深处的特征图大小为1×1,这些特征图具有不同的尺度与感受野,可以负责检测不同尺度的物体。

  • PriorBox与多层特征图:与Faster RCNN类似,SSD利用了固定大小与宽高的PriorBox作为区域生成,但与Faster RCNN不同的是,SSD不是只在一个特征图上设定预选框,而是在6个不同尺度上都设立预选框,并且在浅层特征图上设立较小的PriorBox来负责检测小物体,在深层特征图上设立较大的PriorBox来负责检测大物体。原因的是浅层特征层的感受野小,分辨率高,深层特征层感受野大,分辨率低

  • 正、负样本的选取与损失计算:利用3×3的卷积在6个特征图上进行特征的提取,并分为分类与回归两个分支,代表所有预选框的预测值,随后进行预选框与真实框的匹配,利用IoU筛选出正样本与负样本,最终计算出分类损失与回归损失。

由整个过程可以看出,SSD只进行了一次框的预测与损失计算,属于一阶网络。由于利用了多个特征图,SSD实现了较好的检测精度。接下来分点介绍几个部分。

数据增强:


SSD做了丰富的数据增强策略,这部分为模型的mAP带来了8.8%的提升,尤其是对于小物体和遮挡物体等难点,数据增强起到了非常重要的作用。

img

SSD的数据增强 整体流程如图所示,总体上包括光学变换与几何变换两个过程。光学变换包括亮度和对比度等随机调整,可以调整图像像素值的大小,并不会改变图像尺寸; 几何变换包括扩展、裁剪和镜像等操作,主要负责进行尺度上的变化,最后再进行去均值操作。大部分操作都是随机的过程,尽可能保证数据的丰富性。

数据增强的总体流程代码如下:

class SSDAugmentation(object):

def init(self, size=300, mean=(104, 117, 123)):

self.mean = mean

self.size = size

self.augment = Compose([

# 首先将图像像素值从整型变成浮点型

ConvertFromInts(),

# 将标签中的边框从比例坐标变换为真实坐标

ToAbsoluteCoords(),

# 进行亮度、对比度、色相与饱和度的随机调整,然后随机调换通道

PhotometricDistort(),

Expand(self.mean),     # 随机扩展图像大小,图像仅靠右下方

RandomSampleCrop(),         # 随机裁剪图像

RandomMirror(),       # 随机左右镜像

ToPercentCoords(),     # 从真实坐标变回比例坐标

Resize(self.size),         # 缩放到固定的300×300大小

SubtractMeans(self.mean)  # 最后进行去均值

])

将像素值从整型变到浮点型,边框从比例坐标变换到真实坐标,这两种变换较为简单,这里不展开叙述。接下来重点介绍光学变换与几何变换这两个重要的变换方法。

  1. 光学变换

首先是进行亮度调整,具体方法是以0.5的概率为图像中的每一个点加一个实数,该实数随机选取于[-32,32)区间中。具体可见如下RandomBrightness类的实现。

class RandomBrightness(object):

def init(self, delta=32):

self.delta = delta

def call(self, image, boxes=None, labels=None):

if random.randint(2):

# 随机选取一个位于[-32, 32)区间的数,相加到图像上

delta = random.uniform(-self.delta, self.delta)

image += delta

return image, boxes, labels

接下来是对比度、色相与饱和度的随机调整。色相的随机调整与亮度很类似,都是随机地加一个数,而对比度与饱和度则是随机乘一个数。另外,对色相与饱和度的调整是在HSV色域空间进行的。由于此三者与亮度很相似,代码不再单独给出。 ​ 关于以上三者的调整顺序,SSD也给了一个随机处理,即有一半的概率对比度在另外两者之前,另一半概率则是对比度在另外两者之后。 光学变换的最后一项是添加随机的光照噪声,具体做法是随机交换RGB三个通道的值,具体实现如RandomLightingNoise()类所示。

class RandomLightingNoise(object):

def init(self):

self.perms = ((0, 1, 2), (0, 2, 1),

(1, 0, 2), (1, 2, 0),

(2, 0, 1), (2, 1, 0))

def call(self, image, boxes=None, labels=None):

if random.randint(2):

# 随机选取一个通道的交换顺序,交换图像三个通道的值

swap = self.perms[random.randint(len(self.perms))]

shuffle = SwapChannels(swap)        # shuffle channels

image = shuffle(image)

return image, boxes, labels

  1. 几何变换

在几何变换中,首先进行的是尺度的随机扩展。扩展的具体过程是随机选择一个在[1,4)区间的数作为扩展比例,将原图像放在扩展后图像的右下角,其他区域填入每个通道的均值&#x

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值