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)


初始化输出目标:

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数量:

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的缩放平移


        由于在图片预处理时,将图像最短边定为600,且整个图像做了缩放,所以在这一步获取bbox坐标时,也应作相对应的变化。

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循环中,即对每个bbox做判断。

初始化该bbox是否为target:bbox_type = 'neg'

计算当前bbox和图像中所有ground truth的bbox的IoU(调用def iou),结果赋给curr_iou;对每一个ground truth 的bbox,执行如下操作:


gta中存储的是原图的bbox的ground truth!!!

首先获取当前比较的这个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

再获取当前bbox中心:
cxa = (x1_anc + x2_anc) / 2.0

cya = (y1_anc + y2_anc) / 2.0

紧接着,比较两个bbox间的差异:

tx = (cx - cxa) / (x2_anc - x1_anc)#中心坐标

ty = (cy - cya) / (y2_anc - y1_anc)#中心坐标

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))#宽高比


如果当前ground truth bbox的label class不是background,即框住了某个物体:

!!!!必须保证原图中每一个ground truth bbox都能找到至少一个对应的anchor

如果当前这个坐标和尺寸的bbox与当前比较的ground truth bbox的IoU得分大于已有的得分,则更新:

best_anchor_for_bbox[bbox_num] = [jy, ix, anchor_ratio_idx,anchor_size_idx]#参数为当前bbox的中心坐标和长宽比以及整体尺寸;

并更新得分:

best_iou_for_bbox[bbox_num] = curr_iou

更新中心位置,即为当前这个anchor的坐标:

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

更新当前bbox与ground truth bbox的差异,宽高差异百分比、缩放差异百分比:

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


与上一个如果(if)是并列:

如果现在这个bbox与当前对比的ground truth bbox的重叠度超过C.rpn_max_overlap=0.7:

则认为当前bbox为正样本:bbox_type = 'pos'

当前ground_truth_bbox对应的anchor数量加一。

####

best_iou_for_loc在每次确定一个anchor对应的bbox后,初始化为0,接下来开始遍历所有原图中的ground truth bbox;目的是,找到和当前bbox匹配度最高的ground truth bbox。

#####

且,如果当前bbox的IoU大于了best_iou_for_loc,即这一步是定最好的回归参数:

           best_iou_for_loc = curr_iou

           best_regr = (tx, ty, tw, th)


如果当前IoU在0.3到0.7之间,则认为该bbox与当前遍历到的ground truth bbox关系不密切,则设: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有重叠。此时可以将其对应的回归参数best_regr保存下来。

对应的,

与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没有对应的anchor,即:

在各个尺寸的bbox下,没有一个anchor的bbox和gound truth bbox的IoU>0.7,也就是说

num_anchors_for_bbox = 0

我们必须保证每个ground truth bbox都能找到至少一个对应的anchor,则现在采取如下措施:
找到与其IoU最高的(尽管<0.7),将其坐标和尺寸以及相应的回归系数作为这个ground truth bbox对应的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参数做std_scaling,即对bbox的偏移做scaling:

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


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容