1. 程式人生 > >tensorflow+faster rcnn程式碼理解(四)boundingbox迴歸

tensorflow+faster rcnn程式碼理解(四)boundingbox迴歸

1.為什麼要做Bounding-box regression?

如圖所示,綠色的框為飛機的Ground Truth,紅色的框是提取的Region Proposal。那麼即便紅色的框被分類器識別為飛機,但是由於紅色的框定位不準(IoU<0.5),那麼這張圖相當於沒有正確的檢測出飛機。如果我們能對紅色的框進行微調,使得經過微調後的視窗跟Ground Truth更接近,這樣豈不是定位會更準確。所以,Bounding-box regression 就是用來微調這個視窗的。

2.  迴歸/微調的物件是什麼?

3. Bounding-box regression(邊框迴歸)

注意:只有當Proposal和Ground Truth比較接近時(線性問題),我們才能將其作為訓練樣本訓練我們的線性迴歸模型,否則會導致訓練的迴歸模型不work(當Proposal跟GT離得較遠,就是複雜的非線性問題了,此時用線性迴歸建模顯然不合理)。這個也是G-CNN: an Iterative Grid Based Object Detector多次迭代實現目標準確定位的關鍵。

4. tensorflow faster rcnn程式碼中的實現

faster rcnn中進行邊框迴歸存在於兩個部分,第一個是在訓練RPN的過程中對anchor進行邊框迴歸,另一個是在訓練fast rcnn過程中對proposal進行邊框迴歸。

4.1 RPN訓練中的邊框迴歸

在RPN的訓練中,一方面會輸出anchor對於gt的預測的偏移量rpn_bbox_pred,同時anchor_target_layer會計算anchor與gt的實際的偏移量rpn_bbox_targets,計算的公式如下:

程式碼實現如下(該函式中anchor是經過篩選後存在於圖片大小邊界內的,對於那些篩選掉的anchor,其四個偏移引數預設全為0。)

def bbox_transform(ex_rois, gt_rois):
    #計算anchor的長寬以及中心
    ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0
    ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0
    ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths
    ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights
    
    #計算gt的長寬以及中心
    gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + 1.0
    gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + 1.0
    gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths
    gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights
    #anchor與gt的實際偏移量
    targets_dx = (gt_ctr_x - ex_ctr_x) / ex_widths
    targets_dy = (gt_ctr_y - ex_ctr_y) / ex_heights
    targets_dw = np.log(gt_widths / ex_widths)
    targets_dh = np.log(gt_heights / ex_heights)

    targets = np.vstack(
        (targets_dx, targets_dy, targets_dw, targets_dh)).transpose()
    return targets

 利用rpn_bbox_pred、rpn_bbox_targets、rpn_inside_weights和rpn_outside_weights就可以計算RPN bbox loss。

見部落格tensorflow+faster rcnn程式碼理解(三):損失函式構建

4.2 fast rcnn訓練中的邊框迴歸

在訓練fast rcnn之前要從proposal_layer從約20000個anchor中選擇出12000個proposal作為rois,從anchor->proposal的過程需要對anchor進行修正,修正的公式就是:

 程式碼實現為如下,其中delas就是RPN網路輸出的預測偏移量rpn_bbox_pred.

def bbox_transform_inv(boxes, deltas):
    if boxes.shape[0] == 0:
        return np.zeros((0, deltas.shape[1]), dtype=deltas.dtype)

    boxes = boxes.astype(deltas.dtype, copy=False)
    widths = boxes[:, 2] - boxes[:, 0] + 1.0
    heights = boxes[:, 3] - boxes[:, 1] + 1.0
    ctr_x = boxes[:, 0] + 0.5 * widths   #anchor的中心
    ctr_y = boxes[:, 1] + 0.5 * heights

    dx = deltas[:, 0::4] 
    dy = deltas[:, 1::4] 
    dw = deltas[:, 2::4]  
    dh = deltas[:, 3::4]
    #修正後的中心點座標(x,y)以及w、h
    pred_ctr_x = dx * widths[:, np.newaxis] + ctr_x[:, np.newaxis]
    pred_ctr_y = dy * heights[:, np.newaxis] + ctr_y[:, np.newaxis]
    pred_w = np.exp(dw) * widths[:, np.newaxis]
    pred_h = np.exp(dh) * heights[:, np.newaxis]

    pred_boxes = np.zeros(deltas.shape, dtype=deltas.dtype)
    # 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
    pred_boxes[:, 2::4] = pred_ctr_x + 0.5 * pred_w
    # y2
    pred_boxes[:, 3::4] = pred_ctr_y + 0.5 * pred_h

    return pred_boxes

修正完畢後,在proposal_target_layer,會選擇出來的128個rois,此時就要計算這些rois與gt實際的偏移量bbox_targets,會呼叫bbox_transform函式,見4.1:

 bbox_target_data = _compute_targets(
        rois[:, 1:5], gt_boxes[gt_assignment[keep_inds], :4], labels)

而這些rois經過fast rcnn部分的訓練後會輸出預測的偏移量bbox_pred,因此利用bbox_targets,bbox_pred bbox_inside_weights,bbox_outside_weights就可以計算fastrcnn部分的bbox loss。

見部落格tensorflow+faster rcnn程式碼理解(三):損失函式構建