data_generator.py

class SampleSelector:

#param:class_count, img_data

def __init__:

? ? ? ? ? self.classes = [b for b in class_count.keys() if class_count[b] >0]

? ? ? ? ? self.class_cycle = itertools.cycle(self.classes)

? ? ? ? ? self.curr_class =next(self.class_cycle)#迭代器


def skip_sample_for_balanced_class(self, img_data):

獲取img_data中box信息,對于每個bbox,有key['class']表示該box中圖像的類別:

for bbox in img_data['bboxes']:

? ?cls_name = bbox['class']


def get_anchor_gt(all_img_data, class_count, C, model='train')

如果model=='train',則采用data_augment;否則,不采用:

img_data_aug, x_img = data_augment


令img_size最小邊為C.im_size,即最小邊為600,并等比縮放另一條邊:

resized_width, resized_height = get_new_img_size


計算rpn,

def calc_rpn(C, ing_data, width, height, resized_width, resized_height)

downscale = float(C.rpn_stride)

anchor_sizes = C.anchor_box_scales

anchor_ratios = C.anchor_box_ratios

num_anchors = len(anchor_sizes) * len(anchor_ratios)


初始化輸出目標(biāo):

y_rpn_overlap = np.zeros((output_height, output_width, num_anchors))#

y_is_box_valid = np.zeros((output_height, output_width, num_anchors))

y_rpn_regr = np.zeros((output_height, output_width, num_anchors * 4))


獲取一張圖中的bbox數(shù)量:

num_bboxes = len(img_data['bboxes'])


定義best_anchor:best_anchor_for_bbox = -1 * np.ones((num_bboxes, 4)).astype(int)

初始化iou, x, dx:

? ? ? ? best_iou_for_bbox = np.zeros(num_bboxes).astype(np.float32)#每一個bbox的IoU

? ? ? ? best_x_for_bbox = np.zeros((num_bboxes, 4)).astype(int)#每一個bbox的中心和寬高

? ? ? ? best_dx_for_bbox = np.zeros((num_bboxes, 4)).astype(np.float32)#每一個bbox的縮放平移


? ? ? ? 由于在圖片預(yù)處理時,將圖像最短邊定為600,且整個圖像做了縮放,所以在這一步獲取bbox坐標(biāo)時,也應(yīng)作相對應(yīng)的變化。

for bbox_num, bbox in enumerate(img_data['bboxes']):

'''獲取每個bbox的ground truth'''

? ? ? ? ? ?gta[bbox_num, 0] = bbox['x1'] * (resized_width / float(width))

? ? ? ? ? ?gta[bbox_num, 1] = bbox['x2'] * (resized_width / float(width))

? ? ? ? ? ?gta[bbox_num, 2] = bbox['y1'] * (resized_height / float(height))

? ? ? ? ? ?gta[bbox_num, 3] = bbox['y2'] * (resized_height / float(height))


獲取rpn gound truth:

在圖片上,從bbox整體不越界的第一個位置開始,每隔rpn_stride=16個像素,取3 x 3個anchor;

for anchor_size_idx in range(len(anchor_sizes)):

? ? for anchor_ratio_idx in range(n_anchratios):

? ? ? ? ? ? anchor_x = anchor_sizes[anchor_size_idx] * anchor_ratios[anchor_ratio_idx][0]

? ? ? ? ? ? anchor_y = anchor_sizes[anchor_size_idx] * anchor_ratios[anchor_ratio_idx][1]

? ? ? ? ? ? for ix in range(output_width):

? ? ? ? ? ? ? ? ? ?# x-coordinates of the current anchor box

? ? ? ? ? ? ? ? ? x1_anc = downscale * (ix +0.5) - anchor_x /2

? ? ? ? ? ? ? ? ? x2_anc = downscale * (ix +0.5) + anchor_x /2

? ? ? ? ? ? ? ? ? # ignore boxes that go across image boundaries

? ? ? ? ? ? ? ? ? if x1_anc <0 or x2_anc > resized_width:

? ? ? ? ? ? ? ? ? ? ? ? ? ?continue

? ? ? ? ? ?for jy in range(output_height):

? ? ? ? ? ? ? ? ? ?# y-coordinates of the current anchor box

? ? ? ? ? ? ? ? ? ?y1_anc = downscale * (jy +0.5) - anchor_y /2

? ? ? ? ? ? ? ? ? ?y2_anc = downscale * (jy +0.5) + anchor_y /2

? ? ? ? ? ? ? ? ? # ignore boxes that go across image boundaries

? ? ? ? ? ? ? ? ? if y1_anc <0 or y2_anc > resized_height:

? ? ? ? ? ? ? ? ? ? ? ? ? ?continue


這一步嵌套在上層for循環(huán)中,即對每個bbox做判斷。

初始化該bbox是否為target:bbox_type = 'neg'

計算當(dāng)前bbox和圖像中所有g(shù)round truth的bbox的IoU(調(diào)用def iou),結(jié)果賦給curr_iou;對每一個ground truth 的bbox,執(zhí)行如下操作:


gta中存儲的是原圖的bbox的ground truth?。。?/p>

首先獲取當(dāng)前比較的這個ground truth bbox的中心:

cx = (gta[bbox_num, 0] + gta[bbox_num, 1]) / 2.0

cy = (gta[bbox_num, 2] + gta[bbox_num, 3]) / 2.0

再獲取當(dāng)前bbox中心:
cxa = (x1_anc + x2_anc) / 2.0

cya = (y1_anc + y2_anc) / 2.0

緊接著,比較兩個bbox間的差異:

