提交 13701da8 编写于 作者: W Waleed Abdulla

Refactoring and clean up. No functionality change

上级 7444fbaa
...@@ -115,6 +115,9 @@ class Config(object): ...@@ -115,6 +115,9 @@ class Config(object):
# Pooled ROIs # Pooled ROIs
POOL_SIZE = 7 POOL_SIZE = 7
MASK_POOL_SIZE = 14 MASK_POOL_SIZE = 14
# Shape of output mask
# To change this you also need to change the neural network mask branch
MASK_SHAPE = [28, 28] MASK_SHAPE = [28, 28]
# Maximum number of ground truth instances to use in one image # Maximum number of ground truth instances to use in one image
......
...@@ -1728,12 +1728,9 @@ def data_generator(dataset, config, shuffle=True, augment=False, augmentation=No ...@@ -1728,12 +1728,9 @@ def data_generator(dataset, config, shuffle=True, augment=False, augmentation=No
(batch_size, config.MAX_GT_INSTANCES), dtype=np.int32) (batch_size, config.MAX_GT_INSTANCES), dtype=np.int32)
batch_gt_boxes = np.zeros( batch_gt_boxes = np.zeros(
(batch_size, config.MAX_GT_INSTANCES, 4), dtype=np.int32) (batch_size, config.MAX_GT_INSTANCES, 4), dtype=np.int32)
if config.USE_MINI_MASK: batch_gt_masks = np.zeros(
batch_gt_masks = np.zeros((batch_size, config.MINI_MASK_SHAPE[0], config.MINI_MASK_SHAPE[1], (batch_size, gt_masks.shape[1], gt_masks.shape[1],
config.MAX_GT_INSTANCES)) config.MAX_GT_INSTANCES), dtype=gt_masks.dtype)
else:
batch_gt_masks = np.zeros(
(batch_size, image.shape[0], image.shape[1], config.MAX_GT_INSTANCES))
if random_rois: if random_rois:
batch_rpn_rois = np.zeros( batch_rpn_rois = np.zeros(
(batch_size, rpn_rois.shape[0], 4), dtype=rpn_rois.dtype) (batch_size, rpn_rois.shape[0], 4), dtype=rpn_rois.dtype)
...@@ -2446,15 +2443,15 @@ class MaskRCNN(): ...@@ -2446,15 +2443,15 @@ class MaskRCNN():
for image in images: for image in images:
log("image", image) log("image", image)
# Mold inputs to format expected by the neural network
molded_images, image_metas, windows = self.mold_inputs(images)
# Validate image sizes # Validate image sizes
if self.config.IMAGE_RESIZE_MODE == "square": # All images in a batch MUST be of the same size
image_shape = self.config.IMAGE_SHAPE image_shape = molded_images[0].shape
else: for g in molded_images[1:]:
# All images MUST be of the same size assert g.shape == image_shape,\
image_shape = images[0].shape "After resizing, all images must have the same size. Check IMAGE_RESIZE_MODE and image sizes."
for g in images[1:]:
assert g.shape == image_shape,\
"Images must have the same size unless IMAGE_RESIZE_MODE is 'square'"
# Anchors # Anchors
anchors = self.get_anchors(image_shape) anchors = self.get_anchors(image_shape)
...@@ -2462,8 +2459,6 @@ class MaskRCNN(): ...@@ -2462,8 +2459,6 @@ class MaskRCNN():
# TODO: can this be optimized to avoid duplicating the anchors? # TODO: can this be optimized to avoid duplicating the anchors?
anchors = np.broadcast_to(anchors, (self.config.BATCH_SIZE,) + anchors.shape) anchors = np.broadcast_to(anchors, (self.config.BATCH_SIZE,) + anchors.shape)
# Mold inputs to format expected by the neural network
molded_images, image_metas, windows = self.mold_inputs(images)
if verbose: if verbose:
log("molded_images", molded_images) log("molded_images", molded_images)
log("image_metas", image_metas) log("image_metas", image_metas)
......
...@@ -602,23 +602,25 @@ def trim_zeros(x): ...@@ -602,23 +602,25 @@ def trim_zeros(x):
return x[~np.all(x == 0, axis=1)] return x[~np.all(x == 0, axis=1)]
def compute_ap(gt_boxes, gt_class_ids, gt_masks, def compute_matches(gt_boxes, gt_class_ids, gt_masks,
pred_boxes, pred_class_ids, pred_scores, pred_masks, pred_boxes, pred_class_ids, pred_scores, pred_masks,
iou_threshold=0.5): iou_threshold=0.5, score_threshold=0.0):
"""Compute Average Precision at a set IoU threshold (default 0.5). """Finds matches between prediction and ground truth instances.
Returns: Returns:
mAP: Mean Average Precision gt_match: 1-D array. For each GT box it has the index of the matched
precisions: List of precisions at different class score thresholds. predicted box.
recalls: List of recall values at different class score thresholds. pred_match: 1-D array. For each predicted box, it has the index of
overlaps: [pred_boxes, gt_boxes] IoU overlaps. the matched ground truth box.
overlaps: [pred_boxes, gt_boxes] IoU overlaps.
""" """
# Trim zero padding and sort predictions by score from high to low # Trim zero padding
# TODO: cleaner to do zero unpadding upstream # TODO: cleaner to do zero unpadding upstream
gt_boxes = trim_zeros(gt_boxes) gt_boxes = trim_zeros(gt_boxes)
gt_masks = gt_masks[..., :gt_boxes.shape[0]] gt_masks = gt_masks[..., :gt_boxes.shape[0]]
pred_boxes = trim_zeros(pred_boxes) pred_boxes = trim_zeros(pred_boxes)
pred_scores = pred_scores[:pred_boxes.shape[0]] pred_scores = pred_scores[:pred_boxes.shape[0]]
# Sort predictions by score from high to low
indices = np.argsort(pred_scores)[::-1] indices = np.argsort(pred_scores)[::-1]
pred_boxes = pred_boxes[indices] pred_boxes = pred_boxes[indices]
pred_class_ids = pred_class_ids[indices] pred_class_ids = pred_class_ids[indices]
...@@ -634,10 +636,16 @@ def compute_ap(gt_boxes, gt_class_ids, gt_masks, ...@@ -634,10 +636,16 @@ def compute_ap(gt_boxes, gt_class_ids, gt_masks,
gt_match = np.zeros([gt_boxes.shape[0]]) gt_match = np.zeros([gt_boxes.shape[0]])
for i in range(len(pred_boxes)): for i in range(len(pred_boxes)):
# Find best matching ground truth box # Find best matching ground truth box
# 1. Sort matches by score
sorted_ixs = np.argsort(overlaps[i])[::-1] sorted_ixs = np.argsort(overlaps[i])[::-1]
# 2. Remove low scores
low_score_idx = np.where(overlaps[i, sorted_ixs] < score_threshold)[0]
if low_score_idx.size > 0:
sorted_ixs = sorted_ixs[:low_score_idx[0]]
# 3. Find the match
for j in sorted_ixs: for j in sorted_ixs:
# If ground truth box is already matched, go to next one # If ground truth box is already matched, go to next one
if gt_match[j] == 1: if gt_match[j] > 0:
continue continue
# If we reach IoU smaller than the threshold, end the loop # If we reach IoU smaller than the threshold, end the loop
iou = overlaps[i, j] iou = overlaps[i, j]
...@@ -646,13 +654,33 @@ def compute_ap(gt_boxes, gt_class_ids, gt_masks, ...@@ -646,13 +654,33 @@ def compute_ap(gt_boxes, gt_class_ids, gt_masks,
# Do we have a match? # Do we have a match?
if pred_class_ids[i] == gt_class_ids[j]: if pred_class_ids[i] == gt_class_ids[j]:
match_count += 1 match_count += 1
gt_match[j] = 1 gt_match[j] = i
pred_match[i] = 1 pred_match[i] = j
break break
return gt_match, pred_match, overlaps
def compute_ap(gt_boxes, gt_class_ids, gt_masks,
pred_boxes, pred_class_ids, pred_scores, pred_masks,
iou_threshold=0.5):
"""Compute Average Precision at a set IoU threshold (default 0.5).
Returns:
mAP: Mean Average Precision
precisions: List of precisions at different class score thresholds.
recalls: List of recall values at different class score thresholds.
overlaps: [pred_boxes, gt_boxes] IoU overlaps.
"""
# Get matches and overlaps
gt_match, pred_match, overlaps = compute_matches(
gt_boxes, gt_class_ids, gt_masks,
pred_boxes, pred_class_ids, pred_scores, pred_masks,
iou_threshold)
# Compute precision and recall at each prediction box step # Compute precision and recall at each prediction box step
precisions = np.cumsum(pred_match) / (np.arange(len(pred_match)) + 1) precisions = np.cumsum(pred_match > 0) / (np.arange(len(pred_match)) + 1)
recalls = np.cumsum(pred_match).astype(np.float32) / len(gt_match) recalls = np.cumsum(pred_match > 0).astype(np.float32) / len(gt_match)
# Pad with start and end values to simplify the math # Pad with start and end values to simplify the math
precisions = np.concatenate([[0], precisions, [0]]) precisions = np.concatenate([[0], precisions, [0]])
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册