Skip to content

Commit

Permalink
Add TEST.MODE top
Browse files Browse the repository at this point in the history
  • Loading branch information
endernewton committed Feb 7, 2017
1 parent ee021c9 commit 01ccafd
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 3 deletions.
1 change: 0 additions & 1 deletion lib/layer_utils/proposal_layer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# --------------------------------------------------------
# Faster R-CNN
# Copyright (c) 2017 Xinlei Chen
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick and Xinlei Chen
# --------------------------------------------------------
Expand Down
54 changes: 54 additions & 0 deletions lib/layer_utils/proposal_top_layer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# --------------------------------------------------------
# Faster R-CNN
# Licensed under The MIT License [see LICENSE for details]
# Written by Xinlei Chen
# --------------------------------------------------------

import numpy as np
from model.config import cfg
from model.bbox_transform import bbox_transform_inv, clip_boxes
import numpy.random as npr

def proposal_top_layer(rpn_cls_prob, rpn_bbox_pred, im_info, _feat_stride, anchors, anchor_scales):
"""A layer that just selects the top region proposals
without using non-maximal suppression,
For details please see the technical report
"""
rpn_top_n = cfg.TEST.RPN_TOP_N
scales = np.array(anchor_scales)
num_anchors = scales.shape[0] * 3
im_info = im_info[0]

scores = rpn_cls_prob[:, :, :, num_anchors:]

rpn_bbox_pred = rpn_bbox_pred.reshape((-1, 4))
scores = scores.reshape((-1, 1))

length = scores.shape[0]
if length < rpn_top_n:
# Random selection, maybe unnecessary and loses good proposals
# But this case rarely happen
top_inds = npr.choice(length, size=rpn_top_n, replace=True)
else:
top_inds = scores.argsort(0)[::-1]
top_inds = top_inds[:rpn_top_n]
top_inds = top_inds.reshape(rpn_top_n,)

# Do the selection here
anchors = anchors[top_inds,:]
rpn_bbox_pred = rpn_bbox_pred[top_inds,:]
scores = scores[top_inds]

# Convert anchors into proposals via bbox transformations
proposals = bbox_transform_inv(anchors, rpn_bbox_pred)

# Clip predicted boxes to image
proposals = clip_boxes(proposals, im_info[:2])

# Output rois blob
# Our RPN implementation only supports a single input image, so all
# batch inds are 0
batch_inds = np.zeros((proposals.shape[0], 1), dtype=np.float32)
blob = np.hstack((batch_inds, proposals.astype(np.float32, copy=False)))
return blob, scores

9 changes: 8 additions & 1 deletion lib/model/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,13 @@
# Proposal height and width both need to be greater than RPN_MIN_SIZE (at orig image scale)
# __C.TEST.RPN_MIN_SIZE = 16

# Testing mode, default to be 'nms', 'top' is slower but better
# See report for details
__C.TEST.MODE = 'nms'

# Only useful when TEST.MODE is 'top', specifies the number of top proposals to select
__C.TEST.RPN_TOP_N = 4096

#
# MISC
#
Expand Down Expand Up @@ -224,7 +231,7 @@
# Default GPU device id
__C.GPU_ID = 0

# Default pooling mode, either 'roi' or 'crop'
# Default pooling mode, only 'crop' is available
__C.POOLING_MODE = 'crop'


Expand Down
18 changes: 17 additions & 1 deletion lib/nets/vgg16.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from layer_utils.snippets import generate_anchors_pre
from layer_utils.proposal_layer import proposal_layer
from layer_utils.proposal_top_layer import proposal_top_layer
from layer_utils.anchor_target_layer import anchor_target_layer
from layer_utils.proposal_target_layer import proposal_target_layer

Expand Down Expand Up @@ -190,6 +191,16 @@ def _softmax_layer(self, bottom, name):
return tf.reshape(reshaped_score, input_shape)
return tf.nn.softmax(bottom, name=name)

def _proposal_top_layer(self, rpn_cls_prob, rpn_bbox_pred, name):
with tf.variable_scope(name) as scope:
rois, rpn_scores = tf.py_func(proposal_top_layer,
[rpn_cls_prob, rpn_bbox_pred, self._im_info,
self._feat_stride, self._anchors, self._anchor_scales], [tf.float32, tf.float32])
rois.set_shape([cfg.TEST.RPN_TOP_N, 5])
rpn_scores.set_shape([cfg.TEST.RPN_TOP_N, 1])

return rois, rpn_scores

def _proposal_layer(self, rpn_cls_prob, rpn_bbox_pred, name):
with tf.variable_scope(name) as scope:
rois, rpn_scores = tf.py_func(proposal_layer,
Expand Down Expand Up @@ -348,7 +359,12 @@ def _vgg16_from_imagenet(self, sess, train=True):
with tf.control_dependencies([rpn_labels]):
rois, _ = self._proposal_target_layer(rois, roi_scores, "rpn_rois")
else:
rois, _ = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois")
if cfg.TEST.MODE == 'nms':
rois, _ = self._proposal_layer(rpn_cls_prob, rpn_bbox_pred, "rois")
elif cfg.TEST.MODE == 'top':
rois, _ = self._proposal_top_layer(rpn_cls_prob, rpn_bbox_pred, "rois")
else:
raise NotImplementedError

# rcnn
if cfg.POOLING_MODE == 'crop':
Expand Down
1 change: 1 addition & 0 deletions lib/roi_data_layer/layer.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def _shuffle_roidb_inds(self):
"""Randomly permute the training roidb."""
# If the random flag is set,
# then the database is shuffled according to system time
# Useful for the validation set
if self._random:
st0 = np.random.get_state()
millis = int(round(time.time() * 1000)) % 4294967295
Expand Down

0 comments on commit 01ccafd

Please sign in to comment.