1. 程式人生 > >detectron程式碼理解(四):generate_anchors

detectron程式碼理解(四):generate_anchors

def generate_anchors(
    stride=16, sizes=(32, 64, 128, 256, 512), aspect_ratios=(0.5, 1, 2)
):
    """Generates a matrix of anchor boxes in (x1, y1, x2, y2) format. Anchors
    are centered on stride / 2, have (approximate) sqrt areas of the specified
    sizes, and aspect ratios as given.
    #這裡的stride可以理解為元anchor的邊長(base_size)
    產生anchor的原理是:
    (1)先對元anchor生成不同aspect_ratios下的base_anchors
    (2)再根據該層實際設計的anchor的sizes,將base_anchors進行擴大,擴大的倍數就是下面的:np.array(sizes, dtype=np.float) / stride
    """
    return _generate_anchors(
        stride,
        np.array(sizes, dtype=np.float) / stride,
        np.array(aspect_ratios, dtype=np.float)
    )


def _generate_anchors(base_size, scales, aspect_ratios):
    """Generate anchor (reference) windows by enumerating aspect ratios X
    scales wrt a reference (0, 0, base_size - 1, base_size - 1) window.
    
    """
    anchor = np.array([1, 1, base_size, base_size], dtype=np.float) - 1 #這個就是元anchor
    anchors = _ratio_enum(anchor, aspect_ratios)    #根據aspect_ratios,對元anchor生成不同ratio下的base_anchors
    #根據該層實際設計的anchor的邊長size,以及size與stride的關係(size/stride =scales),將base_anchors的邊長乘以scales
    anchors = np.vstack(
        [_scale_enum(anchors[i, :], scales) for i in range(anchors.shape[0])]   
    )
    return anchors


def _whctrs(anchor):
    """Return width, height, x center, and y center for an anchor (window)."""
    w = anchor[2] - anchor[0] + 1
    h = anchor[3] - anchor[1] + 1
    x_ctr = anchor[0] + 0.5 * (w - 1)
    y_ctr = anchor[1] + 0.5 * (h - 1)
    return w, h, x_ctr, y_ctr


def _mkanchors(ws, hs, x_ctr, y_ctr):
    """Given a vector of widths (ws) and heights (hs) around a center
    (x_ctr, y_ctr), output a set of anchors (windows).
    """
    ws = ws[:, np.newaxis] #由(3,)變為(3,1)
    hs = hs[:, np.newaxis]
    anchors = np.hstack(  #hstack橫向拼接,保證行不變,列合併,所以是anchors的大小是(3,4)
        (
            x_ctr - 0.5 * (ws - 1), #anchor左上角的x,大小為(3,1)
            y_ctr - 0.5 * (hs - 1), #anchor左上角的y,大小為(3,1)
            x_ctr + 0.5 * (ws - 1), #anchor右上角的x,大小為(3,1)
            y_ctr + 0.5 * (hs - 1)  #anchor右上角的y,大小為(3,1)
        )
    )
    return anchors


def _ratio_enum(anchor, ratios):
    """Enumerate a set of anchors for each aspect ratio wrt an anchor."""
    w, h, x_ctr, y_ctr = _whctrs(anchor)#返回高寬以及中心
    size = w * h  #面積
    #下面這三個是計算在面積相同情況固定長寬比下的長hs與寬ws
    size_ratios = size / ratios
    ws = np.round(np.sqrt(size_ratios))
    hs = np.round(ws * ratios)
    anchors = _mkanchors(ws, hs, x_ctr, y_ctr) #根據求取的長寬和中心seanchor
    return anchors


def _scale_enum(anchor, scales):
    """Enumerate a set of anchors for each scale wrt an anchor."""
    w, h, x_ctr, y_ctr = _whctrs(anchor) 
    ws = w * scales
    hs = h * scales
    anchors = _mkanchors(ws, hs, x_ctr, y_ctr)
    return anchors