一、利用ROI训练分类器
最后是ROI的生成了,在每个训练的epch循环中,核心代码如下:
#输出:yield np.copy(x_img), [np.copy(y_rpn_cls), np.copy(y_rpn_regr)], img_data_aug
#网络训练的输入是图片,和找到的最优的anchor,不是GTbox
X, Y, img_data = next(data_gen_train)
#
loss_rpn = model_rpn.train_on_batch(X, Y)#Scalar training loss (if the model has a single output and no metrics) or list of scalars (if the model has multiple outputs and/or metrics).
write_log(callback, ['rpn_cls_loss', 'rpn_reg_loss'], loss_rpn, train_step)
P_rpn = model_rpn.predict_on_batch(X)#获取预测的Y值,即[np.copy(y_rpn_cls), np.copy(y_rpn_regr)]
#筛选出ROI,ROI指的是在feature map中合法box中具有最大概率包含物体的box,删除重叠率较高的box之后剩下来的box(xxx,4)
R = roi_helpers.rpn_to_roi(P_rpn[0], P_rpn[1], C, K.image_dim_ordering(), use_regr=True, overlap_thresh=0.7, max_boxes=300)
# note: calc_iou converts from (x1,y1,x2,y2) to (x,y,w,h) format
#img_data,图片的信息,R候选ROI
#输出:
#X2:#选取的iou大于0.7的roi,这里用X2是为了和上面的X相区别,
#Y1:对应的类别序号(1,xxx,21),类别标签是one_hot
#Y2:[np.array(y_class_regr_label),np.array(y_class_regr_coords)]包含对应的类别的标签和回归参数,类别标签是one_hot的
#IoUs:用于调试的,没有用
X2, Y1, Y2, IouS = roi_helpers.calc_iou(R, img_data, C, class_mapping)
if X2 is None:
rpn_accuracy_rpn_monitor.append(0)
rpn_accuracy_for_epoch.append(0)
continue
# sampling positive/negative samples
neg_samples = np.where(Y1[0, :, -1] == 1)#背景,最后一项代表背景分类
pos_samples = np.where(Y1[0, :, -1] == 0)#非背景
if len(neg_samples) > 0:
neg_samples = neg_samples[0]
else:
neg_samples = []
if len(pos_samples) > 0:
pos_samples = pos_samples[0]
else:
pos_samples = []
rpn_accuracy_rpn_monitor.append(len(pos_samples))
rpn_accuracy_for_epoch.append((len(pos_samples)))
if C.num_rois > 1:
if len(pos_samples) < C.num_rois//2:#选取一些正例样本和一些反例样本,共300个,每类约150个
selected_pos_samples = pos_samples.tolist()
else:
selected_pos_samples = np.random.choice(pos_samples, C.num_rois//2, replace=False).tolist()
try:
selected_neg_samples = np.random.choice(neg_samples, C.num_rois - len(selected_pos_samples), replace=False).tolist()
except:
selected_neg_samples = np.random.choice(neg_samples, C.num_rois - len(selected_pos_samples), replace=True).tolist()
sel_samples = selected_pos_samples + selected_neg_samples
else:
# in the extreme case where num_rois = 1, we pick a random pos or neg sample
selected_pos_samples = pos_samples.tolist()
selected_neg_samples = neg_samples.tolist()
if np.random.randint(0, 2):
sel_samples = random.choice(neg_samples)
else:
sel_samples = random.choice(pos_samples)
#X用于生成share_layers,X2是挑选出来的roi
loss_class = model_classifier.train_on_batch([X, X2[:, sel_samples, :]], [Y1[:, sel_samples, :], Y2[:, sel_samples, :]])
write_log(callback, ['detection_cls_loss', 'detection_reg_loss', 'detection_acc'], loss_class, train_step)
train_step += 1
这里面有两个关键方法,rpn_to_roi和calc_iou