代码解读记录

调整数据集:
merge_data.py --> select.py --> order.py

Dataset:
image_info = [ {“source”: “id”: “path”: “width”: “height”: “mask_path”: “yaml_path”: }, { }, { }… ] 用**add_image()添加
class_info = [ {“source”: “id”: “name”: }, { }, { }… ] 用
add_class()**添加

image_meta = np.array([image_id] + list(original_image_shape) + list(image_shape) + list(window) + [scale] + list(active_class_ids))

输入输出的格式(ndarray):
rpn_class_logits: [batch, anchors, 2] 2是[FG, BG]
rpn_probs: [batch, anchors, 2] 2是[FG, BG]
rpn_bbox: [batch, anchors, 4] 4是[x, y, log(w), log(h)]
anchors: [N, (y1, x1, y2, x2)]

boxes: [num_instance, (y1, x1, y2, x2, class_id)] in image coordinates.
masks: [height, width, num_instances]
class_ids: [num_instances]

data_generator

  • images: [batch, H, W, C]
  • image_meta: [batch, (meta data)] Image details.
  • rpn_match: [batch, N] Integer (1=positive anchor, -1=negative, 0=neutral)
  • rpn_bbox: [batch, N, (dy, dx, log(dh), log(dw))] Anchor bbox deltas.
  • gt_class_ids: [batch, MAX_GT_INSTANCES] Integer class IDs
  • gt_boxes: [batch, MAX_GT_INSTANCES, (y1, x1, y2, x2)]
  • gt_masks: [batch, height, width, MAX_GT_INSTANCES].

训练参数

steps_per_epoch 就是多少个batch算一个epoch,此时的epoch不一定是全体训练集。

训练流程##

1、创建MirrorDataset对象dataset_train和dataset_val
2、调用该对象的load_mirror(),Image.open()读取label8.png,用add_class()加入镜子类,再用add_image()将mask和yaml路径信息加入Mirror数据集
3、调用该对象的prepare()方法,为处理多个数据集的情况,在这里我们只有Mirror一个数据集,因此没啥实质上的作用
4、创建MaskRCNN的model
5、设置初始化的权重:coco、imagenet、or last
6、model.train()中,data_generator()–>load_image_gt()–>mirror.load_image, mirror.load_mask, and utils.extract_bboxes(mask).
data_generator()可以设置数据扩充参数
load_image()使用skimage.io.imread()读取rgb图片
load_mask()自己定义的,调用draw_mask()绘制mask,再从最后一层往前用occlusion乘mask依次得到前面的mask.

7、设置model_path,调用model.keras_model.save_weights()保存模型权重

测试流程

compute_ap_mask()解读
首先调用compute_matches()
sort(x)返回ndarray的从小到大的索引值,类型为ndarray,[::-1]所有元素倒过来
1.gt_boxes将全是0的行去掉。
2.根据pred_scores从大到小排序pred_boxes.class_ids.scores.masks.
3.计算pred和gt mask之间的overlaps,是一个矩阵,其中pred是行,gt是列。在两个坐标轴的方向上都是从高到低排序的。纵轴pred按照scores降序排序,横轴gt按照overlaps降序排序。
4.两层循环,寻找匹配(1)对overlaps的每一行进行从大到小的排序,因为每一行代表预测的一个实例(2)设置一个score_threshold(目前设置的是0),低于这个score的排在后面的就不要了(3)对于每一行,列从前到后(也就是数值从大到小)的顺序查找,如果iou小于设定的阀值iou_threshold,则跳过,继续保持为-1。如果预测的类别和gt的类别正好相同,那么match_count加一,gt_match[列数]=预测的行数,pred_match[行数]=gt的列数,意思就是对于每列的gt,gt_match保存预测的实例 在预测结果中的第几行;pred_match也是如此。

然后用np.cumsum()函数按照pred_match计算出每一步的precisions和recalls,调整precisions只减不增,接着找出recalls变化的那一步,用横坐标的宽×纵坐标的precision,最后mAP就都算出来了!

