Commit 78c43ef1 authored by Gunho Park's avatar Gunho Park
Browse files

Merge branch 'master' of https://github.com/tensorflow/models

parents 67cfc95b e3c7e300
"""Tests for google3.third_party.tensorflow_models.object_detection.models.keras_models.nonlocal_block."""
import unittest
from absl.testing import parameterized
import tensorflow as tf
from object_detection.models.keras_models import nonlocal_block
from object_detection.utils import test_case
from object_detection.utils import tf_version
@unittest.skipIf(tf_version.is_tf1(), 'Skipping TF2.X only test.')
class NonlocalTest(test_case.TestCase, parameterized.TestCase):
@parameterized.parameters([{'pool_size': None,
'add_coord_conv': False},
{'pool_size': None,
'add_coord_conv': True},
{'pool_size': 2,
'add_coord_conv': False},
{'pool_size': 2,
'add_coord_conv': True}])
def test_run_nonlocal_block(self, pool_size, add_coord_conv):
nonlocal_op = nonlocal_block.NonLocalBlock(
8, pool_size=pool_size, add_coord_conv=add_coord_conv)
def graph_fn():
inputs = tf.zeros((4, 16, 16, 32), dtype=tf.float32)
outputs = nonlocal_op(inputs)
return outputs
outputs = self.execute(graph_fn, [])
self.assertAllEqual([4, 16, 16, 32], outputs.shape)
if __name__ == '__main__':
tf.test.main()
...@@ -19,7 +19,7 @@ from __future__ import absolute_import ...@@ -19,7 +19,7 @@ from __future__ import absolute_import
from __future__ import division from __future__ import division
from __future__ import print_function from __future__ import print_function
from keras.applications import resnet from tensorflow.python.keras.applications import resnet
import tensorflow.compat.v1 as tf import tensorflow.compat.v1 as tf
......
...@@ -21,7 +21,11 @@ REQUIRED_PACKAGES = [ ...@@ -21,7 +21,11 @@ REQUIRED_PACKAGES = [
'lvis', 'lvis',
'scipy', 'scipy',
'pandas', 'pandas',
'tf-models-official' # tensorflow 2.5.0 requires grpcio~=1.34.0.
# tf-models-official (which requires google-could-bigquery) ends
# up installing the latest grpcio which causes problems later.
'google-cloud-bigquery==1.21.0',
'tf-models-official',
] ]
setup( setup(
......
...@@ -187,8 +187,9 @@ message CenterNet { ...@@ -187,8 +187,9 @@ message CenterNet {
// vicinity of each regressed keypoint. // vicinity of each regressed keypoint.
optional float candidate_search_scale = 15 [default = 0.3]; optional float candidate_search_scale = 15 [default = 0.3];
// One of ['min_distance', 'score_distance_ratio'] indicating how to select // One of ['min_distance', 'score_distance_ratio',
// the keypoint candidate. // 'score_scaled_distance_ratio', 'gaussian_weighted'] indicating how to
// select the keypoint candidate.
optional string candidate_ranking_mode = 16 [default = "min_distance"]; optional string candidate_ranking_mode = 16 [default = "min_distance"];
// The score distance ratio offset, only used if candidate_ranking_mode is // The score distance ratio offset, only used if candidate_ranking_mode is
...@@ -197,6 +198,28 @@ message CenterNet { ...@@ -197,6 +198,28 @@ message CenterNet {
// keypoint_score / (distance + score_distance_offset) // keypoint_score / (distance + score_distance_offset)
optional float score_distance_offset = 22 [default = 1.0]; optional float score_distance_offset = 22 [default = 1.0];
// A scalar used to multiply the bounding box size to be used as the offset
// in the score-to-distance-ratio formula. Only applicable when the
// candidate_ranking_mode is score_scaled_distance_ratio.
// The keypoint candidates are ranked using the formula:
// ranking_score = score / (distance + offset)
// where 'score' is the keypoint heatmap scores, 'distance' is the distance
// between the heatmap peak location and the regressed joint location,
// 'offset' is a function of the predicted bounding box:
// offset = max(bbox height, bbox width) * score_distance_multiplier
optional float score_distance_multiplier = 28 [default = 0.1];
// A scalar used to multiply the Gaussian standard deviation to control the
// Gaussian kernel which is used to weight the candidates. Only applicable
// when the candidate_ranking_mode is gaussian_weighted.
// The keypoint candidates are ranked using the formula:
// scores * exp((-distances^2) / (2 * sigma^2))
// where 'distances' is the distance between the heatmap peak location and
// the regressed joint location and 'sigma' is the Gaussian standard
// deviation used in generating the Gaussian heatmap target multiplied by the
// 'std_dev_multiplier'.
optional float std_dev_multiplier = 29 [default = 1.0];
// The radius (in the unit of output pixel) around heatmap peak to assign // The radius (in the unit of output pixel) around heatmap peak to assign
// the offset targets. If set 0, then the offset target will only be // the offset targets. If set 0, then the offset target will only be
// assigned to the heatmap peak (same behavior as the original paper). // assigned to the heatmap peak (same behavior as the original paper).
...@@ -238,6 +261,11 @@ message CenterNet { ...@@ -238,6 +261,11 @@ message CenterNet {
// the number of keypoints for that class. // the number of keypoints for that class.
optional bool rescore_instances = 24 [default = false]; optional bool rescore_instances = 24 [default = false];
// A scalar used when "rescore_instances" is set to True. The detection
// score of an instance is set to be the average score among those keypoints
// with scores higher than the threshold.
optional float rescoring_threshold = 30 [default = 0.0];
// Parameters to determine the architecture of the keypoint heatmap // Parameters to determine the architecture of the keypoint heatmap
// prediction head. // prediction head.
optional PredictionHeadParams heatmap_head_params = 25; optional PredictionHeadParams heatmap_head_params = 25;
...@@ -418,6 +446,10 @@ message CenterNet { ...@@ -418,6 +446,10 @@ message CenterNet {
// The mode for jitterting box ROIs. See RandomJitterBoxes in // The mode for jitterting box ROIs. See RandomJitterBoxes in
// preprocessor.proto for more details // preprocessor.proto for more details
optional RandomJitterBoxes.JitterMode jitter_mode = 15 [default=DEFAULT]; optional RandomJitterBoxes.JitterMode jitter_mode = 15 [default=DEFAULT];
// Weight for the box consistency loss as described in the BoxInst paper
// https://arxiv.org/abs/2012.02310
optional float box_consistency_loss_weight = 16 [default=0.0];
} }
optional DeepMACMaskEstimation deepmac_mask_estimation = 14; optional DeepMACMaskEstimation deepmac_mask_estimation = 14;
...@@ -466,3 +498,4 @@ message CenterNetFeatureExtractor { ...@@ -466,3 +498,4 @@ message CenterNetFeatureExtractor {
optional string upsampling_interpolation = 11 [default = 'nearest']; optional string upsampling_interpolation = 11 [default = 'nearest'];
} }
...@@ -639,6 +639,12 @@ def _maybe_update_config_with_key_value(configs, key, value): ...@@ -639,6 +639,12 @@ def _maybe_update_config_with_key_value(configs, key, value):
_update_rescore_instances(configs["model"], value) _update_rescore_instances(configs["model"], value)
elif field_name == "unmatched_keypoint_score": elif field_name == "unmatched_keypoint_score":
_update_unmatched_keypoint_score(configs["model"], value) _update_unmatched_keypoint_score(configs["model"], value)
elif field_name == "score_distance_multiplier":
_update_score_distance_multiplier(configs["model"], value)
elif field_name == "std_dev_multiplier":
_update_std_dev_multiplier(configs["model"], value)
elif field_name == "rescoring_threshold":
_update_rescoring_threshold(configs["model"], value)
else: else:
return False return False
return True return True
...@@ -1135,10 +1141,12 @@ def _update_candidate_search_scale(model_config, search_scale): ...@@ -1135,10 +1141,12 @@ def _update_candidate_search_scale(model_config, search_scale):
def _update_candidate_ranking_mode(model_config, mode): def _update_candidate_ranking_mode(model_config, mode):
"""Updates how keypoints are snapped to candidates in CenterNet.""" """Updates how keypoints are snapped to candidates in CenterNet."""
if mode not in ("min_distance", "score_distance_ratio"): if mode not in ("min_distance", "score_distance_ratio",
"score_scaled_distance_ratio", "gaussian_weighted"):
raise ValueError("Attempting to set the keypoint candidate ranking mode " raise ValueError("Attempting to set the keypoint candidate ranking mode "
"to {}, but the only options are 'min_distance' and " "to {}, but the only options are 'min_distance', "
"'score_distance_ratio'.".format(mode)) "'score_distance_ratio', 'score_scaled_distance_ratio', "
"'gaussian_weighted'.".format(mode))
meta_architecture = model_config.WhichOneof("model") meta_architecture = model_config.WhichOneof("model")
if meta_architecture == "center_net": if meta_architecture == "center_net":
if len(model_config.center_net.keypoint_estimation_task) == 1: if len(model_config.center_net.keypoint_estimation_task) == 1:
...@@ -1214,3 +1222,50 @@ def _update_unmatched_keypoint_score(model_config, score): ...@@ -1214,3 +1222,50 @@ def _update_unmatched_keypoint_score(model_config, score):
"unmatched_keypoint_score since there are multiple " "unmatched_keypoint_score since there are multiple "
"keypoint estimation tasks") "keypoint estimation tasks")
def _update_score_distance_multiplier(model_config, score_distance_multiplier):
"""Updates the keypoint candidate selection metric. See CenterNet proto."""
meta_architecture = model_config.WhichOneof("model")
if meta_architecture == "center_net":
if len(model_config.center_net.keypoint_estimation_task) == 1:
kpt_estimation_task = model_config.center_net.keypoint_estimation_task[0]
kpt_estimation_task.score_distance_multiplier = score_distance_multiplier
else:
tf.logging.warning("Ignoring config override key for "
"score_distance_multiplier since there are multiple "
"keypoint estimation tasks")
else:
raise ValueError(
"Unsupported meta_architecture type: %s" % meta_architecture)
def _update_std_dev_multiplier(model_config, std_dev_multiplier):
"""Updates the keypoint candidate selection metric. See CenterNet proto."""
meta_architecture = model_config.WhichOneof("model")
if meta_architecture == "center_net":
if len(model_config.center_net.keypoint_estimation_task) == 1:
kpt_estimation_task = model_config.center_net.keypoint_estimation_task[0]
kpt_estimation_task.std_dev_multiplier = std_dev_multiplier
else:
tf.logging.warning("Ignoring config override key for "
"std_dev_multiplier since there are multiple "
"keypoint estimation tasks")
else:
raise ValueError(
"Unsupported meta_architecture type: %s" % meta_architecture)
def _update_rescoring_threshold(model_config, rescoring_threshold):
"""Updates the keypoint candidate selection metric. See CenterNet proto."""
meta_architecture = model_config.WhichOneof("model")
if meta_architecture == "center_net":
if len(model_config.center_net.keypoint_estimation_task) == 1:
kpt_estimation_task = model_config.center_net.keypoint_estimation_task[0]
kpt_estimation_task.rescoring_threshold = rescoring_threshold
else:
tf.logging.warning("Ignoring config override key for "
"rescoring_threshold since there are multiple "
"keypoint estimation tasks")
else:
raise ValueError(
"Unsupported meta_architecture type: %s" % meta_architecture)
...@@ -70,7 +70,7 @@ def iou(boxes1, boxes2): ...@@ -70,7 +70,7 @@ def iou(boxes1, boxes2):
Args: Args:
boxes1: a numpy array with shape [N, 4] holding N boxes. boxes1: a numpy array with shape [N, 4] holding N boxes.
boxes2: a numpy array with shape [M, 4] holding N boxes. boxes2: a numpy array with shape [M, 4] holding M boxes.
Returns: Returns:
a numpy array with shape [N, M] representing pairwise iou scores. a numpy array with shape [N, M] representing pairwise iou scores.
...@@ -92,7 +92,7 @@ def ioa(boxes1, boxes2): ...@@ -92,7 +92,7 @@ def ioa(boxes1, boxes2):
Args: Args:
boxes1: a numpy array with shape [N, 4] holding N boxes. boxes1: a numpy array with shape [N, 4] holding N boxes.
boxes2: a numpy array with shape [M, 4] holding N boxes. boxes2: a numpy array with shape [M, 4] holding M boxes.
Returns: Returns:
a numpy array with shape [N, M] representing pairwise ioa scores. a numpy array with shape [N, M] representing pairwise ioa scores.
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
import tensorflow.compat.v1 as tf import tensorflow.compat.v1 as tf
from object_detection.core import box_list
from object_detection.core import box_list_ops
from object_detection.utils import shape_utils from object_detection.utils import shape_utils
...@@ -290,7 +292,8 @@ def get_valid_keypoint_mask_for_class(keypoint_coordinates, ...@@ -290,7 +292,8 @@ def get_valid_keypoint_mask_for_class(keypoint_coordinates,
def blackout_pixel_weights_by_box_regions(height, width, boxes, blackout, def blackout_pixel_weights_by_box_regions(height, width, boxes, blackout,
weights=None): weights=None,
boxes_scale=1.0):
"""Apply weights at pixel locations. """Apply weights at pixel locations.
This function is used to generate the pixel weight mask (usually in the output This function is used to generate the pixel weight mask (usually in the output
...@@ -332,6 +335,10 @@ def blackout_pixel_weights_by_box_regions(height, width, boxes, blackout, ...@@ -332,6 +335,10 @@ def blackout_pixel_weights_by_box_regions(height, width, boxes, blackout,
a value to apply in each box region. Note that if blackout=True for a a value to apply in each box region. Note that if blackout=True for a
given box, the weight will be zero. If None, all weights are assumed to be given box, the weight will be zero. If None, all weights are assumed to be
1. 1.
boxes_scale: The amount to scale the height/width of the boxes before
constructing the blackout regions. This is often useful to guarantee that
the proper weight fully covers the object boxes/masks during supervision,
as shifting might occur during image resizing, network stride, etc.
Returns: Returns:
A float tensor with shape [height, width] where all values within the A float tensor with shape [height, width] where all values within the
...@@ -347,6 +354,10 @@ def blackout_pixel_weights_by_box_regions(height, width, boxes, blackout, ...@@ -347,6 +354,10 @@ def blackout_pixel_weights_by_box_regions(height, width, boxes, blackout,
(y_grid, x_grid) = image_shape_to_grids(height, width) (y_grid, x_grid) = image_shape_to_grids(height, width)
y_grid = tf.expand_dims(y_grid, axis=0) y_grid = tf.expand_dims(y_grid, axis=0)
x_grid = tf.expand_dims(x_grid, axis=0) x_grid = tf.expand_dims(x_grid, axis=0)
boxlist = box_list.BoxList(boxes)
boxlist = box_list_ops.scale_height_width(
boxlist, y_scale=boxes_scale, x_scale=boxes_scale)
boxes = boxlist.get()
y_min = tf.expand_dims(boxes[:, 0:1], axis=-1) y_min = tf.expand_dims(boxes[:, 0:1], axis=-1)
x_min = tf.expand_dims(boxes[:, 1:2], axis=-1) x_min = tf.expand_dims(boxes[:, 1:2], axis=-1)
y_max = tf.expand_dims(boxes[:, 2:3], axis=-1) y_max = tf.expand_dims(boxes[:, 2:3], axis=-1)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment