Ejemplo n.º 1
0
 def _distribute_rois_over_fpn_levels(rois_blob_name):
     """Distribute rois over the different FPN levels."""
     # Get target level for each roi
     # Recall blob rois are in (batch_idx, x1, y1, x2, y2) format, hence take
     # the box coordinates from columns 1:5
     target_lvls = fpn.map_rois_to_fpn_levels(blobs[rois_blob_name][:, 1:5],
                                              lvl_min, lvl_max)
     # Add per FPN level roi blobs named like: <rois_blob_name>_fpn<lvl>
     fpn.add_multilevel_roi_blobs(blobs, rois_blob_name,
                                  blobs[rois_blob_name], target_lvls,
                                  lvl_min, lvl_max)
Ejemplo n.º 2
0
 def _distribute_rois_over_fpn_levels(rois_blob_name):
     """Distribute rois over the different FPN levels."""
     # Get target level for each roi
     # Recall blob rois are in (batch_idx, x1, y1, x2, y2) format, hence take
     # the box coordinates from columns 1:5
     target_lvls = fpn.map_rois_to_fpn_levels(
         blobs[rois_blob_name][:, 1:5], lvl_min, lvl_max
     )
     # Add per FPN level roi blobs named like: <rois_blob_name>_fpn<lvl>
     fpn.add_multilevel_roi_blobs(
         blobs, rois_blob_name, blobs[rois_blob_name], target_lvls, lvl_min,
         lvl_max
     )
Ejemplo n.º 3
0
def _add_multilevel_rois(blobs):
    lvl_min = cfg.FPN.ROI_MIN_LEVEL
    lvl_max = cfg.FPN.ROI_MAX_LEVEL
    # The map_rois_to_fpn_levels and add_multilevel_roi_blobs functions are
    # shared among the 2D and 3D models.
    lvls = fpn.map_rois_to_fpn_levels(blobs['rois'][:, 1:], lvl_min, lvl_max)
    fpn.add_multilevel_roi_blobs(blobs, 'rois', blobs['rois'], lvls, lvl_min,
                                 lvl_max)

    if cfg.MODEL.MASK_ON:
        # Masks use the same rois as the box/cls head
        fpn.add_multilevel_roi_blobs(blobs,
                                     'mask_rois',
                                     blobs['rois'],
                                     lvls,
                                     lvl_min,
                                     lvl_max,
                                     valid_levels=blobs['roi_has_mask_int32'])

    if cfg.MODEL.KEYPOINTS_ON:
        # Keypoints use a separate set of training rois
        lvls = fpn.map_rois_to_fpn_levels(blobs['keypoint_rois'][:, 1:],
                                          lvl_min, lvl_max)
        fpn.add_multilevel_roi_blobs(blobs, 'keypoint_rois',
                                     blobs['keypoint_rois'], lvls, lvl_min,
                                     lvl_max)
Ejemplo n.º 4
0
    def distribute(self, rois, label_blobs, outputs, train):
        """To understand the output blob order see return value of
        roi_data.fast_rcnn.get_fast_rcnn_blob_names(is_training=False)
        """
        # Put all rois into rois without distribute
        outputs[0].reshape(rois.shape)
        outputs[0].data[...] = rois

        # Distribute rois into different level according to map method
        if not cfg.PAN.AdaptivePooling_ON:
            lvl_min = cfg.FPN.ROI_MIN_LEVEL
            lvl_max = cfg.FPN.ROI_MAX_LEVEL
            lvls = fpn.map_rois_to_fpn_levels(rois[:, 1:5], lvl_min, lvl_max)

            # Create new roi blobs for each FPN level
            # (See: modeling.FPN.add_multilevel_roi_blobs which is similar but annoying
            # to generalize to support this particular case.)
            rois_idx_order = np.empty((0, ))
            for output_idx, lvl in enumerate(range(lvl_min, lvl_max + 1)):
                idx_lvl = np.where(lvls == lvl)[0]
                blob_roi_level = rois[idx_lvl, :]
                outputs[output_idx + 1].reshape(blob_roi_level.shape)
                outputs[output_idx + 1].data[...] = blob_roi_level
                rois_idx_order = np.concatenate((rois_idx_order, idx_lvl))
            rois_idx_restore = np.argsort(rois_idx_order)
            blob_utils.py_op_copy_blob(rois_idx_restore.astype(np.int32),
                                       outputs[-1])
