Faster RCNN(目标检测算法)(1)

本文详细介绍了Faster RCNN目标检测算法,包括其整体思路、ResNet50主干网络、区域建议网络(RPN)的工作原理、建议框的解码过程以及ROI Pooling的操作。通过使用ResNet50提取特征,Faster RCNN先生成候选框,再进行精细化调整,以达到高精度目标检测。文章提供了代码示例,帮助理解先验框的生成和解码过程。
摘要由CSDN通过智能技术生成

Faster RCNN目标检测算法(Two-stage目标检测算法)

本文中代码来自:https://github.com/bubbliiiing/faster-rcnn-keras
Two - stage 和One - stage目标检测算法的综述。

Two-stage目标检测算法:先生成一系列的候选框,在通过卷积神经网络进行样本分类。(在精度上占优势)
One-stage目标检测算法:不生成候选框直接将目标边框的定位问题转化成回归问题。(在算法速度上占优势)
在这里插入图片描述

1、Faster RCNN网络的整体思路

首先将原图片输入到特征提取网络中,特征提取网络可以看做将图像划分成不同大小的网格,每个网格上有若干个先验框;利用RPN(Region proposal network)区域建议网络进行粗略的筛选,获得建议框在共享特征层上进行截取,将截取到的建议框输入到ROI Pooling网络进行细致的调整,将建议框resize 成相同的大小,再利用分类回归网络判断框中是否存在目标,并对建议框进行调整。

Faster RCNN网络对输入图片的大小没有限制,在输入到特征提取网络之前,对图片进行resize 操作,将图片中的较短边resize成600(保持原图片的长宽比,图片不会失真),输入到backbone特征提取网络(ResNet50),看作将图片划分成不同个大小的网格,输出特征feature(共享特征层,后面得到的建议框也是在共享特征层上进行截取。)此时,得到的共享特征层有两个去向:1、进行一次3×3的卷积,再分别进行两次通道数不同的1×1卷积(通道数分别为9和36),这里每一个网格中默认的先验框个数为9,那么9和36分别代表什么含义呢?

9和36分别代表的含义:每一个网格中默认先验框的个数为9,而两个1×1卷积输出的结果分别表示先验框中是否存在物体、先验框的调整参数(中心点坐标和宽高)。9代表每个网格中每一个先验框中是否存在物体;36代表每个网格中每一个先验框的调整参数。对先验框调整后的结果就是经过粗略筛选后的建议框。

利用建议框在共享特征层上进行截取,截取下来的建议框输入到ROI Pooling中。这也就是共享特征层的第二个去向:用建议框对共享特征层进行截取,用于进一步更精细的调整。
在Roi Pooling中,首先将截取到的建议框resize成相同大小,然后1、(bbox_pred)获得建议框的调整参数;2、(class_pred)经过softmax获得建议框中物体的种类。得到最终的目标检测结果。

2、主干特征提取网络(ResNet50)

在ResNet中有两种结构:Conv_BlockIdentity_Block
Conv_Block的残差边上有卷积操作,该结构的输入和输出的通道数改变了,所以不能够连续串联。
Identity_Block的残差边上没有卷积操作,该结构的输入、输出的维度相同,可以连续串联,作用是增加网络的深度。

Conv_Block代码:
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
    filters1, filters2, filters3 = filters
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'
    x = Conv2D(filters1, (1, 1), strides=strides,
               name=conv_name_base + '2a')(input_tensor)
    x = BatchNormalization(name=bn_name_base + '2a')(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters2, kernel_size, padding='same',
               name=conv_name_base + '2b')(x)
    x = BatchNormalization(name=bn_name_base + '2b')(x)
    x = Activation('relu')(x)
    
    x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)
    x = BatchNormalization(name=bn_name_base + '2c')(x)
    
    shortcut = Conv2D(filters3, (1, 1), strides=strides,
                      name=conv_name_base + '1')(input_tensor)
    shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut)
    x = layers.add([x, shortcut])
    x = Activation('relu')(x)
    return x

Conv_Block默认的步长为(2,2)
首先进行卷积核大小为1×1的卷积操作,使用默认的步长,宽高减半
BatchNormalization归一化操作
relu非线性激活函数


卷积核大小为3×3的卷积操作,宽高不变
BatchNormalization归一化操作
relu非线性激活函数


卷积核大小为1×1的卷积操作,宽高不变
BatchNormalization归一化操作


残差边是将输入的特征经过一次卷积核大小为1×1的卷积操作,步长为2,输出宽高减半
和一次BatchNormalization归一化操作


然后将残差边和主干网络的结果叠加,经过一个非线性激活函数,最后得到conv_Block的输出结果。

Identity_block代码
def identity_block(input_tensor, kernel_size, filters, stage, block):
    filters1, filters2, filters3 = filters
    conv_name_base = 'res' + str(stage) + block + '_branch'
    bn_name_base = 'bn' + str(stage) + block + '_branch'

    x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor)
    x = BatchNormalization(name=bn_name_base + '2a')(x)
    x = Activation('relu')(x)

    x = Conv2D(filters2, kernel_size,padding='same', name=conv_name_base + '2b')(x)
    x = BatchNormalization(name=bn_name_base + '2b')(x)
    x = Activation('relu')(x)

    x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x)
    x = BatchNormalization(name=bn_name_base + '2c')(x)

    x = layers.add([x, input_tensor])
    x = Activation('relu')(x)
    return x

首先进行一次卷积核大小为1×1的卷积,宽高不变
BatchNormalization归一化
relu非线性激活函数


卷积核大小为3×3的卷积,宽高不变
BatchNormalization归一化
relu非线性激活函数


卷积核大小为1×1的卷积,宽高不变
BatchNormalization归一化


残差边将输入直接引入到主干的输出特征层,进行叠加,再经过一个relu非线性激活函数得到Identity_Block的结果。

ResNet50网络结构

调用Identity_Block和Conv_Block构建残差网络结构

def ResNet50(inputs):

    img_input = inputs

    x = ZeroPadding2D((3, 3))(img_input)
    x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x)
    x = BatchNormalization(name='bn_conv1')(x)
    x = Activation('relu')(x)

    x = MaxPooling2D((3, 3), strides=(2, 2), padding="same")(x)

    x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
    x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
    x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')


    x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
    x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')

    x = conv_block(
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值