• Anchor 的两种编程实现


    • aspect ratios:高宽比率

    假设 window 的尺寸为:((w, h)),锚框的尺寸为:((w_1, h_1)),则有:

    [egin{cases} frac{w_1h_1}{wh} = s^2\ frac{h_1}{w_1} = frac{h}{w} r end{cases} ]

    可以化简为:

    [egin{cases} w_s = frac{w_1}{s} = frac{w}{sqrt{r}} \ h_s = frac{h_1}{s} = h sqrt{r} end{cases} ]

    我们可以有两种编程实现方式:

    1 (w=h)

    [egin{cases} w_s = frac{w_1}{s} = frac{w}{sqrt{r}} = ext{round}(sqrt{frac{wh}{r}})\ h_s = frac{h_1}{s} = h sqrt{r} = sqrt{whr} = ext{round}(w_s r) end{cases} ]

    编程实现:

    import numpy as np
    
    
    class AnchorBase:
        def __init__(self, base_size, scales, ratios):
            self.scales = np.array(scales)  #
            self.ratios = np.array(ratios)  #
            self.num_anchors = len(self.ratios) * len(self.scales)  # 锚框的个数
            self.base_size = base_size  # 滑动窗口的大小
            if isinstance(base_size, int):
                self._w, self._h = [base_size]*2
            elif len(base_size) == 2:
                self._w, self._h = base_size
            elif len(base_size) == 1:
                self._w, self._h = base_size*2
    
            self._anchor = np.array([1, 1, self._w, self._h]) - 1
    
        @property
        def anchor(self):
            return self._anchor
    
        @anchor.setter
        def anchor(self, new_anchor):
            self._anchor = new_anchor
    
        @property
        def w(self):
            '''
            锚框的宽度
            '''
            return self.anchor[2] - self.anchor[0] + 1
    
        @property
        def h(self):
            '''
            锚框的高度
            '''
            return self.anchor[3] - self.anchor[1] + 1
    
        @property
        def size(self):
            '''
            锚框的面积
            '''
            return self.w * self.h
    
        @property
        def _whctrs(self):
            """
            Return x center, and y center for an anchor (window). 锚框的中心坐标
            """
            x_ctr = self.anchor[0] + 0.5 * (self.w - 1)
            y_ctr = self.anchor[1] + 0.5 * (self.h - 1)
            return np.array([x_ctr, y_ctr])
    
        @staticmethod
        def _coordinate(aspect, ctr):
            '''
            依据宽高组合计算锚框的坐标
            '''
            k = (aspect - 1) / 2
            return np.concatenate([ctr - k, ctr + k], axis=1)
    
    
    class AnchorRCNN(AnchorBase):
        def __init__(self, base_size, scales, ratios):
            super().__init__(base_size, scales, ratios)
            self.anchors = self.gen_anchors()
    
        @property
        def ratio_aspects(self):
            '''
            依据 ratios 获取锚框的所有宽高组合
            '''
            size_ratios = self.size / self.ratios
            ws = np.round(np.sqrt(size_ratios))
            hs = np.round(ws * self.ratios)
            return np.stack([ws, hs], axis=1)
    
        @property
        def ratio_anchors(self):
            return self._coordinate(self.ratio_aspects, self._whctrs)
    
        @property
        def scale_aspects(self):
            '''
            依据 scales 获取锚框的所有宽高组合
            '''
            ws = self.w * self.scales
            hs = self.h * self.scales
            return np.stack([ws, hs], axis=1)
    
        @property
        def scale_anchors(self):
            return self._coordinate(self.scale_aspects, self._whctrs)
    
        def gen_anchors(self):
            '''
            获取最终的 base_anchors
            '''
            anchors = []
            for anchor in self.ratio_anchors:
                self.anchor = anchor
                anchors.append(self.scale_anchors)
            return np.concatenate(anchors)
    
    scales = [8, 16, 32]  # 尺度,面积比
    ratios = [0.5, 1, 2]  # window(滑动窗口) 与锚框的面积的比率(aspect ratios)
    base_size = 16  # 滑动窗口的大小
    
    self = AnchorRCNN(base_size, scales, ratios)
    
    self.anchors
    
    array([[ -84.,  -40.,   99.,   55.],
           [-176.,  -88.,  191.,  103.],
           [-360., -184.,  375.,  199.],
           [ -56.,  -56.,   71.,   71.],
           [-120., -120.,  135.,  135.],
           [-248., -248.,  263.,  263.],
           [ -36.,  -80.,   51.,   95.],
           [ -80., -168.,   95.,  183.],
           [-168., -344.,  183.,  359.]])
    
    self.ratio_anchors
    
    array([[-3. ,  2.5, 18. , 12.5],
           [ 0. ,  0. , 15. , 15. ],
           [ 2.5, -3. , 12.5, 18. ]])
    

    2

    [egin{cases} frac{w_1}{w} = frac{s}{sqrt{r}} = ext{round}(frac{s}{sqrt{r}})\ frac{h_1}{h} = s sqrt{r} = ext{round}(frac{w_1}{w} r) end{cases} ]

    [egin{cases} S = [s_1, s_1, cdots, s_m]\ R = [r_1, r_2, cdots, r_n] end{cases} ]

    则有(下面的运算均是元素级别的元素):

    [egin{cases} W = (frac{s_i}{sqrt{r_j}}) = frac{S}{sqrt{R}}\ H = (s_i sqrt{r_j}) = W cdot R end{cases} ]

    class Anchor(AnchorBase):
        def __init__(self, base_size, scales, ratios):
            super().__init__(base_size, scales, ratios)
    
        @property
        def W(self):
            '''
            计算 w_1/ w
            '''
            W = self.scales[:, None] / np.sqrt(self.ratios)
            return np.round(W)
    
        @property
        def H(self):
            '''
            计算 h_1/ h
            '''
            H = self.W * self.ratios
            return np.round(H)
    
        @property
        def aspect(self):
            '''
            所有的宽高组合
            '''
            return np.stack([self.W.flatten(), self.H.flatten()], axis=1)
    
        @property
        def base_anchors(self):
            return self._coordinate(self.aspect, self._whctrs)
    
        @property
        def anchors(self):
            '''
            获取最终的 base_anchors
            '''
            return self.base_anchors * np.array([self.w, self.h]*2)
    
    scales = [8, 16, 32]  # 尺度,面积比
    ratios = [0.5, 1, 2]  #  window(滑动窗口) 与锚框的面积的比率(aspect ratios)
    base_size = [16, 8]
    self = Anchor(base_size, scales, ratios)
    
    self.anchors
    
    array([[  40.,    8.,  200.,   48.],
           [  64.,    0.,  176.,   56.],
           [  80.,  -16.,  160.,   72.],
           [ -56.,  -16.,  296.,   72.],
           [   0.,  -32.,  240.,   88.],
           [  40.,  -56.,  200.,  112.],
           [-232.,  -56.,  472.,  112.],
           [-128.,  -96.,  368.,  152.],
           [ -56., -152.,  296.,  208.]])
    
    
    
  • 相关阅读:
    报表图片不显示的问题(一)
    数据库时区问题
    变色
    给div加滚动条,当内容超过它的范围的时候
    Apple Style Effect
    easyui发生重叠现象的原因
    mysql 获取字符串长度
    纯css的带下拉菜单的导航条
    jQuery验证控件jquery.validate.js使用说明+中文API
    background-position 用法详细介绍
  • 原文地址:https://www.cnblogs.com/q735613050/p/10587986.html
Copyright © 2020-2023  润新知