Ejemplo n.º 5
0
def _add_multilevel_rois_for_test(blobs, name):
    """Distributes a set of RoIs across FPN pyramid levels by creating new level
    specific RoI blobs.

    Arguments:
        blobs (dict): dictionary of blobs
        name (str): a key in 'blobs' identifying the source RoI blob

    Returns:
        [by ref] blobs (dict): new keys named by `name + 'fpn' + level`
            are added to dict each with a value that's an R_level x 5 ndarray of
            RoIs (see _get_rois_blob for format)
    """
    lvl_min = cfg.FPN.ROI_MIN_LEVEL
    lvl_max = cfg.FPN.ROI_MAX_LEVEL
    lvls = fpn.map_rois_to_fpn_levels(blobs[name][:, 1:], lvl_min, lvl_max)
    fpn.add_multilevel_roi_blobs(
        blobs, name, blobs[name], lvls, lvl_min, lvl_max)
Ejemplo n.º 6
0
def _add_multilevel_rois(blobs):
    """By default training RoIs are added for a single feature map level only.
    When using FPN, the RoIs must be distributed over different FPN levels
    according the level assignment heuristic (see: modeling.FPN.
    map_rois_to_fpn_levels).
    """
    lvl_min = cfg.FPN.ROI_MIN_LEVEL
    lvl_max = cfg.FPN.ROI_MAX_LEVEL
    rois_blob_name = 'mask_rois'
    """Distribute rois over the different FPN levels."""
    # Get target level for each roi
    # Recall blob rois are in (batch_idx, x1, y1, x2, y2) format, hence take
    # the box coordinates from columns 1:5
    target_lvls = fpn.map_rois_to_fpn_levels(blobs[rois_blob_name][:, 1:5],
                                             lvl_min, lvl_max)
    # Add per FPN level roi blobs named like: <rois_blob_name>_fpn<lvl>
    fpn.add_multilevel_roi_blobs(blobs, rois_blob_name, blobs[rois_blob_name],
                                 target_lvls, lvl_min, lvl_max)
Ejemplo n.º 7
0
def _add_multilevel_rois_for_test(blobs, name):
    """Distributes a set of RoIs across FPN pyramid levels by creating new level
    specific RoI blobs.

    Arguments:
        blobs (dict): dictionary of blobs
        name (str): a key in 'blobs' identifying the source RoI blob

    Returns:
        [by ref] blobs (dict): new keys named by `name + 'fpn' + level`
            are added to dict each with a value that's an R_level x 5 ndarray of
            RoIs (see _get_rois_blob for format)
    """
    lvl_min = cfg.FPN.ROI_MIN_LEVEL
    lvl_max = cfg.FPN.ROI_MAX_LEVEL
    lvls = fpn.map_rois_to_fpn_levels(blobs[name][:, 1:5], lvl_min, lvl_max)
    fpn.add_multilevel_roi_blobs(blobs, name, blobs[name], lvls, lvl_min,
                                 lvl_max)
Ejemplo n.º 8
0
def generic_rpn_outputs(dim_in, spatial_scale_in):
    """Add RPN outputs (objectness classification and bounding box regression)
    to an RPN model. Abstracts away the use of FPN.
    """
    if cfg.FPN.FPN_ON:
        # Delegate to the FPN module
        return FPN.fpn_rpn_outputs(dim_in, spatial_scale_in)
    else:
        # Not using FPN, add RPN to a single scale
        return single_scale_rpn_outputs(dim_in, spatial_scale_in)
Ejemplo n.º 9
0
def generic_rpn_outputs_panet(dim_in, spatial_scale_in):
    """Add RPN outputs (objectness classification and bounding box regression)
    to an RPN model. Abstracts away the use of FPN.
    """
    if cfg.FPN.FPN_ON:
        # Delegate to the FPN module
        return FPN.fpn_rpn_outputs(dim_in, spatial_scale_in)
    else:
        # Not using FPN, add RPN to a single scale
        return single_scale_rpn_outputs(dim_in, spatial_scale_in)
