【论文阅读笔记】faster rcnn 代码阅读细节

[亡魂溺海] 提交于 2020-02-01 01:41:26


参考:https://zhuanlan.zhihu.com/p/31426458

https://www.cnblogs.com/dudumiaomiao/p/6560841.html

bounding box regression原理

如图所示绿色框为飞机的Ground Truth(GT),红色为提取的positive anchors,即便红色的框被分类器识别为飞机,但是由于红色的框定位不准,这张图相当于没有正确的检测出飞机。所以我们希望采用一种方法对红色的框进行微调,使得positive anchors和GT更加接近。
在这里插入图片描述

理论

对于窗口一般使用四维向量(x,y,w,h)(x,y,w,h)表示,分别表示窗口的中心点坐标和宽高。
对下图,红色的框A代表原始的positive Anchors,绿色的框G代表目标的GT,我们的目标是寻找一种关系,使得输入原始的anchor A经过映射得到一个跟真实窗口G更接近的回归窗口G’,即:

  • 给定anchor A=(Ax,Ay,Aw,Ah)A=(A_x,A_y,A_w,A_h)和GT G=[Gx,Gy,Gw,Gh]G=[G_x,G_y,G_w,G_h]
  • 寻找一种变换F,使得F(Ax,Ay,Aw,Ah)=(Gx,Gy,Gw,Gh)F(A_x,A_y,A_w,A_h)=(G^‘_x,G^‘_y,G^‘_w,G^‘_h),其中(Gx,Gy,Gw,Gh)(Gx,Gy,Gw,Gh)(G^‘_x,G^‘_y,G^‘_w,G^‘_h)≈(G_x,G_y,G_w,G_h)
    在这里插入图片描述
    那么这个变换F应该怎么寻找呢,比较简单的思路就是先做平移再做缩放
  • 先做平移
    在这里插入图片描述
    在这里插入图片描述
  • 再做缩放
    在这里插入图片描述
    在这里插入图片描述

观察上面4个公式发现,需要学习的是 dx(A),dy(A),dw(A),dh(A)d_x(A),d_y(A),d_w(A),d_h(A)这四个变换。当输入的anchor A与GT相差较小时,可以认为这种变换是一种线性变换, 那么就可以用线性回归来建模对窗口进行微调(注意,只有当anchors A和GT比较接近时,才能使用线性回归模型,否则就是复杂的非线性问题了。
接下来的问题就是如何通过线性回归获得dx(A),dy(A),dw(A),dh(A)d_x(A),d_y(A),d_w(A),d_h(A)
线性回归就是给定输入的特征向量X, 学习一组参数W, 使得经过线性回归后的值跟真实值Y非常接近,即Y=WXY=WX
对于该问题,输入X是cnn feature map,定义为Φ;同时还有训练传入A与GT之间的变换量,即tx,ty,tw,tht_x,t_y,t_w,t_h。输出是dx(A),dy(A),dw(A),dh(A)d_x(A),d_y(A),d_w(A),d_h(A)四个变换。那么目标函数可以表示为:
在这里插入图片描述
其中 Φ(A)是对应anchor的feature map组成的特征向量, WW_*是需要学习的参数, d(A)d_*(A)是得到的预测值(*表示 x,y,w,h,也就是每一个变换对应一个上述目标函数)。
为了让预测值d(A)d_*(A)与真实值 tt_* 差距最小,设计L1损失函数:
在这里插入图片描述
函数优化目标为
在这里插入图片描述

为了方便描述,这里以L1损失为例介绍,而真实情况中一般使用soomth-L1损失。

需要说明,只有在GT与需要回归框位置比较接近时,才可近似认为上述线性变换成立。

faster rcnn

说完原理,对应于Faster RCNN原文,positive anchor与ground truth之间的平移量 (tx,ty)(t_x,t_y) 与尺度因子tw,tht_w,t_h如下:
在这里插入图片描述
在这里插入图片描述

对于训练bouding box regression网络回归分支,输入是cnn feature Φ,监督信号是Anchor与GT的差距 tx,ty,tw,tht_x,t_y,t_w,t_h,即训练目标是:输入 Φ的情况下使网络输出与监督信号尽可能接近。那么当bouding box regression工作时,再输入Φ时,回归网络分支的输出就是每个Anchor的平移量和变换尺度 tx,ty,tw,tht_x,t_y,t_w,t_h,显然即可用来修正Anchor位置了。

代码

box_coder.py

/home/flora/maskrcnn-benchmark/maskrcnn_benchmark/modeling/box_coder.py

box_coder.py的decode过程中,我们可以看到通过对anchor A进行平移和缩放得到修正后的预测框GG^’的过程

    def decode(self, rel_codes, boxes):
        """
        From a set of original boxes and encoded relative box offsets,
        get the decoded boxes.

        Arguments:
            rel_codes (Tensor): encoded boxes
            boxes (Tensor): reference boxes.
        """
        #rel_codes.size()(box_regression) torch.Size([4000, 4])
        #boxes.size()(concat_anchors) torch.Size([4000, 4])      
        boxes = boxes.to(rel_codes.dtype) #把anchors也转成浮点数torch.float32
        
        #anchors的宽高和中心点
        TO_REMOVE = 1  # TODO remove
        widths = boxes[:, 2] - boxes[:, 0] + TO_REMOVE  #x2-x1 torch.Size([4000])
        heights = boxes[:, 3] - boxes[:, 1] + TO_REMOVE #y2-y1
        ctr_x = boxes[:, 0] + 0.5 * widths
        ctr_y = boxes[:, 1] + 0.5 * heights

        
        wx, wy, ww, wh = self.weights ##(1.0, 1.0, 1.0, 1.0)
        dx = rel_codes[:, 0::4] / wx #rel_codes的第0列
        dy = rel_codes[:, 1::4] / wy #rel_codes的第1列
        dw = rel_codes[:, 2::4] / ww #rel_codes的第2列
        dh = rel_codes[:, 3::4] / wh #rel_codes的第3列

        # Prevent sending too large values into torch.exp()
        dw = torch.clamp(dw, max=self.bbox_xform_clip) ##self.bbox_xform_clip4.135166556742356
        dh = torch.clamp(dh, max=self.bbox_xform_clip)

        #对anchor进行微调,使positive anchors与GT更加接近
        #先做平移
        pred_ctr_x = dx * widths[:, None] + ctr_x[:, None]
        pred_ctr_y = dy * heights[:, None] + ctr_y[:, None]
        #再做缩放
        pred_w = torch.exp(dw) * widths[:, None]
        pred_h = torch.exp(dh) * heights[:, None]

        #得到预测框的值(x1,y1,x2,y2)
        pred_boxes = torch.zeros_like(rel_codes)
        # x1
        pred_boxes[:, 0::4] = pred_ctr_x - 0.5 * pred_w
        # y1
        pred_boxes[:, 1::4] = pred_ctr_y - 0.5 * pred_h
        # x2 (note: "- 1" is correct; don't be fooled by the asymmetry)
        pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w - 1
        # y2 (note: "- 1" is correct; don't be fooled by the asymmetry)
        pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h - 1

        #torch.Size([4000, 4])
        return pred_boxes
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!