|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Function to build box predictor from configuration.""" |
|
|
|
import collections |
|
import tensorflow as tf |
|
from object_detection.predictors import convolutional_box_predictor |
|
from object_detection.predictors import convolutional_keras_box_predictor |
|
from object_detection.predictors import mask_rcnn_box_predictor |
|
from object_detection.predictors import rfcn_box_predictor |
|
from object_detection.predictors.heads import box_head |
|
from object_detection.predictors.heads import class_head |
|
from object_detection.predictors.heads import keras_box_head |
|
from object_detection.predictors.heads import keras_class_head |
|
from object_detection.predictors.heads import mask_head |
|
from object_detection.protos import box_predictor_pb2 |
|
|
|
|
|
def build_convolutional_box_predictor(is_training, |
|
num_classes, |
|
conv_hyperparams_fn, |
|
min_depth, |
|
max_depth, |
|
num_layers_before_predictor, |
|
use_dropout, |
|
dropout_keep_prob, |
|
kernel_size, |
|
box_code_size, |
|
apply_sigmoid_to_scores=False, |
|
add_background_class=True, |
|
class_prediction_bias_init=0.0, |
|
use_depthwise=False,): |
|
"""Builds the ConvolutionalBoxPredictor from the arguments. |
|
|
|
Args: |
|
is_training: Indicates whether the BoxPredictor is in training mode. |
|
num_classes: number of classes. Note that num_classes *does not* |
|
include the background category, so if groundtruth labels take values |
|
in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the |
|
assigned classification targets can range from {0,... K}). |
|
conv_hyperparams_fn: A function to generate tf-slim arg_scope with |
|
hyperparameters for convolution ops. |
|
min_depth: Minimum feature depth prior to predicting box encodings |
|
and class predictions. |
|
max_depth: Maximum feature depth prior to predicting box encodings |
|
and class predictions. If max_depth is set to 0, no additional |
|
feature map will be inserted before location and class predictions. |
|
num_layers_before_predictor: Number of the additional conv layers before |
|
the predictor. |
|
use_dropout: Option to use dropout or not. Note that a single dropout |
|
op is applied here prior to both box and class predictions, which stands |
|
in contrast to the ConvolutionalBoxPredictor below. |
|
dropout_keep_prob: Keep probability for dropout. |
|
This is only used if use_dropout is True. |
|
kernel_size: Size of final convolution kernel. If the |
|
spatial resolution of the feature map is smaller than the kernel size, |
|
then the kernel size is automatically set to be |
|
min(feature_width, feature_height). |
|
box_code_size: Size of encoding for each box. |
|
apply_sigmoid_to_scores: If True, apply the sigmoid on the output |
|
class_predictions. |
|
add_background_class: Whether to add an implicit background class. |
|
class_prediction_bias_init: Constant value to initialize bias of the last |
|
conv2d layer before class prediction. |
|
use_depthwise: Whether to use depthwise convolutions for prediction |
|
steps. Default is False. |
|
|
|
Returns: |
|
A ConvolutionalBoxPredictor class. |
|
""" |
|
box_prediction_head = box_head.ConvolutionalBoxHead( |
|
is_training=is_training, |
|
box_code_size=box_code_size, |
|
kernel_size=kernel_size, |
|
use_depthwise=use_depthwise) |
|
class_prediction_head = class_head.ConvolutionalClassHead( |
|
is_training=is_training, |
|
num_class_slots=num_classes + 1 if add_background_class else num_classes, |
|
use_dropout=use_dropout, |
|
dropout_keep_prob=dropout_keep_prob, |
|
kernel_size=kernel_size, |
|
apply_sigmoid_to_scores=apply_sigmoid_to_scores, |
|
class_prediction_bias_init=class_prediction_bias_init, |
|
use_depthwise=use_depthwise) |
|
other_heads = {} |
|
return convolutional_box_predictor.ConvolutionalBoxPredictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
box_prediction_head=box_prediction_head, |
|
class_prediction_head=class_prediction_head, |
|
other_heads=other_heads, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
num_layers_before_predictor=num_layers_before_predictor, |
|
min_depth=min_depth, |
|
max_depth=max_depth) |
|
|
|
|
|
def build_convolutional_keras_box_predictor(is_training, |
|
num_classes, |
|
conv_hyperparams, |
|
freeze_batchnorm, |
|
inplace_batchnorm_update, |
|
num_predictions_per_location_list, |
|
min_depth, |
|
max_depth, |
|
num_layers_before_predictor, |
|
use_dropout, |
|
dropout_keep_prob, |
|
kernel_size, |
|
box_code_size, |
|
add_background_class=True, |
|
class_prediction_bias_init=0.0, |
|
use_depthwise=False, |
|
name='BoxPredictor'): |
|
"""Builds the Keras ConvolutionalBoxPredictor from the arguments. |
|
|
|
Args: |
|
is_training: Indicates whether the BoxPredictor is in training mode. |
|
num_classes: number of classes. Note that num_classes *does not* |
|
include the background category, so if groundtruth labels take values |
|
in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the |
|
assigned classification targets can range from {0,... K}). |
|
conv_hyperparams: A `hyperparams_builder.KerasLayerHyperparams` object |
|
containing hyperparameters for convolution ops. |
|
freeze_batchnorm: Whether to freeze batch norm parameters during |
|
training or not. When training with a small batch size (e.g. 1), it is |
|
desirable to freeze batch norm update and use pretrained batch norm |
|
params. |
|
inplace_batchnorm_update: Whether to update batch norm moving average |
|
values inplace. When this is false train op must add a control |
|
dependency on tf.graphkeys.UPDATE_OPS collection in order to update |
|
batch norm statistics. |
|
num_predictions_per_location_list: A list of integers representing the |
|
number of box predictions to be made per spatial location for each |
|
feature map. |
|
min_depth: Minimum feature depth prior to predicting box encodings |
|
and class predictions. |
|
max_depth: Maximum feature depth prior to predicting box encodings |
|
and class predictions. If max_depth is set to 0, no additional |
|
feature map will be inserted before location and class predictions. |
|
num_layers_before_predictor: Number of the additional conv layers before |
|
the predictor. |
|
use_dropout: Option to use dropout or not. Note that a single dropout |
|
op is applied here prior to both box and class predictions, which stands |
|
in contrast to the ConvolutionalBoxPredictor below. |
|
dropout_keep_prob: Keep probability for dropout. |
|
This is only used if use_dropout is True. |
|
kernel_size: Size of final convolution kernel. If the |
|
spatial resolution of the feature map is smaller than the kernel size, |
|
then the kernel size is automatically set to be |
|
min(feature_width, feature_height). |
|
box_code_size: Size of encoding for each box. |
|
add_background_class: Whether to add an implicit background class. |
|
class_prediction_bias_init: constant value to initialize bias of the last |
|
conv2d layer before class prediction. |
|
use_depthwise: Whether to use depthwise convolutions for prediction |
|
steps. Default is False. |
|
name: A string name scope to assign to the box predictor. If `None`, Keras |
|
will auto-generate one from the class name. |
|
|
|
Returns: |
|
A Keras ConvolutionalBoxPredictor class. |
|
""" |
|
box_prediction_heads = [] |
|
class_prediction_heads = [] |
|
other_heads = {} |
|
|
|
for stack_index, num_predictions_per_location in enumerate( |
|
num_predictions_per_location_list): |
|
box_prediction_heads.append( |
|
keras_box_head.ConvolutionalBoxHead( |
|
is_training=is_training, |
|
box_code_size=box_code_size, |
|
kernel_size=kernel_size, |
|
conv_hyperparams=conv_hyperparams, |
|
freeze_batchnorm=freeze_batchnorm, |
|
num_predictions_per_location=num_predictions_per_location, |
|
use_depthwise=use_depthwise, |
|
name='ConvolutionalBoxHead_%d' % stack_index)) |
|
class_prediction_heads.append( |
|
keras_class_head.ConvolutionalClassHead( |
|
is_training=is_training, |
|
num_class_slots=( |
|
num_classes + 1 if add_background_class else num_classes), |
|
use_dropout=use_dropout, |
|
dropout_keep_prob=dropout_keep_prob, |
|
kernel_size=kernel_size, |
|
conv_hyperparams=conv_hyperparams, |
|
freeze_batchnorm=freeze_batchnorm, |
|
num_predictions_per_location=num_predictions_per_location, |
|
class_prediction_bias_init=class_prediction_bias_init, |
|
use_depthwise=use_depthwise, |
|
name='ConvolutionalClassHead_%d' % stack_index)) |
|
|
|
return convolutional_keras_box_predictor.ConvolutionalBoxPredictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
box_prediction_heads=box_prediction_heads, |
|
class_prediction_heads=class_prediction_heads, |
|
other_heads=other_heads, |
|
conv_hyperparams=conv_hyperparams, |
|
num_layers_before_predictor=num_layers_before_predictor, |
|
min_depth=min_depth, |
|
max_depth=max_depth, |
|
freeze_batchnorm=freeze_batchnorm, |
|
inplace_batchnorm_update=inplace_batchnorm_update, |
|
name=name) |
|
|
|
|
|
def build_weight_shared_convolutional_box_predictor( |
|
is_training, |
|
num_classes, |
|
conv_hyperparams_fn, |
|
depth, |
|
num_layers_before_predictor, |
|
box_code_size, |
|
kernel_size=3, |
|
add_background_class=True, |
|
class_prediction_bias_init=0.0, |
|
use_dropout=False, |
|
dropout_keep_prob=0.8, |
|
share_prediction_tower=False, |
|
apply_batch_norm=True, |
|
use_depthwise=False, |
|
score_converter_fn=tf.identity, |
|
box_encodings_clip_range=None): |
|
"""Builds and returns a WeightSharedConvolutionalBoxPredictor class. |
|
|
|
Args: |
|
is_training: Indicates whether the BoxPredictor is in training mode. |
|
num_classes: number of classes. Note that num_classes *does not* |
|
include the background category, so if groundtruth labels take values |
|
in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the |
|
assigned classification targets can range from {0,... K}). |
|
conv_hyperparams_fn: A function to generate tf-slim arg_scope with |
|
hyperparameters for convolution ops. |
|
depth: depth of conv layers. |
|
num_layers_before_predictor: Number of the additional conv layers before |
|
the predictor. |
|
box_code_size: Size of encoding for each box. |
|
kernel_size: Size of final convolution kernel. |
|
add_background_class: Whether to add an implicit background class. |
|
class_prediction_bias_init: constant value to initialize bias of the last |
|
conv2d layer before class prediction. |
|
use_dropout: Whether to apply dropout to class prediction head. |
|
dropout_keep_prob: Probability of keeping activiations. |
|
share_prediction_tower: Whether to share the multi-layer tower between box |
|
prediction and class prediction heads. |
|
apply_batch_norm: Whether to apply batch normalization to conv layers in |
|
this predictor. |
|
use_depthwise: Whether to use depthwise separable conv2d instead of conv2d. |
|
score_converter_fn: Callable score converter to perform elementwise op on |
|
class scores. |
|
box_encodings_clip_range: Min and max values for clipping the box_encodings. |
|
|
|
Returns: |
|
A WeightSharedConvolutionalBoxPredictor class. |
|
""" |
|
box_prediction_head = box_head.WeightSharedConvolutionalBoxHead( |
|
box_code_size=box_code_size, |
|
kernel_size=kernel_size, |
|
use_depthwise=use_depthwise, |
|
box_encodings_clip_range=box_encodings_clip_range) |
|
class_prediction_head = ( |
|
class_head.WeightSharedConvolutionalClassHead( |
|
num_class_slots=( |
|
num_classes + 1 if add_background_class else num_classes), |
|
kernel_size=kernel_size, |
|
class_prediction_bias_init=class_prediction_bias_init, |
|
use_dropout=use_dropout, |
|
dropout_keep_prob=dropout_keep_prob, |
|
use_depthwise=use_depthwise, |
|
score_converter_fn=score_converter_fn)) |
|
other_heads = {} |
|
return convolutional_box_predictor.WeightSharedConvolutionalBoxPredictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
box_prediction_head=box_prediction_head, |
|
class_prediction_head=class_prediction_head, |
|
other_heads=other_heads, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
depth=depth, |
|
num_layers_before_predictor=num_layers_before_predictor, |
|
kernel_size=kernel_size, |
|
apply_batch_norm=apply_batch_norm, |
|
share_prediction_tower=share_prediction_tower, |
|
use_depthwise=use_depthwise) |
|
|
|
|
|
def build_mask_rcnn_box_predictor(is_training, |
|
num_classes, |
|
fc_hyperparams_fn, |
|
use_dropout, |
|
dropout_keep_prob, |
|
box_code_size, |
|
add_background_class=True, |
|
share_box_across_classes=False, |
|
predict_instance_masks=False, |
|
conv_hyperparams_fn=None, |
|
mask_height=14, |
|
mask_width=14, |
|
mask_prediction_num_conv_layers=2, |
|
mask_prediction_conv_depth=256, |
|
masks_are_class_agnostic=False, |
|
convolve_then_upsample_masks=False): |
|
"""Builds and returns a MaskRCNNBoxPredictor class. |
|
|
|
Args: |
|
is_training: Indicates whether the BoxPredictor is in training mode. |
|
num_classes: number of classes. Note that num_classes *does not* |
|
include the background category, so if groundtruth labels take values |
|
in {0, 1, .., K-1}, num_classes=K (and not K+1, even though the |
|
assigned classification targets can range from {0,... K}). |
|
fc_hyperparams_fn: A function to generate tf-slim arg_scope with |
|
hyperparameters for fully connected ops. |
|
use_dropout: Option to use dropout or not. Note that a single dropout |
|
op is applied here prior to both box and class predictions, which stands |
|
in contrast to the ConvolutionalBoxPredictor below. |
|
dropout_keep_prob: Keep probability for dropout. |
|
This is only used if use_dropout is True. |
|
box_code_size: Size of encoding for each box. |
|
add_background_class: Whether to add an implicit background class. |
|
share_box_across_classes: Whether to share boxes across classes rather |
|
than use a different box for each class. |
|
predict_instance_masks: If True, will add a third stage mask prediction |
|
to the returned class. |
|
conv_hyperparams_fn: A function to generate tf-slim arg_scope with |
|
hyperparameters for convolution ops. |
|
mask_height: Desired output mask height. The default value is 14. |
|
mask_width: Desired output mask width. The default value is 14. |
|
mask_prediction_num_conv_layers: Number of convolution layers applied to |
|
the image_features in mask prediction branch. |
|
mask_prediction_conv_depth: The depth for the first conv2d_transpose op |
|
applied to the image_features in the mask prediction branch. If set |
|
to 0, the depth of the convolution layers will be automatically chosen |
|
based on the number of object classes and the number of channels in the |
|
image features. |
|
masks_are_class_agnostic: Boolean determining if the mask-head is |
|
class-agnostic or not. |
|
convolve_then_upsample_masks: Whether to apply convolutions on mask |
|
features before upsampling using nearest neighbor resizing. Otherwise, |
|
mask features are resized to [`mask_height`, `mask_width`] using |
|
bilinear resizing before applying convolutions. |
|
|
|
Returns: |
|
A MaskRCNNBoxPredictor class. |
|
""" |
|
box_prediction_head = box_head.MaskRCNNBoxHead( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
fc_hyperparams_fn=fc_hyperparams_fn, |
|
use_dropout=use_dropout, |
|
dropout_keep_prob=dropout_keep_prob, |
|
box_code_size=box_code_size, |
|
share_box_across_classes=share_box_across_classes) |
|
class_prediction_head = class_head.MaskRCNNClassHead( |
|
is_training=is_training, |
|
num_class_slots=num_classes + 1 if add_background_class else num_classes, |
|
fc_hyperparams_fn=fc_hyperparams_fn, |
|
use_dropout=use_dropout, |
|
dropout_keep_prob=dropout_keep_prob) |
|
third_stage_heads = {} |
|
if predict_instance_masks: |
|
third_stage_heads[ |
|
mask_rcnn_box_predictor. |
|
MASK_PREDICTIONS] = mask_head.MaskRCNNMaskHead( |
|
num_classes=num_classes, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
mask_height=mask_height, |
|
mask_width=mask_width, |
|
mask_prediction_num_conv_layers=mask_prediction_num_conv_layers, |
|
mask_prediction_conv_depth=mask_prediction_conv_depth, |
|
masks_are_class_agnostic=masks_are_class_agnostic, |
|
convolve_then_upsample=convolve_then_upsample_masks) |
|
return mask_rcnn_box_predictor.MaskRCNNBoxPredictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
box_prediction_head=box_prediction_head, |
|
class_prediction_head=class_prediction_head, |
|
third_stage_heads=third_stage_heads) |
|
|
|
|
|
def build_score_converter(score_converter_config, is_training): |
|
"""Builds score converter based on the config. |
|
|
|
Builds one of [tf.identity, tf.sigmoid] score converters based on the config |
|
and whether the BoxPredictor is for training or inference. |
|
|
|
Args: |
|
score_converter_config: |
|
box_predictor_pb2.WeightSharedConvolutionalBoxPredictor.score_converter. |
|
is_training: Indicates whether the BoxPredictor is in training mode. |
|
|
|
Returns: |
|
Callable score converter op. |
|
|
|
Raises: |
|
ValueError: On unknown score converter. |
|
""" |
|
if score_converter_config == ( |
|
box_predictor_pb2.WeightSharedConvolutionalBoxPredictor.IDENTITY): |
|
return tf.identity |
|
if score_converter_config == ( |
|
box_predictor_pb2.WeightSharedConvolutionalBoxPredictor.SIGMOID): |
|
return tf.identity if is_training else tf.sigmoid |
|
raise ValueError('Unknown score converter.') |
|
|
|
|
|
BoxEncodingsClipRange = collections.namedtuple('BoxEncodingsClipRange', |
|
['min', 'max']) |
|
|
|
|
|
def build(argscope_fn, box_predictor_config, is_training, num_classes, |
|
add_background_class=True): |
|
"""Builds box predictor based on the configuration. |
|
|
|
Builds box predictor based on the configuration. See box_predictor.proto for |
|
configurable options. Also, see box_predictor.py for more details. |
|
|
|
Args: |
|
argscope_fn: A function that takes the following inputs: |
|
* hyperparams_pb2.Hyperparams proto |
|
* a boolean indicating if the model is in training mode. |
|
and returns a tf slim argscope for Conv and FC hyperparameters. |
|
box_predictor_config: box_predictor_pb2.BoxPredictor proto containing |
|
configuration. |
|
is_training: Whether the models is in training mode. |
|
num_classes: Number of classes to predict. |
|
add_background_class: Whether to add an implicit background class. |
|
|
|
Returns: |
|
box_predictor: box_predictor.BoxPredictor object. |
|
|
|
Raises: |
|
ValueError: On unknown box predictor. |
|
""" |
|
if not isinstance(box_predictor_config, box_predictor_pb2.BoxPredictor): |
|
raise ValueError('box_predictor_config not of type ' |
|
'box_predictor_pb2.BoxPredictor.') |
|
|
|
box_predictor_oneof = box_predictor_config.WhichOneof('box_predictor_oneof') |
|
|
|
if box_predictor_oneof == 'convolutional_box_predictor': |
|
config_box_predictor = box_predictor_config.convolutional_box_predictor |
|
conv_hyperparams_fn = argscope_fn(config_box_predictor.conv_hyperparams, |
|
is_training) |
|
return build_convolutional_box_predictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
add_background_class=add_background_class, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
use_dropout=config_box_predictor.use_dropout, |
|
dropout_keep_prob=config_box_predictor.dropout_keep_probability, |
|
box_code_size=config_box_predictor.box_code_size, |
|
kernel_size=config_box_predictor.kernel_size, |
|
num_layers_before_predictor=( |
|
config_box_predictor.num_layers_before_predictor), |
|
min_depth=config_box_predictor.min_depth, |
|
max_depth=config_box_predictor.max_depth, |
|
apply_sigmoid_to_scores=config_box_predictor.apply_sigmoid_to_scores, |
|
class_prediction_bias_init=( |
|
config_box_predictor.class_prediction_bias_init), |
|
use_depthwise=config_box_predictor.use_depthwise) |
|
|
|
if box_predictor_oneof == 'weight_shared_convolutional_box_predictor': |
|
config_box_predictor = ( |
|
box_predictor_config.weight_shared_convolutional_box_predictor) |
|
conv_hyperparams_fn = argscope_fn(config_box_predictor.conv_hyperparams, |
|
is_training) |
|
apply_batch_norm = config_box_predictor.conv_hyperparams.HasField( |
|
'batch_norm') |
|
|
|
|
|
score_converter_fn = build_score_converter( |
|
config_box_predictor.score_converter, is_training) |
|
|
|
|
|
box_encodings_clip_range = ( |
|
BoxEncodingsClipRange( |
|
min=config_box_predictor.box_encodings_clip_range.min, |
|
max=config_box_predictor.box_encodings_clip_range.max) |
|
if config_box_predictor.HasField('box_encodings_clip_range') else None) |
|
|
|
return build_weight_shared_convolutional_box_predictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
add_background_class=add_background_class, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
depth=config_box_predictor.depth, |
|
num_layers_before_predictor=( |
|
config_box_predictor.num_layers_before_predictor), |
|
box_code_size=config_box_predictor.box_code_size, |
|
kernel_size=config_box_predictor.kernel_size, |
|
class_prediction_bias_init=( |
|
config_box_predictor.class_prediction_bias_init), |
|
use_dropout=config_box_predictor.use_dropout, |
|
dropout_keep_prob=config_box_predictor.dropout_keep_probability, |
|
share_prediction_tower=config_box_predictor.share_prediction_tower, |
|
apply_batch_norm=apply_batch_norm, |
|
use_depthwise=config_box_predictor.use_depthwise, |
|
score_converter_fn=score_converter_fn, |
|
box_encodings_clip_range=box_encodings_clip_range) |
|
|
|
if box_predictor_oneof == 'mask_rcnn_box_predictor': |
|
config_box_predictor = box_predictor_config.mask_rcnn_box_predictor |
|
fc_hyperparams_fn = argscope_fn(config_box_predictor.fc_hyperparams, |
|
is_training) |
|
conv_hyperparams_fn = None |
|
if config_box_predictor.HasField('conv_hyperparams'): |
|
conv_hyperparams_fn = argscope_fn( |
|
config_box_predictor.conv_hyperparams, is_training) |
|
return build_mask_rcnn_box_predictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
add_background_class=add_background_class, |
|
fc_hyperparams_fn=fc_hyperparams_fn, |
|
use_dropout=config_box_predictor.use_dropout, |
|
dropout_keep_prob=config_box_predictor.dropout_keep_probability, |
|
box_code_size=config_box_predictor.box_code_size, |
|
share_box_across_classes=( |
|
config_box_predictor.share_box_across_classes), |
|
predict_instance_masks=config_box_predictor.predict_instance_masks, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
mask_height=config_box_predictor.mask_height, |
|
mask_width=config_box_predictor.mask_width, |
|
mask_prediction_num_conv_layers=( |
|
config_box_predictor.mask_prediction_num_conv_layers), |
|
mask_prediction_conv_depth=( |
|
config_box_predictor.mask_prediction_conv_depth), |
|
masks_are_class_agnostic=( |
|
config_box_predictor.masks_are_class_agnostic), |
|
convolve_then_upsample_masks=( |
|
config_box_predictor.convolve_then_upsample_masks)) |
|
|
|
if box_predictor_oneof == 'rfcn_box_predictor': |
|
config_box_predictor = box_predictor_config.rfcn_box_predictor |
|
conv_hyperparams_fn = argscope_fn(config_box_predictor.conv_hyperparams, |
|
is_training) |
|
box_predictor_object = rfcn_box_predictor.RfcnBoxPredictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
conv_hyperparams_fn=conv_hyperparams_fn, |
|
crop_size=[config_box_predictor.crop_height, |
|
config_box_predictor.crop_width], |
|
num_spatial_bins=[config_box_predictor.num_spatial_bins_height, |
|
config_box_predictor.num_spatial_bins_width], |
|
depth=config_box_predictor.depth, |
|
box_code_size=config_box_predictor.box_code_size) |
|
return box_predictor_object |
|
raise ValueError('Unknown box predictor: {}'.format(box_predictor_oneof)) |
|
|
|
|
|
def build_keras(conv_hyperparams_fn, freeze_batchnorm, inplace_batchnorm_update, |
|
num_predictions_per_location_list, box_predictor_config, |
|
is_training, num_classes, add_background_class=True): |
|
"""Builds a Keras-based box predictor based on the configuration. |
|
|
|
Builds Keras-based box predictor based on the configuration. |
|
See box_predictor.proto for configurable options. Also, see box_predictor.py |
|
for more details. |
|
|
|
Args: |
|
conv_hyperparams_fn: A function that takes a hyperparams_pb2.Hyperparams |
|
proto and returns a `hyperparams_builder.KerasLayerHyperparams` |
|
for Conv or FC hyperparameters. |
|
freeze_batchnorm: Whether to freeze batch norm parameters during |
|
training or not. When training with a small batch size (e.g. 1), it is |
|
desirable to freeze batch norm update and use pretrained batch norm |
|
params. |
|
inplace_batchnorm_update: Whether to update batch norm moving average |
|
values inplace. When this is false train op must add a control |
|
dependency on tf.graphkeys.UPDATE_OPS collection in order to update |
|
batch norm statistics. |
|
num_predictions_per_location_list: A list of integers representing the |
|
number of box predictions to be made per spatial location for each |
|
feature map. |
|
box_predictor_config: box_predictor_pb2.BoxPredictor proto containing |
|
configuration. |
|
is_training: Whether the models is in training mode. |
|
num_classes: Number of classes to predict. |
|
add_background_class: Whether to add an implicit background class. |
|
|
|
Returns: |
|
box_predictor: box_predictor.KerasBoxPredictor object. |
|
|
|
Raises: |
|
ValueError: On unknown box predictor, or one with no Keras box predictor. |
|
""" |
|
if not isinstance(box_predictor_config, box_predictor_pb2.BoxPredictor): |
|
raise ValueError('box_predictor_config not of type ' |
|
'box_predictor_pb2.BoxPredictor.') |
|
|
|
box_predictor_oneof = box_predictor_config.WhichOneof('box_predictor_oneof') |
|
|
|
if box_predictor_oneof == 'convolutional_box_predictor': |
|
config_box_predictor = box_predictor_config.convolutional_box_predictor |
|
conv_hyperparams = conv_hyperparams_fn( |
|
config_box_predictor.conv_hyperparams) |
|
return build_convolutional_keras_box_predictor( |
|
is_training=is_training, |
|
num_classes=num_classes, |
|
add_background_class=add_background_class, |
|
conv_hyperparams=conv_hyperparams, |
|
freeze_batchnorm=freeze_batchnorm, |
|
inplace_batchnorm_update=inplace_batchnorm_update, |
|
num_predictions_per_location_list=num_predictions_per_location_list, |
|
use_dropout=config_box_predictor.use_dropout, |
|
dropout_keep_prob=config_box_predictor.dropout_keep_probability, |
|
box_code_size=config_box_predictor.box_code_size, |
|
kernel_size=config_box_predictor.kernel_size, |
|
num_layers_before_predictor=( |
|
config_box_predictor.num_layers_before_predictor), |
|
min_depth=config_box_predictor.min_depth, |
|
max_depth=config_box_predictor.max_depth, |
|
class_prediction_bias_init=( |
|
config_box_predictor.class_prediction_bias_init), |
|
use_depthwise=config_box_predictor.use_depthwise) |
|
|
|
raise ValueError( |
|
'Unknown box predictor for Keras: {}'.format(box_predictor_oneof)) |
|
|