Ejemplo n.º 10
0
def add_generic_rpn_outputs(model, blob_in, dim_in, spatial_scale_in):
    """Add RPN outputs (objectness classification and bounding box regression)
    to an RPN model. Abstracts away the use of FPN.
    """
    loss_gradients = None
    if cfg.FPN.FPN_ON:
        # Delegate to the FPN module
        FPN.add_fpn_rpn_outputs(model, blob_in, dim_in, spatial_scale_in)
        if cfg.MODEL.FASTER_RCNN:
            # CollectAndDistributeFpnRpnProposals also labels proposals when in
            # training mode
            model.CollectAndDistributeFpnRpnProposals()
        if model.train:
            loss_gradients = FPN.add_fpn_rpn_losses(model)
    else:
        # Not using FPN, add RPN to a single scale
        add_single_scale_rpn_outputs(model, blob_in, dim_in, spatial_scale_in)
        if model.train:
            loss_gradients = add_single_scale_rpn_losses(model)
    return loss_gradients
Ejemplo n.º 11
0
def add_generic_rpn_outputs(model, blob_in, dim_in, spatial_scale_in):
    """Add RPN outputs (objectness classification and bounding box regression)
    to an RPN model. Abstracts away the use of FPN.
    """
    loss_gradients = None
    if cfg.FPN.FPN_ON:
        # Delegate to the FPN module
        FPN.add_fpn_rpn_outputs(model, blob_in, dim_in, spatial_scale_in)
        if cfg.MODEL.FASTER_RCNN:
            # CollectAndDistributeFpnRpnProposals also labels proposals when in
            # training mode
            model.CollectAndDistributeFpnRpnProposals()
        if model.train:
            loss_gradients = FPN.add_fpn_rpn_losses(model)
    else:
        # Not using FPN, add RPN to a single scale
        add_single_scale_rpn_outputs(model, blob_in, dim_in, spatial_scale_in)
        if model.train:
            loss_gradients = add_single_scale_rpn_losses(model)
    return loss_gradients
Ejemplo n.º 12
0
def _add_multilevel_rois(blobs):
    lvl_min = cfg.FPN.ROI_MIN_LEVEL
    lvl_max = cfg.FPN.ROI_MAX_LEVEL
    # The map_rois_to_fpn_levels and add_multilevel_roi_blobs functions are
    # shared among the 2D and 3D models.
    lvls = fpn.map_rois_to_fpn_levels(blobs['rois'][:, 1:], lvl_min, lvl_max)
    fpn.add_multilevel_roi_blobs(
        blobs, 'rois', blobs['rois'], lvls, lvl_min, lvl_max)

    if cfg.MODEL.MASK_ON:
        # Masks use the same rois as the box/cls head
        fpn.add_multilevel_roi_blobs(
            blobs, 'mask_rois', blobs['rois'], lvls, lvl_min, lvl_max,
            valid_levels=blobs['roi_has_mask_int32'])

    if cfg.MODEL.KEYPOINTS_ON:
        # Keypoints use a separate set of training rois
        lvls = fpn.map_rois_to_fpn_levels(
            blobs['keypoint_rois'][:, 1:], lvl_min, lvl_max)
        fpn.add_multilevel_roi_blobs(
            blobs, 'keypoint_rois', blobs['keypoint_rois'], lvls, lvl_min,
            lvl_max)
def distribute(rois, label_blobs, outputs, train):
    """To understand the output blob order see return value of
    roi_data.fast_rcnn.get_fast_rcnn_blob_names(is_training=False)
    """
    lvl_min = cfg.FPN.ROI_MIN_LEVEL
    lvl_max = cfg.FPN.ROI_MAX_LEVEL
    lvls = fpn.map_rois_to_fpn_levels(rois[:, 1:5], lvl_min, lvl_max)

    outputs[0].reshape(rois.shape)
    outputs[0].data[...] = rois

    # Create new roi blobs for each FPN level
    # (See: modeling.FPN.add_multilevel_roi_blobs which is similar but annoying
    # to generalize to support this particular case.)
    rois_idx_order = np.empty((0, ))
    for output_idx, lvl in enumerate(range(lvl_min, lvl_max + 1)):
        idx_lvl = np.where(lvls == lvl)[0]
        blob_roi_level = rois[idx_lvl, :]
        outputs[output_idx + 1].reshape(blob_roi_level.shape)
        outputs[output_idx + 1].data[...] = blob_roi_level
        rois_idx_order = np.concatenate((rois_idx_order, idx_lvl))
    rois_idx_restore = np.argsort(rois_idx_order)
    blob_utils.py_op_copy_blob(rois_idx_restore.astype(np.int32), outputs[-1])