compute_ap_box()实现原理
为每一个预测的box(行),找到与之对应的gt_box,就是与该预测box的iou最大的那一个gt_box。
对于每一行,如果iou大于阀值,就认为找对了。
因为类别只有镜子,所以不需要判断预测类别和真实类别是否一致(因为肯定是一致的),对每一行的所有列取的最大值,可能存在一个gt_box对应多个pred_box的情况。而compute_ap_mask()函数中是逐个元素判断的,只有类别一致才可以认为找到了,都是准确的一一对应的。

RPN

Level 0. Anchors: 76800 Feature map Shape: [160 160]
Level 1. Anchors: 19200 Feature map Shape: [80 80]
Level 2. Anchors: 4800 Feature map Shape: [40 40]
Level 3. Anchors: 1200 Feature map Shape: [20 20]
Level 4. Anchors: 300 Feature map Shape: [10 10]
一共是102300个anchor。

Generate Proposals流程(1940行)##

设置产生的proposal的数量:训练2000,测试1000
调用ProposalLayer,输入[rpn输出的类别的概率,rpn输出边界框的delta,anchors]
根据类别的得分,选出不多于6000个anchor,将选出的对应的delta应用到anchor上,将这些anchor进行clip(别超出图像的边界),进行nms,得到proposals,如果不够2000个的话,用0补齐。
在这里应该是anchor的顺序和rpn输出的顺序默认是一致的。rpn会按顺序产生每一个anchor的前景/背景得分、delta。Proposals是相对整个图的比例了,不是delta了。

Generate Detection Targets(1968行)

调用DetectionTargetLayer
输入:[ target_rois, input_gt_class_ids, gt_boxes, input_gt_masks]
调用detection_targets_graph

asserts = [tf.Assert(tf.greater(tf.shape(proposals)[0], 0), [proposals], name="roi_assertion"),]
with tf.control_dependencies(asserts):
    proposals = tf.identity(proposals)

Assert (
condition ,
data ,
summarize = None ,
name = None

在执行proposals = tf.identity(proposals)之前先执行asserts。
首先去除0的padding,找一下有没有拥挤的bbox,计算rpn产生的proposals和gt_boxes之间的overlaps,proposal是行,gt_box是列,在每一行找到最大值,如果大于0.5,就认为这个proposal是positive的,否则是negative。将positive的索引打乱,取前X个(X是自己设置的),negative的也是。根据索引在proposals中选取positive和negative的。在输入的gt中找出索引对应的box和id。调用box_refinement_graph,计算proposal的box和gt的box的delta [dy, dx, dh, dw] (proposal可以根据这些数据计算出gt的box)。然后再除个std_dev。找出gt的mask,把proposal对应的区域抠出来,二值化处理。
最后把positive和negative拼接起来,再补一些0,就得到输出:[预测的roi(调整好正负比例的),预测的roi的gt类别号,预测的roi到gt_box的delta,预测的roi对应的gt的mask]

数据集扩充

图片的尺寸 (width,height)

One

build_fpn_mask_graph()
调用PyramidROIAlign_mask()生成固定尺寸的特征图,然后送入decoder中。
在函数PyramidROIAlign_mask()中,roi_level的尺寸是batch行,box_number列,矩阵中的每个元素代表level,ix是roi_level筛选后的结果,对ix取第一个维度ranhou就是tf.image.crop_and_resize函数中的box_indices, 就是记录每个box是来在mini_batch中的哪一个。

数量

训练时POST_NMS_ROIS_TRAINING(2000)个proposals ,经过DetectionTargetLayer变成了100个(TRAIN_ROIS_PER_IMAGE)然后再送入classifier和mask中,因此shared的数量是100。
测试时POST_NMS_ROIS_INFERENCE(1000)个proposals ,先送入classifier,产生了1000的shared,然后再过DetectionLayer,数量变为100(DETECTION_MAX_INSTANCES),然后再送入mask分支,shared的数量和mask的数量不一致了(1000vs100),因此在fusion_context_guided_decoder中设置二者相同。

关于mask

在DetectionTargetLayer,产生对应proposal的mask,然后用bilinear来resize到64x64,mrcnn_mask是由mask_branch产生的,也是64x64的,最后二者算binary loss
测试的时候,对每个proposal产生64x64的mask结果,用bilinear(在utils.unmold_mask里面)再缩放至proposal的尺寸。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值