tx = (cx - cxa) / (x2_anc - x1_anc)#中心坐標(biāo)

ty = (cy - cya) / (y2_anc - y1_anc)#中心坐標(biāo)

tw = np.log((gta[bbox_num,1] - gta[bbox_num,0]) / (x2_anc - x1_anc))

th = np.log((gta[bbox_num,3] - gta[bbox_num,2]) / (y2_anc - y1_anc))#寬高比


如果當(dāng)前ground truth bbox的label class不是background,即框住了某個物體:

!?。。”仨毐WC原圖中每一個ground truth bbox都能找到至少一個對應(yīng)的anchor

如果當(dāng)前這個坐標(biāo)和尺寸的bbox與當(dāng)前比較的ground truth bbox的IoU得分大于已有的得分,則更新:

best_anchor_for_bbox[bbox_num] = [jy, ix, anchor_ratio_idx,anchor_size_idx]#參數(shù)為當(dāng)前bbox的中心坐標(biāo)和長寬比以及整體尺寸;

并更新得分:

best_iou_for_bbox[bbox_num] = curr_iou

更新中心位置,即為當(dāng)前這個anchor的坐標(biāo):

best_x_for_bbox[bbox_num,:] = [x1_anc, x2_anc, y1_anc, y2_anc]

更新當(dāng)前bbox與ground truth bbox的差異,寬高差異百分比、縮放差異百分比:

best_dx_for_bbox[bbox_num,:] = [tx, ty, tw, th]


與上一個如果(if)是并列:

如果現(xiàn)在這個bbox與當(dāng)前對比的ground truth bbox的重疊度超過C.rpn_max_overlap=0.7:

則認(rèn)為當(dāng)前bbox為正樣本:bbox_type = 'pos'

當(dāng)前ground_truth_bbox對應(yīng)的anchor數(shù)量加一。

####

best_iou_for_loc在每次確定一個anchor對應(yīng)的bbox后,初始化為0,接下來開始遍歷所有原圖中的ground truth bbox;目的是,找到和當(dāng)前bbox匹配度最高的ground truth bbox。

#####

且,如果當(dāng)前bbox的IoU大于了best_iou_for_loc,即這一步是定最好的回歸參數(shù):

? ? ? ? ? ?best_iou_for_loc = curr_iou

? ? ? ? ? ?best_regr = (tx, ty, tw, th)


如果當(dāng)前IoU在0.3到0.7之間,則認(rèn)為該bbox與當(dāng)前遍歷到的ground truth bbox關(guān)系不密切,則設(shè):bbox_type = 'neutral'


對于一個bbox,遍歷完原圖中所有的ground truth bbox后,

(1)如果bbox_type == 'neg',則表明該bbox是有用的,可以作為負樣本,但是沒有和rpn重疊;

(2)如果bbox_type == 'neutral',則表明該bbox沒有用處;

(3)如果bbox_type == 'pos'(只要該bbox與原圖中任何一個ground truth bbox的IoU>0.7,則該bbox可作為正樣本),則表明該bbox是有用的,可以作為正樣本,并且和rpn有重疊。此時可以將其對應(yīng)的回歸參數(shù)best_regr保存下來。

對應(yīng)的,

與rpn有重疊,y_rpn_overlap=1;bbox有用,y_is_box_valid=1;

y_rpn_overlap, y_is_box_valid:[output_height, output_width, num_anchors],

輸出圖片的某個位置[x, y]上,第i號尺寸的bbox有overlap或valid,記作:

y_rpn_overlap[x,y,i]=1, y_is_box_valid[x, y, i]=1


對于每一個anchor位置,每一種bbox尺寸都遍歷完之后

如果,有某個gound truth bbox沒有對應(yīng)的anchor,即:

在各個尺寸的bbox下,沒有一個anchor的bbox和gound truth bbox的IoU>0.7,也就是說

num_anchors_for_bbox = 0

我們必須保證每個ground truth bbox都能找到至少一個對應(yīng)的anchor,則現(xiàn)在采取如下措施:
找到與其IoU最高的(盡管<0.7),將其坐標(biāo)和尺寸以及相應(yīng)的回歸系數(shù)作為這個ground truth bbox對應(yīng)的anchor。


定義pos_loc為rpn_overlap和box_valid都為1的位置,定義neg_loc為均為0的位置。

由于RPN存在的問題是,negative遠超過positive,故對正負樣本做一定的取舍。


y_rpn_regr:[output_height, output_width, num_anchors * 4]

進行transpose以及expand_dim后:
y_rpn_overlap: [0, num_anchors, output_height, output_width]

y_is_box_valid: [0, num_anchors, output_height, output_width]

y_rpn_regr: [0, num_anchors*4, output_height, output_width]


最終,

y_rpn_cls = np.concatenate([y_is_box_valid, y_rpn_overlap],axis=1)

# [0, num_anchors*2, output_height , output_width]

y_rpn_regr = np.concatenate([np.repeat(y_rpn_overlap,4,axis=1), y_rpn_regr],axis=1)

# [0, num_anchors*8, output_height , output_width]


return np.copy(y_rpn_cls), np.copy(y_rpn_regr)


在def get_anchor_gt中,

y_rpn_cls, y_rpn_regr = 上欄中的return()

對于y_rpn_regr[0, num_anchors*8, output_height, output_width]第二個維度后4個anchor參數(shù)做std_scaling,即對bbox的偏移做scaling:

y_rpn_regr[:, y_rpn_regr.shape[1]//2:, :, :] *= C.std_scaling


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容