Ejemplo n.º 14
0
    def _single_gpu_build_func(model):
        """Builds the model on a single GPU. Can be called in a loop over GPUs
        with name and device scoping to create a data parallel model."""
        # Some generic tensors
        model.ConstantFill([], 'zero', shape=[1], value=0)
        model.ConstantFill([], 'minus1', shape=[1], value=-1)

        blob, dim, spatial_scale = add_conv_body_func(model)
        if freeze_conv_body:
            model.StopGradient(blob, blob)
        if cfg.MODEL.VIDEO_ON:
            blob = time_pool_blobs(
                blob, model, cfg.VIDEO.BODY_HEAD_LINK)
        if not model.train:
            # Create a net that can be used to compute the conv body only on an
            # image (no RPN or heads / branches)
            model.conv_body_net = model.net.Clone('conv_body_net')
        if cfg.MODEL.VIDEO_ON and cfg.VIDEO.BODY_HEAD_LINK == '':
            FPN_lib = FPN3D
            head_3d = True
            out_time_dim = cfg.VIDEO.NUM_FRAMES_MID
        else:
            FPN_lib = FPN
            head_3d = False
            out_time_dim = 1
        if cfg.FPN.FPN_ON:
            FPN_lib.add_fpn_rpn_outputs(model, blob, dim, spatial_scale,
                                        time_dim=out_time_dim)
            if model.train:
                loss_gradients = FPN.add_fpn_rpn_losses(model)
        else:
            add_rpn_outputs(model, blob, dim, spatial_scale, nd=head_3d,
                            time_dim=out_time_dim)
            if model.train:
                loss_gradients = add_rpn_losses(model,
                                                time_dim=out_time_dim)
        return loss_gradients if model.train else None
Ejemplo n.º 15
0
def generic_rpn_losses(*inputs, **kwargs):
    """Add RPN losses. Abstracts away the use of FPN."""
    if cfg.FPN.FPN_ON:
        return FPN.fpn_rpn_losses(*inputs, **kwargs)
    else:
        return single_scale_rpn_losses(*inputs, **kwargs)
Ejemplo n.º 16
0
def generic_rpn_losses(*inputs, **kwargs):
    """Add RPN losses. Abstracts away the use of FPN."""
    if cfg.FPN.FPN_ON:
        return FPN.fpn_rpn_losses(*inputs, **kwargs)
    else:
        return single_scale_rpn_losses(*inputs, **kwargs)
