Datawhale炼丹之Object Detetion(2)锚框与模型结构

本文介绍了Datawhale OD项目中关于目标检测的锚框概念,包括不同尺度的先验框设置、先验框与特征图的对应、类别信息确定及生成算法。同时,详细解析了模型结构,如VGG16特征提取模块、分类头和回归头的设计,以及如何量化和预测边界框的偏移量。
摘要由CSDN通过智能技术生成


前言

一时兴起和好朋友一起组队参加了Datawhale的OD小项目,索性也算是第一次做CV的项目了,顺便练练pytorch和神经网络的内容。这是第二次任务的博客。

一、锚框

锚框就是先验框。之前提到目标检测的任务分为两步,识别+标定。我们需要遍历图片上每一个可能的目标框,在对这些框进行分类和微调。

1. 设置不同尺度的先验框

为了覆盖更多的情况,在图中的同一位置,会设置几个不同尺度的先验框。这个很好理解,增大覆盖面。那么什么样的框叫做良好的先验框呢,很简单,回到上一节讲到的一个OD任务中非常重要的指标,就是交并比IoU了,交并比越高,说明我们的先验框的匹配度越高。

2. 先验框与特征图的对应

通过先验框和特征图这种一一对应的映射关系,可以通过特征图一次性的输出所有先验框的类别信息以及坐标信息。

3. 先验框类别信息的确定

设定一个IoU阈值,与图片中目标的IoU小于阈值的先验框划分为背景,大于阈值的划分为目标先验框

4. 先验框生成算法

  • 编译特征图上每一个cell,并进行归一化,这叫做基准框
  • 根据在每个cell上设置的长宽比为1:1的基准框,几个三种设hi真的尺度和三种长宽比可以得到9个先验框
  • 返回这些先验框

来看一看代码,VGG16网络最后生成的特征图的尺寸为 7 × 7 7 \times 7 7×7,每一个cell上有9种不同的候选框。

def create_prior_boxes():
    fmap_dims = 7 
    obj_scales = [0.2, 0.4, 0.6]
    aspect_ratios = [1., 2., 0.5]
    
    prior_boxes = []
    
    for i in range(fmap_dims):
        for j in range(fmap_dims):
            cx = (j + 0.5) / fmap_dims #将坐标移到中心
            cy = (i + 0.5) / fmap_dims

            for obj_scale in obj_scales:
                for ratio in aspect_ratios:
                    prior_boxes.append([cx, cy, obj_scale * sqrt(ratio), obj_scale / sqrt(ratio)])
	prior_boxes = torch.FloatTensor(prior_boxes).to(device)  # (441, 4)
    prior_boxes.clamp_(0, 1)  # (441, 4)
    
    return prior_boxes

来看看代码生成的效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oWDKdWwT-1608375237952)(3-16.jpg)]

需要注意,刚刚我们使用了prior.clamp_(0,1)是为了防止越界问题,比如上图中的蓝框,所以我们需要将其截断。

二、模型结构

这部分我们就来看看这次的OD任务种的网络和模型。

1. 特征提取模块

我们采用VGG16作为特征提取的模块,模型参数如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qKBK1saJ-1608375237954)(3-17.png)]

我们可以用Pytorch定义出这个网络,pytorch中,所有的神经网络都继承自nn.Module类,定义类的时候,可以在__init__()函数中定义网络结构,在forward()函数中定义前向传播的过程

import torch
import torch.nn as nn
import torch.nn.functional as F # 激活函数

class VGGBase(nn.Module):
    
    def __init__(self):
        #首先找到VGGBase的父类(nn.module),然后把类VGGBase的对象self转换为类nn.module的对象,然后“被转换”的类nn.module对象调用自己的init函数
        super(VGGBase,self).__init__()

        ######  下面逐层定义这个网络  ######
        '''
            输入为224 * 224 * 3
        '''
        ## Conv2d(self, in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True))
        self.conv1_1 = nn.Conv2d(3,64,3,1)
        self.conv1_2 = nn.Conv2d(64, 64, kernel_size=3, padding=1) # 224 * 224 * 64
        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2) # 112 * 112 * 64 

        self.conv2_1 = nn.Conv2d(64, 128, kernel_size=3, padding=1) 
        self.conv2_2 = nn.Conv2d(128, 128, kernel_size=3, padding=1) # 112 * 112 * 128
        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2)    # 56 * 56 * 128

        self.conv3_1 = nn.Conv2d(128, 256, kernel_size=3, padding=1)
        s
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值