Ejemplo n.º 17
0
    def _single_gpu_build_func(model):
        """Builds the model on a single GPU. Can be called in a loop over GPUs
        with name and device scoping to create a data parallel model."""
        # For training we define one net that contains all ops
        # For inference, we split the graph into two nets: a standard fast r-cnn
        # net and a mask prediction net; the mask net is only applied to a
        # subset of high-scoring detections
        is_inference = not model.train

        # Some generic tensors
        model.ConstantFill([], 'zero', shape=[1], value=0)
        model.ConstantFill([], 'minus1', shape=[1], value=-1)

        # Add the conv body
        blob_conv, dim_conv, spatial_scale_conv = add_conv_body_func(model)
        if freeze_conv_body:
            for b in blob_ref_to_list(blob_conv):
                model.StopGradient(b, b)

        # Convert from 3D blob to 2D, in case of videos to attach a 2D head
        # (not necessarily will happen though)
        if cfg.MODEL.VIDEO_ON:
            blob_conv = time_pool_blobs(
                blob_conv, model, cfg.VIDEO.BODY_HEAD_LINK)

        if is_inference:
            # Create a net that can be used to compute the conv body only on an
            # image (no RPN or heads / branches)
            model.conv_body_net = model.net.Clone('conv_body_net')

        # Select the FPN lib, based on whether the head is 3D or 2D
        if cfg.MODEL.VIDEO_ON and cfg.VIDEO.BODY_HEAD_LINK == '':
            FPN_lib = FPN3D
            head_3d = True
            out_time_dim = cfg.VIDEO.NUM_FRAMES_MID
        else:
            FPN_lib = FPN
            head_3d = False
            out_time_dim = 1

        # Add the RPN branch
        if cfg.MODEL.FASTER_RCNN:
            if cfg.FPN.FPN_ON:
                FPN_lib.add_fpn_rpn_outputs(
                    model, blob_conv, dim_conv, spatial_scale_conv,
                    time_dim=out_time_dim)
                model.CollectAndDistributeFpnRpnProposals()
            else:
                add_rpn_outputs(model, blob_conv, dim_conv, spatial_scale_conv,
                                nd=head_3d, time_dim=out_time_dim)

        if cfg.FPN.FPN_ON:
            # Code only supports case when RPN and ROI min levels are the same
            assert cfg.FPN.RPN_MIN_LEVEL == cfg.FPN.ROI_MIN_LEVEL
            # FPN RPN max level might be > FPN ROI max level in which case we
            # need to discard some leading conv blobs (blobs are ordered from
            # max level to min level)
            num_roi_levels = cfg.FPN.ROI_MAX_LEVEL - cfg.FPN.ROI_MIN_LEVEL + 1
            blob_conv = blob_conv[-num_roi_levels:]
            spatial_scale_conv = spatial_scale_conv[-num_roi_levels:]

        # Add the Fast R-CNN branch
        blob_frcn, dim_frcn, spatial_scale_frcn = add_roi_frcn_head_func(
            model, blob_conv, dim_conv, spatial_scale_conv)
        add_fast_rcnn_outputs(model, blob_frcn, dim_frcn, is_head_3d=head_3d)

        # Add the mask branch
        if cfg.MODEL.MASK_ON:
            if is_inference:
                bbox_net = copy.deepcopy(model.net.Proto())

            # Add the mask branch
            blob_mrcn, dim_mrcn, _ = add_roi_mask_head_func(
                model, blob_conv, dim_conv, spatial_scale_conv)
            blob_mask = add_mask_rcnn_outputs(model, blob_mrcn, dim_mrcn)

            if is_inference:
                # Extract the mask prediction net, store it as its own network,
                # then restore the primary net to the bbox-only network
                model.mask_net, blob_mask = get_suffix_net(
                    'mask_net', bbox_net.op, model.net, [blob_mask])
                model.net._net = bbox_net

        # Add the keypoint branch
        if cfg.MODEL.KEYPOINTS_ON:
            if is_inference:
                bbox_net = copy.deepcopy(model.net.Proto())

            blob_krcnn, dim_krcnn, _ = add_roi_keypoint_head_func(
                model, blob_conv, dim_conv, spatial_scale_conv)
            blob_keypoint = add_heatmap_outputs(
                model, blob_krcnn, dim_krcnn,
                time_dim=out_time_dim, is_head_3d=head_3d)

            if is_inference:
                model.keypoint_net, keypoint_blob_out = get_suffix_net(
                    'keypoint_net', bbox_net.op, model.net, [blob_keypoint])
                model.net._net = bbox_net

        if model.train:
            loss_gradients = add_fast_rcnn_losses(model, time_dim=out_time_dim)
            if cfg.MODEL.MASK_ON:
                loss_gradients.update(add_mask_rcnn_losses(model, blob_mask,
                                                           time_dim=out_time_dim))
            if cfg.MODEL.KEYPOINTS_ON:
                loss_gradients.update(add_heatmap_losses(model, time_dim=out_time_dim))
            if cfg.MODEL.FASTER_RCNN:
                if cfg.FPN.FPN_ON:
                    # The loss function is shared between 2D and 3D FPN
                    loss_gradients.update(FPN.add_fpn_rpn_losses(
                        model, time_dim=out_time_dim))
                    if cfg.VIDEO.PREDICT_RPN_BOX_VIS:
                        loss_gradients.update(FPN.add_fpn_rpn_vis_losses(
                            model, time_dim=out_time_dim))
                else:
                    loss_gradients.update(add_rpn_losses(
                        model, time_dim=out_time_dim))
                    if cfg.VIDEO.PREDICT_RPN_BOX_VIS:
                        loss_gradients.update(add_rpn_vis_losses(
                            model, time_dim=out_time_dim))
        return loss_gradients if model.train else None