Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ModelZoo
ResNet50_tensorflow
Commits
b0ccdb11
Commit
b0ccdb11
authored
Sep 28, 2020
by
Shixin Luo
Browse files
resolve conflict with master
parents
e61588cd
1611a8c5
Changes
210
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
180 additions
and
1440 deletions
+180
-1440
official/vision/beta/modeling/backbones/revnet.py
official/vision/beta/modeling/backbones/revnet.py
+24
-1
official/vision/beta/modeling/backbones/revnet_test.py
official/vision/beta/modeling/backbones/revnet_test.py
+4
-4
official/vision/beta/modeling/backbones/spinenet.py
official/vision/beta/modeling/backbones/spinenet.py
+37
-3
official/vision/beta/modeling/backbones/spinenet_test.py
official/vision/beta/modeling/backbones/spinenet_test.py
+2
-2
official/vision/beta/modeling/decoders/fpn.py
official/vision/beta/modeling/decoders/fpn.py
+14
-14
official/vision/beta/modeling/decoders/fpn_test.py
official/vision/beta/modeling/decoders/fpn_test.py
+2
-2
official/vision/beta/modeling/factory.py
official/vision/beta/modeling/factory.py
+5
-5
official/vision/beta/modeling/heads/dense_prediction_heads.py
...cial/vision/beta/modeling/heads/dense_prediction_heads.py
+9
-9
official/vision/beta/modeling/heads/dense_prediction_heads_test.py
...vision/beta/modeling/heads/dense_prediction_heads_test.py
+12
-12
official/vision/beta/modeling/layers/box_matcher_test.py
official/vision/beta/modeling/layers/box_matcher_test.py
+0
-109
official/vision/beta/modeling/layers/detection_generator.py
official/vision/beta/modeling/layers/detection_generator.py
+8
-7
official/vision/beta/modeling/layers/detection_generator_test.py
...l/vision/beta/modeling/layers/detection_generator_test.py
+15
-12
official/vision/beta/modeling/layers/mask_sampler_test.py
official/vision/beta/modeling/layers/mask_sampler_test.py
+0
-137
official/vision/beta/modeling/layers/roi_generator.py
official/vision/beta/modeling/layers/roi_generator.py
+1
-1
official/vision/beta/modeling/layers/roi_generator_test.py
official/vision/beta/modeling/layers/roi_generator_test.py
+0
-210
official/vision/beta/modeling/retinanet_model.py
official/vision/beta/modeling/retinanet_model.py
+3
-3
official/vision/beta/modeling/retinanet_model_test.py
official/vision/beta/modeling/retinanet_model_test.py
+5
-4
official/vision/beta/ops/anchor.py
official/vision/beta/ops/anchor.py
+37
-44
official/vision/beta/ops/anchor_test.py
official/vision/beta/ops/anchor_test.py
+2
-2
official/vision/beta/ops/box_ops_test.py
official/vision/beta/ops/box_ops_test.py
+0
-859
No files found.
official/vision/beta/modeling/backbones/revnet.py
View file @
b0ccdb11
...
...
@@ -24,6 +24,7 @@ from typing import Any, Callable, Dict, Optional
# Import libraries
import
tensorflow
as
tf
from
official.modeling
import
tf_utils
from
official.vision.beta.modeling.backbones
import
factory
from
official.vision.beta.modeling.layers
import
nn_blocks
...
...
@@ -130,7 +131,7 @@ class RevNet(tf.keras.Model):
block_repeats
=
spec
[
2
],
batch_norm_first
=
(
i
!=
0
),
# Only skip on first block
name
=
'revblock_group_{}'
.
format
(
i
+
2
))
endpoints
[
i
+
2
]
=
x
endpoints
[
str
(
i
+
2
)
]
=
x
self
.
_output_specs
=
{
l
:
endpoints
[
l
].
get_shape
()
for
l
in
endpoints
}
...
...
@@ -202,3 +203,25 @@ class RevNet(tf.keras.Model):
def
output_specs
(
self
)
->
Dict
[
int
,
tf
.
TensorShape
]:
"""A dict of {level: TensorShape} pairs for the model output."""
return
self
.
_output_specs
@
factory
.
register_backbone_builder
(
'revnet'
)
def
build_revnet
(
input_specs
:
tf
.
keras
.
layers
.
InputSpec
,
model_config
,
l2_regularizer
:
tf
.
keras
.
regularizers
.
Regularizer
=
None
)
->
tf
.
keras
.
Model
:
"""Builds ResNet 3d backbone from a config."""
backbone_type
=
model_config
.
backbone
.
type
backbone_cfg
=
model_config
.
backbone
.
get
()
norm_activation_config
=
model_config
.
norm_activation
assert
backbone_type
==
'revnet'
,
(
f
'Inconsistent backbone type '
f
'
{
backbone_type
}
'
)
return
RevNet
(
model_id
=
backbone_cfg
.
model_id
,
input_specs
=
input_specs
,
activation
=
norm_activation_config
.
activation
,
use_sync_bn
=
norm_activation_config
.
use_sync_bn
,
norm_momentum
=
norm_activation_config
.
norm_momentum
,
norm_epsilon
=
norm_activation_config
.
norm_epsilon
,
kernel_regularizer
=
l2_regularizer
)
official/vision/beta/modeling/backbones/revnet_test.py
View file @
b0ccdb11
...
...
@@ -40,16 +40,16 @@ class RevNetTest(parameterized.TestCase, tf.test.TestCase):
self
.
assertAllEqual
(
[
1
,
input_size
/
2
**
2
,
input_size
/
2
**
2
,
128
*
endpoint_filter_scale
],
endpoints
[
2
].
shape
.
as_list
())
endpoints
[
'2'
].
shape
.
as_list
())
self
.
assertAllEqual
(
[
1
,
input_size
/
2
**
3
,
input_size
/
2
**
3
,
256
*
endpoint_filter_scale
],
endpoints
[
3
].
shape
.
as_list
())
endpoints
[
'3'
].
shape
.
as_list
())
self
.
assertAllEqual
(
[
1
,
input_size
/
2
**
4
,
input_size
/
2
**
4
,
512
*
endpoint_filter_scale
],
endpoints
[
4
].
shape
.
as_list
())
endpoints
[
'4'
].
shape
.
as_list
())
self
.
assertAllEqual
(
[
1
,
input_size
/
2
**
5
,
input_size
/
2
**
5
,
832
*
endpoint_filter_scale
],
endpoints
[
5
].
shape
.
as_list
())
endpoints
[
'5'
].
shape
.
as_list
())
@
parameterized
.
parameters
(
1
,
3
,
4
)
def
test_input_specs
(
self
,
input_dim
):
...
...
official/vision/beta/modeling/backbones/spinenet.py
View file @
b0ccdb11
...
...
@@ -25,6 +25,7 @@ import math
from
absl
import
logging
import
tensorflow
as
tf
from
official.modeling
import
tf_utils
from
official.vision.beta.modeling.backbones
import
factory
from
official.vision.beta.modeling.layers
import
nn_blocks
from
official.vision.beta.ops
import
spatial_transform_ops
...
...
@@ -349,7 +350,7 @@ class SpineNet(tf.keras.Model):
block_spec
.
level
>
self
.
_max_level
):
raise
ValueError
(
'Output level is out of range [{}, {}]'
.
format
(
self
.
_min_level
,
self
.
_max_level
))
endpoints
[
block_spec
.
level
]
=
x
endpoints
[
str
(
block_spec
.
level
)
]
=
x
return
endpoints
...
...
@@ -365,14 +366,14 @@ class SpineNet(tf.keras.Model):
kernel_initializer
=
self
.
_kernel_initializer
,
kernel_regularizer
=
self
.
_kernel_regularizer
,
bias_regularizer
=
self
.
_bias_regularizer
)(
net
[
level
])
net
[
str
(
level
)
])
x
=
self
.
_norm
(
axis
=
self
.
_bn_axis
,
momentum
=
self
.
_norm_momentum
,
epsilon
=
self
.
_norm_epsilon
)(
x
)
x
=
tf_utils
.
get_activation
(
self
.
_activation_fn
)(
x
)
endpoints
[
level
]
=
x
endpoints
[
str
(
level
)
]
=
x
return
endpoints
def
_resample_with_alpha
(
self
,
...
...
@@ -476,3 +477,36 @@ class SpineNet(tf.keras.Model):
def
output_specs
(
self
):
"""A dict of {level: TensorShape} pairs for the model output."""
return
self
.
_output_specs
@
factory
.
register_backbone_builder
(
'spinenet'
)
def
build_spinenet
(
input_specs
:
tf
.
keras
.
layers
.
InputSpec
,
model_config
,
l2_regularizer
:
tf
.
keras
.
regularizers
.
Regularizer
=
None
)
->
tf
.
keras
.
Model
:
"""Builds ResNet 3d backbone from a config."""
backbone_type
=
model_config
.
backbone
.
type
backbone_cfg
=
model_config
.
backbone
.
get
()
norm_activation_config
=
model_config
.
norm_activation
assert
backbone_type
==
'spinenet'
,
(
f
'Inconsistent backbone type '
f
'
{
backbone_type
}
'
)
model_id
=
backbone_cfg
.
model_id
if
model_id
not
in
SCALING_MAP
:
raise
ValueError
(
'SpineNet-{} is not a valid architecture.'
.
format
(
model_id
))
scaling_params
=
SCALING_MAP
[
model_id
]
return
SpineNet
(
input_specs
=
input_specs
,
min_level
=
model_config
.
min_level
,
max_level
=
model_config
.
max_level
,
endpoints_num_filters
=
scaling_params
[
'endpoints_num_filters'
],
resample_alpha
=
scaling_params
[
'resample_alpha'
],
block_repeats
=
scaling_params
[
'block_repeats'
],
filter_size_scale
=
scaling_params
[
'filter_size_scale'
],
kernel_regularizer
=
l2_regularizer
,
activation
=
norm_activation_config
.
activation
,
use_sync_bn
=
norm_activation_config
.
use_sync_bn
,
norm_momentum
=
norm_activation_config
.
norm_momentum
,
norm_epsilon
=
norm_activation_config
.
norm_epsilon
)
official/vision/beta/modeling/backbones/spinenet_test.py
View file @
b0ccdb11
...
...
@@ -54,10 +54,10 @@ class SpineNetTest(parameterized.TestCase, tf.test.TestCase):
endpoints
=
model
(
inputs
)
for
l
in
range
(
min_level
,
max_level
+
1
):
self
.
assertIn
(
l
,
endpoints
.
keys
())
self
.
assertIn
(
str
(
l
)
,
endpoints
.
keys
())
self
.
assertAllEqual
(
[
1
,
input_size
/
2
**
l
,
input_size
/
2
**
l
,
endpoints_num_filters
],
endpoints
[
l
].
shape
.
as_list
())
endpoints
[
str
(
l
)
].
shape
.
as_list
())
def
test_serialize_deserialize
(
self
):
# Create a network object that sets all of its config options.
...
...
official/vision/beta/modeling/decoders/fpn.py
View file @
b0ccdb11
...
...
@@ -98,30 +98,30 @@ class FPN(tf.keras.Model):
# Get input feature pyramid from backbone.
inputs
=
self
.
_build_input_pyramid
(
input_specs
,
min_level
)
backbone_max_level
=
min
(
max
(
inputs
.
keys
()),
max_level
)
backbone_max_level
=
min
(
int
(
max
(
inputs
.
keys
())
)
,
max_level
)
# Build lateral connections.
feats_lateral
=
{}
for
level
in
range
(
min_level
,
backbone_max_level
+
1
):
feats_lateral
[
level
]
=
conv2d
(
feats_lateral
[
str
(
level
)
]
=
conv2d
(
filters
=
num_filters
,
kernel_size
=
1
,
padding
=
'same'
,
kernel_initializer
=
kernel_initializer
,
kernel_regularizer
=
kernel_regularizer
,
bias_regularizer
=
bias_regularizer
)(
inputs
[
level
])
inputs
[
str
(
level
)
])
# Build top-down path.
feats
=
{
backbone_max_level
:
feats_lateral
[
backbone_max_level
]}
feats
=
{
str
(
backbone_max_level
)
:
feats_lateral
[
str
(
backbone_max_level
)
]}
for
level
in
range
(
backbone_max_level
-
1
,
min_level
-
1
,
-
1
):
feats
[
level
]
=
spatial_transform_ops
.
nearest_upsampling
(
feats
[
level
+
1
],
2
)
+
feats_lateral
[
level
]
feats
[
str
(
level
)
]
=
spatial_transform_ops
.
nearest_upsampling
(
feats
[
str
(
level
+
1
)
],
2
)
+
feats_lateral
[
str
(
level
)
]
# TODO(xianzhi): consider to remove bias in conv2d.
# Build post-hoc 3x3 convolution kernel.
for
level
in
range
(
min_level
,
backbone_max_level
+
1
):
feats
[
level
]
=
conv2d
(
feats
[
str
(
level
)
]
=
conv2d
(
filters
=
num_filters
,
strides
=
1
,
kernel_size
=
3
,
...
...
@@ -129,15 +129,15 @@ class FPN(tf.keras.Model):
kernel_initializer
=
kernel_initializer
,
kernel_regularizer
=
kernel_regularizer
,
bias_regularizer
=
bias_regularizer
)(
feats
[
level
])
feats
[
str
(
level
)
])
# TODO(xianzhi): consider to remove bias in conv2d.
# Build coarser FPN levels introduced for RetinaNet.
for
level
in
range
(
backbone_max_level
+
1
,
max_level
+
1
):
feats_in
=
feats
[
level
-
1
]
feats_in
=
feats
[
str
(
level
-
1
)
]
if
level
>
backbone_max_level
+
1
:
feats_in
=
activation_fn
(
feats_in
)
feats
[
level
]
=
conv2d
(
feats
[
str
(
level
)
]
=
conv2d
(
filters
=
num_filters
,
strides
=
2
,
kernel_size
=
3
,
...
...
@@ -149,12 +149,12 @@ class FPN(tf.keras.Model):
# Apply batch norm layers.
for
level
in
range
(
min_level
,
max_level
+
1
):
feats
[
level
]
=
norm
(
feats
[
str
(
level
)
]
=
norm
(
axis
=
bn_axis
,
momentum
=
norm_momentum
,
epsilon
=
norm_epsilon
)(
feats
[
level
])
feats
[
str
(
level
)
])
self
.
_output_specs
=
{
level
:
feats
[
level
].
get_shape
()
str
(
level
)
:
feats
[
str
(
level
)
].
get_shape
()
for
level
in
range
(
min_level
,
max_level
+
1
)
}
...
...
@@ -162,7 +162,7 @@ class FPN(tf.keras.Model):
def
_build_input_pyramid
(
self
,
input_specs
,
min_level
):
assert
isinstance
(
input_specs
,
dict
)
if
min
(
input_specs
.
keys
())
>
min_level
:
if
min
(
input_specs
.
keys
())
>
str
(
min_level
)
:
raise
ValueError
(
'Backbone min level should be less or equal to FPN min level'
)
...
...
official/vision/beta/modeling/decoders/fpn_test.py
View file @
b0ccdb11
...
...
@@ -47,10 +47,10 @@ class FPNTest(parameterized.TestCase, tf.test.TestCase):
feats
=
network
(
endpoints
)
for
level
in
range
(
min_level
,
max_level
+
1
):
self
.
assertIn
(
level
,
feats
)
self
.
assertIn
(
str
(
level
)
,
feats
)
self
.
assertAllEqual
(
[
1
,
input_size
//
2
**
level
,
input_size
//
2
**
level
,
256
],
feats
[
level
].
shape
.
as_list
())
feats
[
str
(
level
)
].
shape
.
as_list
())
def
test_serialize_deserialize
(
self
):
# Create a network object that sets all of its config options.
...
...
official/vision/beta/modeling/factory.py
View file @
b0ccdb11
...
...
@@ -21,11 +21,11 @@ from official.vision.beta.configs import image_classification as classification_
from
official.vision.beta.configs
import
maskrcnn
as
maskrcnn_cfg
from
official.vision.beta.configs
import
retinanet
as
retinanet_cfg
from
official.vision.beta.configs
import
video_classification
as
video_classification_cfg
from
official.vision.beta.modeling
import
backbones
from
official.vision.beta.modeling
import
classification_model
from
official.vision.beta.modeling
import
maskrcnn_model
from
official.vision.beta.modeling
import
retinanet_model
from
official.vision.beta.modeling
import
video_classification_model
from
official.vision.beta.modeling.backbones
import
factory
as
backbone_factory
from
official.vision.beta.modeling.decoders
import
factory
as
decoder_factory
from
official.vision.beta.modeling.heads
import
dense_prediction_heads
from
official.vision.beta.modeling.heads
import
instance_heads
...
...
@@ -41,7 +41,7 @@ def build_classification_model(
model_config
:
classification_cfg
.
ImageClassificationModel
,
l2_regularizer
:
tf
.
keras
.
regularizers
.
Regularizer
=
None
):
"""Builds the classification model."""
backbone
=
backbone
_
factory
.
build_backbone
(
backbone
=
backbone
s
.
factory
.
build_backbone
(
input_specs
=
input_specs
,
model_config
=
model_config
,
l2_regularizer
=
l2_regularizer
)
...
...
@@ -64,7 +64,7 @@ def build_maskrcnn(input_specs: tf.keras.layers.InputSpec,
model_config
:
maskrcnn_cfg
.
MaskRCNN
,
l2_regularizer
:
tf
.
keras
.
regularizers
.
Regularizer
=
None
):
"""Builds Mask R-CNN model."""
backbone
=
backbone
_
factory
.
build_backbone
(
backbone
=
backbone
s
.
factory
.
build_backbone
(
input_specs
=
input_specs
,
model_config
=
model_config
,
l2_regularizer
=
l2_regularizer
)
...
...
@@ -193,7 +193,7 @@ def build_retinanet(input_specs: tf.keras.layers.InputSpec,
model_config
:
retinanet_cfg
.
RetinaNet
,
l2_regularizer
:
tf
.
keras
.
regularizers
.
Regularizer
=
None
):
"""Builds RetinaNet model."""
backbone
=
backbone
_
factory
.
build_backbone
(
backbone
=
backbone
s
.
factory
.
build_backbone
(
input_specs
=
input_specs
,
model_config
=
model_config
,
l2_regularizer
=
l2_regularizer
)
...
...
@@ -242,7 +242,7 @@ def build_video_classification_model(
num_classes
:
int
,
l2_regularizer
:
tf
.
keras
.
regularizers
.
Regularizer
=
None
):
"""Builds the video classification model."""
backbone
=
backbone
_
factory
.
build_backbone
_3d
(
backbone
=
backbone
s
.
factory
.
build_backbone
(
input_specs
=
input_specs
,
model_config
=
model_config
,
l2_regularizer
=
l2_regularizer
)
...
...
official/vision/beta/modeling/heads/dense_prediction_heads.py
View file @
b0ccdb11
...
...
@@ -210,18 +210,18 @@ class RetinaNetHead(tf.keras.layers.Layer):
Args:
features: a dict of tensors
- key: `
int
`, the level of the multilevel features.
- key: `
str
`, the level of the multilevel features.
- values: `Tensor`, the feature map tensors, whose shape is
[batch, height_l, width_l, channels].
Returns:
scores: a dict of tensors which includes scores of the predictions.
- key: `
int
`, the level of the multilevel predictions.
- key: `
str
`, the level of the multilevel predictions.
- values: `Tensor`, the box scores predicted from a particular feature
level, whose shape is
[batch, height_l, width_l, num_classes * num_anchors_per_location].
boxes: a dict of tensors which includes coordinates of the predictions.
- key: `
int
`, the level of the multilevel predictions.
- key: `
str
`, the level of the multilevel predictions.
- values: `Tensor`, the box scores predicted from a particular feature
level, whose shape is
[batch, height_l, width_l, 4 * num_anchors_per_location].
...
...
@@ -231,7 +231,7 @@ class RetinaNetHead(tf.keras.layers.Layer):
for
i
,
level
in
enumerate
(
range
(
self
.
_config_dict
[
'min_level'
],
self
.
_config_dict
[
'max_level'
]
+
1
)):
this_level_features
=
features
[
level
]
this_level_features
=
features
[
str
(
level
)
]
# class net.
x
=
this_level_features
...
...
@@ -239,7 +239,7 @@ class RetinaNetHead(tf.keras.layers.Layer):
x
=
conv
(
x
)
x
=
norm
(
x
)
x
=
self
.
_activation
(
x
)
scores
[
level
]
=
self
.
_classifier
(
x
)
scores
[
str
(
level
)
]
=
self
.
_classifier
(
x
)
# box net.
x
=
this_level_features
...
...
@@ -247,7 +247,7 @@ class RetinaNetHead(tf.keras.layers.Layer):
x
=
conv
(
x
)
x
=
norm
(
x
)
x
=
self
.
_activation
(
x
)
boxes
[
level
]
=
self
.
_box_regressor
(
x
)
boxes
[
str
(
level
)
]
=
self
.
_box_regressor
(
x
)
return
scores
,
boxes
def
get_config
(
self
):
...
...
@@ -433,13 +433,13 @@ class RPNHead(tf.keras.layers.Layer):
for
i
,
level
in
enumerate
(
range
(
self
.
_config_dict
[
'min_level'
],
self
.
_config_dict
[
'max_level'
]
+
1
)):
x
=
features
[
level
]
x
=
features
[
str
(
level
)
]
for
conv
,
norm
in
zip
(
self
.
_convs
,
self
.
_norms
[
i
]):
x
=
conv
(
x
)
x
=
norm
(
x
)
x
=
self
.
_activation
(
x
)
scores
[
level
]
=
self
.
_classifier
(
x
)
boxes
[
level
]
=
self
.
_box_regressor
(
x
)
scores
[
str
(
level
)
]
=
self
.
_classifier
(
x
)
boxes
[
str
(
level
)
]
=
self
.
_box_regressor
(
x
)
return
scores
,
boxes
def
get_config
(
self
):
...
...
official/vision/beta/modeling/heads/dense_prediction_heads_test.py
View file @
b0ccdb11
...
...
@@ -48,14 +48,14 @@ class RetinaNetHeadTest(parameterized.TestCase, tf.test.TestCase):
bias_regularizer
=
None
,
)
features
=
{
3
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
4
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
'3'
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
'4'
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
}
scores
,
boxes
=
retinanet_head
(
features
)
self
.
assertAllEqual
(
scores
[
3
].
numpy
().
shape
,
[
2
,
128
,
128
,
9
])
self
.
assertAllEqual
(
scores
[
4
].
numpy
().
shape
,
[
2
,
64
,
64
,
9
])
self
.
assertAllEqual
(
boxes
[
3
].
numpy
().
shape
,
[
2
,
128
,
128
,
12
])
self
.
assertAllEqual
(
boxes
[
4
].
numpy
().
shape
,
[
2
,
64
,
64
,
12
])
self
.
assertAllEqual
(
scores
[
'3'
].
numpy
().
shape
,
[
2
,
128
,
128
,
9
])
self
.
assertAllEqual
(
scores
[
'4'
].
numpy
().
shape
,
[
2
,
64
,
64
,
9
])
self
.
assertAllEqual
(
boxes
[
'3'
].
numpy
().
shape
,
[
2
,
128
,
128
,
12
])
self
.
assertAllEqual
(
boxes
[
'4'
].
numpy
().
shape
,
[
2
,
64
,
64
,
12
])
def
test_serialize_deserialize
(
self
):
retinanet_head
=
dense_prediction_heads
.
RetinaNetHead
(
...
...
@@ -104,14 +104,14 @@ class RpnHeadTest(parameterized.TestCase, tf.test.TestCase):
bias_regularizer
=
None
,
)
features
=
{
3
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
4
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
'3'
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
'4'
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
}
scores
,
boxes
=
rpn_head
(
features
)
self
.
assertAllEqual
(
scores
[
3
].
numpy
().
shape
,
[
2
,
128
,
128
,
3
])
self
.
assertAllEqual
(
scores
[
4
].
numpy
().
shape
,
[
2
,
64
,
64
,
3
])
self
.
assertAllEqual
(
boxes
[
3
].
numpy
().
shape
,
[
2
,
128
,
128
,
12
])
self
.
assertAllEqual
(
boxes
[
4
].
numpy
().
shape
,
[
2
,
64
,
64
,
12
])
self
.
assertAllEqual
(
scores
[
'3'
].
numpy
().
shape
,
[
2
,
128
,
128
,
3
])
self
.
assertAllEqual
(
scores
[
'4'
].
numpy
().
shape
,
[
2
,
64
,
64
,
3
])
self
.
assertAllEqual
(
boxes
[
'3'
].
numpy
().
shape
,
[
2
,
128
,
128
,
12
])
self
.
assertAllEqual
(
boxes
[
'4'
].
numpy
().
shape
,
[
2
,
64
,
64
,
12
])
def
test_serialize_deserialize
(
self
):
rpn_head
=
dense_prediction_heads
.
RPNHead
(
...
...
official/vision/beta/modeling/layers/box_matcher_test.py
deleted
100644 → 0
View file @
e61588cd
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for box_matcher.py."""
# Import libraries
import
numpy
as
np
import
tensorflow
as
tf
from
official.vision.beta.modeling.layers
import
box_matcher
class
BoxMatcherTest
(
tf
.
test
.
TestCase
):
def
test_box_matcher
(
self
):
boxes_np
=
np
.
array
(
[[
[
0
,
0
,
1
,
1
],
[
5
,
0
,
10
,
5
],
]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
gt_boxes_np
=
np
.
array
(
[[
[
0
,
0
,
5
,
5
],
[
0
,
5
,
5
,
10
],
[
5
,
0
,
10
,
5
],
[
5
,
5
,
10
,
10
],
]])
gt_boxes
=
tf
.
constant
(
gt_boxes_np
,
dtype
=
tf
.
float32
)
gt_classes_np
=
np
.
array
([[
2
,
10
,
3
,
-
1
]])
gt_classes
=
tf
.
constant
(
gt_classes_np
,
dtype
=
tf
.
int32
)
fg_threshold
=
0.5
bg_thresh_hi
=
0.2
bg_thresh_lo
=
0.0
matcher
=
box_matcher
.
BoxMatcher
(
fg_threshold
,
bg_thresh_hi
,
bg_thresh_lo
)
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
(
matched_gt_boxes_tpu
,
matched_gt_classes_tpu
,
matched_gt_indices_tpu
,
positive_matches_tpu
,
negative_matches_tpu
,
ignored_matches_tpu
)
=
(
matcher
(
boxes
,
gt_boxes
,
gt_classes
))
# Runs on CPU.
(
matched_gt_boxes_cpu
,
matched_gt_classes_cpu
,
matched_gt_indices_cpu
,
positive_matches_cpu
,
negative_matches_cpu
,
ignored_matches_cpu
)
=
(
matcher
(
boxes
,
gt_boxes
,
gt_classes
))
# correctness
self
.
assertNDArrayNear
(
matched_gt_boxes_cpu
.
numpy
(),
[[[
0
,
0
,
0
,
0
],
[
5
,
0
,
10
,
5
]]],
1e-4
)
self
.
assertAllEqual
(
matched_gt_classes_cpu
.
numpy
(),
[[
0
,
3
]])
self
.
assertAllEqual
(
matched_gt_indices_cpu
.
numpy
(),
[[
-
1
,
2
]])
self
.
assertAllEqual
(
positive_matches_cpu
.
numpy
(),
[[
False
,
True
]])
self
.
assertAllEqual
(
negative_matches_cpu
.
numpy
(),
[[
True
,
False
]])
self
.
assertAllEqual
(
ignored_matches_cpu
.
numpy
(),
[[
False
,
False
]])
# consistency.
self
.
assertNDArrayNear
(
matched_gt_boxes_cpu
.
numpy
(),
matched_gt_boxes_tpu
.
numpy
(),
1e-4
)
self
.
assertAllEqual
(
matched_gt_classes_cpu
.
numpy
(),
matched_gt_classes_tpu
.
numpy
())
self
.
assertAllEqual
(
matched_gt_indices_cpu
.
numpy
(),
matched_gt_indices_tpu
.
numpy
())
self
.
assertAllEqual
(
positive_matches_cpu
.
numpy
(),
positive_matches_tpu
.
numpy
())
self
.
assertAllEqual
(
negative_matches_cpu
.
numpy
(),
negative_matches_tpu
.
numpy
())
self
.
assertAllEqual
(
ignored_matches_cpu
.
numpy
(),
ignored_matches_tpu
.
numpy
())
def
test_serialize_deserialize
(
self
):
kwargs
=
dict
(
foreground_iou_threshold
=
0.5
,
background_iou_high_threshold
=
0.5
,
background_iou_low_threshold
=
0.5
,
)
matcher
=
box_matcher
.
BoxMatcher
(
**
kwargs
)
expected_config
=
dict
(
kwargs
)
self
.
assertEqual
(
matcher
.
get_config
(),
expected_config
)
new_matcher
=
box_matcher
.
BoxMatcher
.
from_config
(
matcher
.
get_config
())
self
.
assertAllEqual
(
matcher
.
get_config
(),
new_matcher
.
get_config
())
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
official/vision/beta/modeling/layers/detection_generator.py
View file @
b0ccdb11
...
...
@@ -563,24 +563,25 @@ class MultilevelDetectionGenerator(tf.keras.layers.Layer):
boxes
=
[]
scores
=
[]
levels
=
list
(
raw_boxes
.
keys
())
min_level
=
min
(
levels
)
max_level
=
max
(
levels
)
min_level
=
int
(
min
(
levels
)
)
max_level
=
int
(
max
(
levels
)
)
for
i
in
range
(
min_level
,
max_level
+
1
):
raw_boxes_i_shape
=
tf
.
shape
(
raw_boxes
[
i
])
raw_boxes_i_shape
=
tf
.
shape
(
raw_boxes
[
str
(
i
)
])
batch_size
=
raw_boxes_i_shape
[
0
]
num_anchors_per_locations
=
raw_boxes_i_shape
[
-
1
]
//
4
num_classes
=
tf
.
shape
(
raw_scores
[
i
])[
-
1
]
//
num_anchors_per_locations
num_classes
=
tf
.
shape
(
raw_scores
[
str
(
i
)])[
-
1
]
//
num_anchors_per_locations
# Applies score transformation and remove the implicit background class.
scores_i
=
tf
.
sigmoid
(
tf
.
reshape
(
raw_scores
[
i
],
[
batch_size
,
-
1
,
num_classes
]))
tf
.
reshape
(
raw_scores
[
str
(
i
)
],
[
batch_size
,
-
1
,
num_classes
]))
scores_i
=
tf
.
slice
(
scores_i
,
[
0
,
0
,
1
],
[
-
1
,
-
1
,
-
1
])
# Box decoding.
# The anchor boxes are shared for all data in a batch.
# One stage detector only supports class agnostic box regression.
anchor_boxes_i
=
tf
.
reshape
(
anchor_boxes
[
i
],
[
batch_size
,
-
1
,
4
])
raw_boxes_i
=
tf
.
reshape
(
raw_boxes
[
i
],
[
batch_size
,
-
1
,
4
])
anchor_boxes_i
=
tf
.
reshape
(
anchor_boxes
[
str
(
i
)
],
[
batch_size
,
-
1
,
4
])
raw_boxes_i
=
tf
.
reshape
(
raw_boxes
[
str
(
i
)
],
[
batch_size
,
-
1
,
4
])
boxes_i
=
box_ops
.
decode_boxes
(
raw_boxes_i
,
anchor_boxes_i
)
# Box clipping.
...
...
official/vision/beta/modeling/layers/detection_generator_test.py
View file @
b0ccdb11
...
...
@@ -148,22 +148,25 @@ class MultilevelDetectionGeneratorTest(
np
.
random
.
rand
(
84
,
num_classes
)
-
0.5
)
*
3
# random 84x3 outputs.
box_outputs_all
=
np
.
random
.
rand
(
84
,
4
)
# random 84 boxes.
class_outputs
=
{
4
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
cls_outputs_all
[
0
:
64
],
dtype
=
tf
.
float32
),
[
1
,
8
,
8
,
num_classes
]),
5
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
cls_outputs_all
[
64
:
80
],
dtype
=
tf
.
float32
),
[
1
,
4
,
4
,
num_classes
]),
6
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
cls_outputs_all
[
80
:
84
],
dtype
=
tf
.
float32
),
[
1
,
2
,
2
,
num_classes
]),
'4'
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
cls_outputs_all
[
0
:
64
],
dtype
=
tf
.
float32
),
[
1
,
8
,
8
,
num_classes
]),
'5'
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
cls_outputs_all
[
64
:
80
],
dtype
=
tf
.
float32
),
[
1
,
4
,
4
,
num_classes
]),
'6'
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
cls_outputs_all
[
80
:
84
],
dtype
=
tf
.
float32
),
[
1
,
2
,
2
,
num_classes
]),
}
box_outputs
=
{
4
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
'4'
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
box_outputs_all
[
0
:
64
],
dtype
=
tf
.
float32
),
[
1
,
8
,
8
,
4
]),
5
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
'5'
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
box_outputs_all
[
64
:
80
],
dtype
=
tf
.
float32
),
[
1
,
4
,
4
,
4
]),
6
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
'6'
:
tf
.
reshape
(
tf
.
convert_to_tensor
(
box_outputs_all
[
80
:
84
],
dtype
=
tf
.
float32
),
[
1
,
2
,
2
,
4
]),
}
image_info
=
tf
.
constant
([[[
1000
,
1000
],
[
100
,
100
],
[
0.1
,
0.1
],
[
0
,
0
]]],
...
...
official/vision/beta/modeling/layers/mask_sampler_test.py
deleted
100644 → 0
View file @
e61588cd
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for mask_sampler.py."""
# Import libraries
import
numpy
as
np
import
tensorflow
as
tf
from
official.vision.beta.modeling.layers
import
mask_sampler
class
SampleAndCropForegroundMasksTest
(
tf
.
test
.
TestCase
):
def
test_sample_and_crop_foreground_masks
(
self
):
candidate_rois_np
=
np
.
array
(
[[[
0
,
0
,
0.5
,
0.5
],
[
0.5
,
0.5
,
1
,
1
],
[
2
,
2
,
4
,
4
],
[
1
,
1
,
5
,
5
]]])
candidate_rois
=
tf
.
constant
(
candidate_rois_np
,
dtype
=
tf
.
float32
)
candidate_gt_boxes_np
=
np
.
array
(
[[[
0
,
0
,
0.6
,
0.6
],
[
0
,
0
,
0
,
0
],
[
1
,
1
,
3
,
3
],
[
1
,
1
,
3
,
3
]]])
candidate_gt_boxes
=
tf
.
constant
(
candidate_gt_boxes_np
,
dtype
=
tf
.
float32
)
candidate_gt_classes_np
=
np
.
array
([[
4
,
0
,
0
,
2
]])
candidate_gt_classes
=
tf
.
constant
(
candidate_gt_classes_np
,
dtype
=
tf
.
float32
)
candidate_gt_indices_np
=
np
.
array
([[
10
,
-
1
,
-
1
,
20
]])
candidate_gt_indices
=
tf
.
constant
(
candidate_gt_indices_np
,
dtype
=
tf
.
int32
)
gt_masks_np
=
np
.
random
.
rand
(
1
,
100
,
32
,
32
)
gt_masks
=
tf
.
constant
(
gt_masks_np
,
dtype
=
tf
.
float32
)
num_mask_samples_per_image
=
2
mask_target_size
=
28
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
foreground_rois
,
foreground_classes
,
cropped_foreground_masks
=
(
mask_sampler
.
_sample_and_crop_foreground_masks
(
candidate_rois
,
candidate_gt_boxes
,
candidate_gt_classes
,
candidate_gt_indices
,
gt_masks
,
num_mask_samples_per_image
,
mask_target_size
))
foreground_rois_tpu
=
foreground_rois
.
numpy
()
foreground_classes_tpu
=
foreground_classes
.
numpy
()
cropped_foreground_masks_tpu
=
cropped_foreground_masks
.
numpy
()
foreground_rois
,
foreground_classes
,
cropped_foreground_masks
=
(
mask_sampler
.
_sample_and_crop_foreground_masks
(
candidate_rois
,
candidate_gt_boxes
,
candidate_gt_classes
,
candidate_gt_indices
,
gt_masks
,
num_mask_samples_per_image
,
mask_target_size
))
foreground_rois_cpu
=
foreground_rois
.
numpy
()
foreground_classes_cpu
=
foreground_classes
.
numpy
()
cropped_foreground_masks_cpu
=
cropped_foreground_masks
.
numpy
()
# consistency.
self
.
assertAllEqual
(
foreground_rois_tpu
.
shape
,
foreground_rois_cpu
.
shape
)
self
.
assertAllEqual
(
foreground_classes_tpu
.
shape
,
foreground_classes_cpu
.
shape
)
self
.
assertAllEqual
(
cropped_foreground_masks_tpu
.
shape
,
cropped_foreground_masks_cpu
.
shape
)
# correctnesss.
self
.
assertAllEqual
(
foreground_rois_tpu
.
shape
,
[
1
,
2
,
4
])
self
.
assertAllEqual
(
foreground_classes_tpu
.
shape
,
[
1
,
2
])
self
.
assertAllEqual
(
cropped_foreground_masks_tpu
.
shape
,
[
1
,
2
,
28
,
28
])
class
MaskSamplerTest
(
tf
.
test
.
TestCase
):
def
test_mask_sampler
(
self
):
candidate_rois_np
=
np
.
array
(
[[[
0
,
0
,
0.5
,
0.5
],
[
0.5
,
0.5
,
1
,
1
],
[
2
,
2
,
4
,
4
],
[
1
,
1
,
5
,
5
]]])
candidate_rois
=
tf
.
constant
(
candidate_rois_np
,
dtype
=
tf
.
float32
)
candidate_gt_boxes_np
=
np
.
array
(
[[[
0
,
0
,
0.6
,
0.6
],
[
0
,
0
,
0
,
0
],
[
1
,
1
,
3
,
3
],
[
1
,
1
,
3
,
3
]]])
candidate_gt_boxes
=
tf
.
constant
(
candidate_gt_boxes_np
,
dtype
=
tf
.
float32
)
candidate_gt_classes_np
=
np
.
array
([[
4
,
0
,
0
,
2
]])
candidate_gt_classes
=
tf
.
constant
(
candidate_gt_classes_np
,
dtype
=
tf
.
float32
)
candidate_gt_indices_np
=
np
.
array
([[
10
,
-
1
,
-
1
,
20
]])
candidate_gt_indices
=
tf
.
constant
(
candidate_gt_indices_np
,
dtype
=
tf
.
int32
)
gt_masks_np
=
np
.
random
.
rand
(
1
,
100
,
32
,
32
)
gt_masks
=
tf
.
constant
(
gt_masks_np
,
dtype
=
tf
.
float32
)
sampler
=
mask_sampler
.
MaskSampler
(
28
,
2
)
foreground_rois
,
foreground_classes
,
cropped_foreground_masks
=
sampler
(
candidate_rois
,
candidate_gt_boxes
,
candidate_gt_classes
,
candidate_gt_indices
,
gt_masks
)
# correctnesss.
self
.
assertAllEqual
(
foreground_rois
.
numpy
().
shape
,
[
1
,
2
,
4
])
self
.
assertAllEqual
(
foreground_classes
.
numpy
().
shape
,
[
1
,
2
])
self
.
assertAllEqual
(
cropped_foreground_masks
.
numpy
().
shape
,
[
1
,
2
,
28
,
28
])
def
test_serialize_deserialize
(
self
):
kwargs
=
dict
(
mask_target_size
=
7
,
num_sampled_masks
=
10
,
)
sampler
=
mask_sampler
.
MaskSampler
(
**
kwargs
)
expected_config
=
dict
(
kwargs
)
self
.
assertEqual
(
sampler
.
get_config
(),
expected_config
)
new_sampler
=
mask_sampler
.
MaskSampler
.
from_config
(
sampler
.
get_config
())
self
.
assertAllEqual
(
sampler
.
get_config
(),
new_sampler
.
get_config
())
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
official/vision/beta/modeling/layers/roi_generator.py
View file @
b0ccdb11
...
...
@@ -95,7 +95,7 @@ def _multilevel_propose_rois(raw_boxes,
roi_scores
=
[]
image_shape
=
tf
.
expand_dims
(
image_shape
,
axis
=
1
)
for
level
in
sorted
(
raw_scores
.
keys
()):
with
tf
.
name_scope
(
'level_%
d
'
%
level
):
with
tf
.
name_scope
(
'level_%
s
'
%
level
):
_
,
feature_h
,
feature_w
,
num_anchors_per_location
=
(
raw_scores
[
level
].
get_shape
().
as_list
())
...
...
official/vision/beta/modeling/layers/roi_generator_test.py
deleted
100644 → 0
View file @
e61588cd
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for roi_generator.py."""
# Import libraries
import
numpy
as
np
import
tensorflow
as
tf
from
official.vision.beta.modeling.layers
import
roi_generator
class
MultilevelProposeRoisTest
(
tf
.
test
.
TestCase
):
def
test_multilevel_propose_rois_single_level
(
self
):
rpn_boxes_np
=
np
.
array
(
[[[[
0
,
0
,
10
,
10
],
[
0.01
,
0.01
,
9.9
,
9.9
]],
[[
5
,
5
,
10
,
10
],
[
2
,
2
,
8
,
8
]]],
[[[
2
,
2
,
4
,
4
],
[
3
,
3
,
6
,
6
]],
[[
3.1
,
3.1
,
6.1
,
6.1
],
[
1
,
1
,
8
,
8
]]]])
rpn_boxes
=
{
2
:
tf
.
constant
(
rpn_boxes_np
,
dtype
=
tf
.
float32
)
}
rpn_scores_np
=
np
.
array
(
[[[[
0.6
],
[
0.9
]],
[[
0.2
],
[
0.3
]]],
[[[
0.1
],
[
0.8
]],
[[
0.3
],
[
0.5
]]]])
rpn_scores
=
{
2
:
tf
.
constant
(
rpn_scores_np
,
dtype
=
tf
.
float32
)
}
anchor_boxes_np
=
np
.
array
(
[[[[
0
,
0
,
10
,
10
],
[
0.01
,
0.01
,
9.9
,
9.9
]],
[[
5
,
5
,
10
,
10
],
[
2
,
2
,
8
,
8
]]],
[[[
2
,
2
,
4
,
4
],
[
3
,
3
,
6
,
6
]],
[[
3.1
,
3.1
,
6.1
,
6.1
],
[
1
,
1
,
8
,
8
]]]])
anchor_boxes
=
{
2
:
tf
.
constant
(
anchor_boxes_np
,
dtype
=
tf
.
float32
)
}
image_shape
=
tf
.
constant
([[
20
,
20
],
[
20
,
20
]],
dtype
=
tf
.
int32
)
selected_rois_np
=
np
.
array
(
[[[
0.01
,
0.01
,
9.9
,
9.9
],
[
2
,
2
,
8
,
8
],
[
5
,
5
,
10
,
10
],
[
0
,
0
,
0
,
0
]],
[[
3
,
3
,
6
,
6
],
[
1
,
1
,
8
,
8
],
[
2
,
2
,
4
,
4
],
[
0
,
0
,
0
,
0
]]])
selected_roi_scores_np
=
np
.
array
(
[[
0.9
,
0.3
,
0.2
,
0
],
[
0.8
,
0.5
,
0.1
,
0
]])
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
selected_rois_tpu
,
selected_roi_scores_tpu
=
(
roi_generator
.
_multilevel_propose_rois
(
rpn_boxes
,
rpn_scores
,
anchor_boxes
=
anchor_boxes
,
image_shape
=
image_shape
,
pre_nms_top_k
=
4
,
pre_nms_score_threshold
=
0.0
,
pre_nms_min_size_threshold
=
0.0
,
nms_iou_threshold
=
0.5
,
num_proposals
=
4
,
use_batched_nms
=
False
,
decode_boxes
=
False
,
clip_boxes
=
False
,
apply_sigmoid_to_score
=
False
))
# Runs on CPU.
selected_rois_cpu
,
selected_roi_scores_cpu
=
(
roi_generator
.
_multilevel_propose_rois
(
rpn_boxes
,
rpn_scores
,
anchor_boxes
=
anchor_boxes
,
image_shape
=
image_shape
,
pre_nms_top_k
=
4
,
pre_nms_score_threshold
=
0.0
,
pre_nms_min_size_threshold
=
0.0
,
nms_iou_threshold
=
0.5
,
num_proposals
=
4
,
use_batched_nms
=
False
,
decode_boxes
=
False
,
clip_boxes
=
False
,
apply_sigmoid_to_score
=
False
))
self
.
assertNDArrayNear
(
selected_rois_tpu
.
numpy
(),
selected_rois_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
selected_roi_scores_tpu
.
numpy
(),
selected_roi_scores_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
selected_rois_tpu
.
numpy
(),
selected_rois_np
,
1e-5
)
self
.
assertNDArrayNear
(
selected_roi_scores_tpu
.
numpy
(),
selected_roi_scores_np
,
1e-5
)
def
test_multilevel_propose_rois_two_levels
(
self
):
rpn_boxes_1_np
=
np
.
array
(
[[[[
0
,
0
,
10
,
10
],
[
0.01
,
0.01
,
9.99
,
9.99
]],
[[
5
,
5
,
10
,
10
],
[
2
,
2
,
8
,
8
]]],
[[[
2
,
2
,
2.5
,
2.5
],
[
3
,
3
,
6
,
6
]],
[[
3.1
,
3.1
,
6.1
,
6.1
],
[
1
,
1
,
8
,
8
]]]])
rpn_boxes_2_np
=
np
.
array
(
[[[[
0
,
0
,
10.01
,
10.01
]]],
[[[
2
,
2
,
4.5
,
4.5
]]]])
rpn_boxes
=
{
2
:
tf
.
constant
(
rpn_boxes_1_np
,
dtype
=
tf
.
float32
),
3
:
tf
.
constant
(
rpn_boxes_2_np
,
dtype
=
tf
.
float32
),
}
rpn_scores_1_np
=
np
.
array
(
[[[[
0.6
],
[
0.9
]],
[[
0.2
],
[
0.3
]]],
[[[
0.1
],
[
0.8
]],
[[
0.3
],
[
0.5
]]]])
rpn_scores_2_np
=
np
.
array
([[[[
0.95
]]],
[[[
0.99
]]]])
rpn_scores
=
{
2
:
tf
.
constant
(
rpn_scores_1_np
,
dtype
=
tf
.
float32
),
3
:
tf
.
constant
(
rpn_scores_2_np
,
dtype
=
tf
.
float32
),
}
anchor_boxes_1_np
=
np
.
array
(
[[[[
0
,
0
,
10
,
10
],
[
0.01
,
0.01
,
9.99
,
9.99
]],
[[
5
,
5
,
10
,
10
],
[
2
,
2
,
8
,
8
]]],
[[[
2
,
2
,
2.5
,
2.5
],
[
3
,
3
,
6
,
6
]],
[[
3.1
,
3.1
,
6.1
,
6.1
],
[
1
,
1
,
8
,
8
]]]])
anchor_boxes_2_np
=
np
.
array
(
[[[[
0
,
0
,
10.01
,
10.01
]]],
[[[
2
,
2
,
4.5
,
4.5
]]]])
anchor_boxes
=
{
2
:
tf
.
constant
(
anchor_boxes_1_np
,
dtype
=
tf
.
float32
),
3
:
tf
.
constant
(
anchor_boxes_2_np
,
dtype
=
tf
.
float32
),
}
image_shape
=
tf
.
constant
([[
20
,
20
],
[
20
,
20
]],
dtype
=
tf
.
int32
)
selected_rois_np
=
np
.
array
(
[[[
0
,
0
,
10.01
,
10.01
],
[
0.01
,
0.01
,
9.99
,
9.99
]],
[[
2
,
2
,
4.5
,
4.5
],
[
3
,
3
,
6
,
6
]]])
selected_roi_scores_np
=
np
.
array
([[
0.95
,
0.9
],
[
0.99
,
0.8
]])
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
selected_rois_tpu
,
selected_roi_scores_tpu
=
(
roi_generator
.
_multilevel_propose_rois
(
rpn_boxes
,
rpn_scores
,
anchor_boxes
=
anchor_boxes
,
image_shape
=
image_shape
,
pre_nms_top_k
=
4
,
pre_nms_score_threshold
=
0.0
,
pre_nms_min_size_threshold
=
0.0
,
nms_iou_threshold
=
0.5
,
num_proposals
=
2
,
use_batched_nms
=
False
,
decode_boxes
=
False
,
clip_boxes
=
False
,
apply_sigmoid_to_score
=
False
))
# Runs on CPU.
selected_rois_cpu
,
selected_roi_scores_cpu
=
(
roi_generator
.
_multilevel_propose_rois
(
rpn_boxes
,
rpn_scores
,
anchor_boxes
=
anchor_boxes
,
image_shape
=
image_shape
,
pre_nms_top_k
=
4
,
pre_nms_score_threshold
=
0.0
,
pre_nms_min_size_threshold
=
0.0
,
nms_iou_threshold
=
0.5
,
num_proposals
=
2
,
use_batched_nms
=
False
,
decode_boxes
=
False
,
clip_boxes
=
False
,
apply_sigmoid_to_score
=
False
))
self
.
assertNDArrayNear
(
selected_rois_tpu
.
numpy
(),
selected_rois_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
selected_roi_scores_tpu
.
numpy
(),
selected_roi_scores_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
selected_rois_tpu
.
numpy
(),
selected_rois_np
,
1e-5
)
self
.
assertNDArrayNear
(
selected_roi_scores_tpu
.
numpy
(),
selected_roi_scores_np
,
1e-5
)
class
MultilevelROIGeneratorTest
(
tf
.
test
.
TestCase
):
def
test_serialize_deserialize
(
self
):
kwargs
=
dict
(
pre_nms_top_k
=
2000
,
pre_nms_score_threshold
=
0.0
,
pre_nms_min_size_threshold
=
0.0
,
nms_iou_threshold
=
0.7
,
num_proposals
=
1000
,
test_pre_nms_top_k
=
1000
,
test_pre_nms_score_threshold
=
0.0
,
test_pre_nms_min_size_threshold
=
0.0
,
test_nms_iou_threshold
=
0.7
,
test_num_proposals
=
1000
,
use_batched_nms
=
False
,
)
generator
=
roi_generator
.
MultilevelROIGenerator
(
**
kwargs
)
expected_config
=
dict
(
kwargs
)
self
.
assertEqual
(
generator
.
get_config
(),
expected_config
)
new_generator
=
roi_generator
.
MultilevelROIGenerator
.
from_config
(
generator
.
get_config
())
self
.
assertAllEqual
(
generator
.
get_config
(),
new_generator
.
get_config
())
official/vision/beta/modeling/retinanet_model.py
View file @
b0ccdb11
...
...
@@ -65,19 +65,19 @@ class RetinaNetModel(tf.keras.Model):
in the batch may be resized into different shapes before padding to the
fixed size.
anchor_boxes: a dict of tensors which includes multilevel anchors.
- key: `
int
`, the level of the multilevel predictions.
- key: `
str
`, the level of the multilevel predictions.
- values: `Tensor`, the anchor coordinates of a particular feature
level, whose shape is [height_l, width_l, num_anchors_per_location].
training: `bool`, indicating whether it is in training mode.
Returns:
scores: a dict of tensors which includes scores of the predictions.
- key: `
int
`, the level of the multilevel predictions.
- key: `
str
`, the level of the multilevel predictions.
- values: `Tensor`, the box scores predicted from a particular feature
level, whose shape is
[batch, height_l, width_l, num_classes * num_anchors_per_location].
boxes: a dict of tensors which includes coordinates of the predictions.
- key: `
int
`, the level of the multilevel predictions.
- key: `
str
`, the level of the multilevel predictions.
- values: `Tensor`, the box coordinates predicted from a particular
feature level, whose shape is
[batch, height_l, width_l, 4 * num_anchors_per_location].
...
...
official/vision/beta/modeling/retinanet_model_test.py
View file @
b0ccdb11
...
...
@@ -153,20 +153,20 @@ class RetinaNetTest(parameterized.TestCase, tf.test.TestCase):
cls_outputs
=
model_outputs
[
'cls_outputs'
]
box_outputs
=
model_outputs
[
'box_outputs'
]
for
level
in
range
(
min_level
,
max_level
+
1
):
self
.
assertIn
(
level
,
cls_outputs
)
self
.
assertIn
(
level
,
box_outputs
)
self
.
assertIn
(
str
(
level
)
,
cls_outputs
)
self
.
assertIn
(
str
(
level
)
,
box_outputs
)
self
.
assertAllEqual
([
2
,
image_size
[
0
]
//
2
**
level
,
image_size
[
1
]
//
2
**
level
,
num_classes
*
num_anchors_per_location
],
cls_outputs
[
level
].
numpy
().
shape
)
],
cls_outputs
[
str
(
level
)
].
numpy
().
shape
)
self
.
assertAllEqual
([
2
,
image_size
[
0
]
//
2
**
level
,
image_size
[
1
]
//
2
**
level
,
4
*
num_anchors_per_location
],
box_outputs
[
level
].
numpy
().
shape
)
],
box_outputs
[
str
(
level
)
].
numpy
().
shape
)
else
:
self
.
assertIn
(
'detection_boxes'
,
model_outputs
)
self
.
assertIn
(
'detection_scores'
,
model_outputs
)
...
...
@@ -220,3 +220,4 @@ class RetinaNetTest(parameterized.TestCase, tf.test.TestCase):
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
official/vision/beta/ops/anchor.py
View file @
b0ccdb11
...
...
@@ -17,13 +17,10 @@
import
collections
# Import libraries
import
tensorflow
as
tf
from
official.vision.beta.ops.experimental
import
anchor_generator
from
official.vision.detection.utils.object_detection
import
argmax_matcher
from
official.vision
import
keras_cv
from
official.vision.detection.utils.object_detection
import
balanced_positive_negative_sampler
from
official.vision.detection.utils.object_detection
import
box_list
from
official.vision.detection.utils.object_detection
import
faster_rcnn_box_coder
from
official.vision.detection.utils.object_detection
import
region_similarity_calculator
from
official.vision.detection.utils.object_detection
import
target_assigner
class
Anchor
(
object
):
...
...
@@ -105,7 +102,7 @@ class Anchor(object):
feat_size_y
=
tf
.
cast
(
self
.
image_size
[
0
]
/
2
**
level
,
tf
.
int32
)
feat_size_x
=
tf
.
cast
(
self
.
image_size
[
1
]
/
2
**
level
,
tf
.
int32
)
steps
=
feat_size_y
*
feat_size_x
*
self
.
anchors_per_location
unpacked_labels
[
level
]
=
tf
.
reshape
(
unpacked_labels
[
str
(
level
)
]
=
tf
.
reshape
(
labels
[
count
:
count
+
steps
],
[
feat_size_y
,
feat_size_x
,
-
1
])
count
+=
steps
return
unpacked_labels
...
...
@@ -135,18 +132,13 @@ class AnchorLabeler(object):
upper-bound threshold to assign negative labels for anchors. An anchor
with a score below the threshold is labeled negative.
"""
similarity_calc
=
region_similarity_calculator
.
IouSimilarity
()
matcher
=
argmax_matcher
.
ArgMaxMatch
er
(
match_threshold
,
unmatched
_threshold
=
un
match
ed
_threshold
,
negative
s_lower_than_unmatched
=
True
,
self
.
similarity_calc
=
keras_cv
.
ops
.
IouSimilarity
()
self
.
anchor_labeler
=
keras_cv
.
ops
.
AnchorLabel
er
(
)
self
.
matcher
=
keras_cv
.
ops
.
BoxMatcher
(
positive
_threshold
=
match_threshold
,
negative
_threshold
=
unmatched_threshold
,
force_match_for_each_row
=
True
)
box_coder
=
faster_rcnn_box_coder
.
FasterRcnnBoxCoder
()
self
.
_target_assigner
=
target_assigner
.
TargetAssigner
(
similarity_calc
,
matcher
,
box_coder
)
self
.
_match_threshold
=
match_threshold
self
.
_unmatched_threshold
=
unmatched_threshold
self
.
box_coder
=
faster_rcnn_box_coder
.
FasterRcnnBoxCoder
()
def
label_anchors
(
self
,
anchor_boxes
,
gt_boxes
,
gt_labels
):
"""Labels anchors with ground truth inputs.
...
...
@@ -177,30 +169,17 @@ class AnchorLabeler(object):
1.0 for positive matched anchors, and 0.0 for negative and ignored
anchors.
"""
gt_box_list
=
box_list
.
BoxList
(
gt_boxes
)
flattened_anchor_boxes
=
[]
for
anchors
in
anchor_boxes
.
values
():
flattened_anchor_boxes
.
append
(
tf
.
reshape
(
anchors
,
[
-
1
,
4
]))
flattened_anchor_boxes
=
tf
.
concat
(
flattened_anchor_boxes
,
axis
=
0
)
similarity_matrix
=
self
.
similarity_calc
(
gt_boxes
,
flattened_anchor_boxes
)
match_results
=
self
.
matcher
(
similarity_matrix
)
cls_targets
,
box_targets
,
cls_weights
,
box_weights
=
self
.
anchor_labeler
(
gt_boxes
,
gt_labels
,
match_results
)
box_targets_list
=
box_list
.
BoxList
(
box_targets
)
anchor_box_list
=
box_list
.
BoxList
(
flattened_anchor_boxes
)
# The cls_weights, box_weights are not used.
(
cls_targets
,
cls_weights
,
box_targets
,
box_weights
,
matches
)
=
self
.
_target_assigner
.
assign
(
anchor_box_list
,
gt_box_list
,
gt_labels
)
# Labels definition in matches.match_results:
# (1) match_results[i]>=0, meaning that column i is matched with row
# match_results[i].
# (2) match_results[i]=-1, meaning that column i is not matched.
# (3) match_results[i]=-2, meaning that column i is ignored.
match_results
=
tf
.
expand_dims
(
matches
.
match_results
,
axis
=
1
)
cls_targets
=
tf
.
cast
(
cls_targets
,
tf
.
int32
)
cls_targets
=
tf
.
where
(
tf
.
equal
(
match_results
,
-
1
),
-
tf
.
ones_like
(
cls_targets
),
cls_targets
)
cls_targets
=
tf
.
where
(
tf
.
equal
(
match_results
,
-
2
),
-
2
*
tf
.
ones_like
(
cls_targets
),
cls_targets
)
box_targets
=
self
.
box_coder
.
encode
(
box_targets_list
,
anchor_box_list
)
# Unpacks labels into multi-level representations.
cls_targets_dict
=
unpack_targets
(
cls_targets
,
anchor_boxes
)
...
...
@@ -285,19 +264,33 @@ class RpnAnchorLabeler(AnchorLabeler):
width_l represent the dimension of bounding box regression output at
l-th level.
"""
gt_box_list
=
box_list
.
BoxList
(
gt_boxes
)
flattened_anchor_boxes
=
[]
for
anchors
in
anchor_boxes
.
values
():
flattened_anchor_boxes
.
append
(
tf
.
reshape
(
anchors
,
[
-
1
,
4
]))
flattened_anchor_boxes
=
tf
.
concat
(
flattened_anchor_boxes
,
axis
=
0
)
anchor_box_list
=
box_list
.
BoxList
(
flattened_anchor_boxes
)
similarity_matrix
=
self
.
similarity_calc
(
gt_boxes
,
flattened_anchor_boxes
)
match_results
=
self
.
matcher
(
similarity_matrix
)
# cls_targets, cls_weights, box_weights are not used.
_
,
_
,
box_targets
,
_
,
matches
=
self
.
_target_assigner
.
assign
(
anchor_box_list
,
gt_box_list
,
gt_labels
)
_
,
box_targets
,
_
,
_
=
self
.
anchor_labeler
(
gt_boxes
,
gt_labels
,
match_results
)
box_targets_list
=
box_list
.
BoxList
(
box_targets
)
anchor_box_list
=
box_list
.
BoxList
(
flattened_anchor_boxes
)
box_targets
=
self
.
box_coder
.
encode
(
box_targets_list
,
anchor_box_list
)
# Zero out the unmatched and ignored regression targets.
num_matches
=
match_results
.
shape
.
as_list
()[
0
]
or
tf
.
shape
(
match_results
)[
0
]
unmatched_ignored_box_targets
=
tf
.
zeros
([
num_matches
,
4
],
dtype
=
tf
.
float32
)
matched_anchors_mask
=
tf
.
greater_equal
(
match_results
,
0
)
# To broadcast matched_anchors_mask to the same shape as
# matched_reg_targets.
matched_anchors_mask
=
tf
.
tile
(
tf
.
expand_dims
(
matched_anchors_mask
,
1
),
[
1
,
tf
.
shape
(
box_targets
)[
1
]])
box_targets
=
tf
.
where
(
matched_anchors_mask
,
box_targets
,
unmatched_ignored_box_targets
)
# score_targets contains the subsampled positive and negative anchors.
score_targets
,
_
,
_
=
self
.
_get_rpn_samples
(
matches
.
match_results
)
score_targets
,
_
,
_
=
self
.
_get_rpn_samples
(
match_results
)
# Unpacks labels.
score_targets_dict
=
unpack_targets
(
score_targets
,
anchor_boxes
)
...
...
@@ -316,9 +309,9 @@ def build_anchor_generator(min_level, max_level, num_scales, aspect_ratios,
scales
.
append
(
2
**
(
scale
/
float
(
num_scales
)))
for
level
in
range
(
min_level
,
max_level
+
1
):
stride
=
2
**
level
strides
[
level
]
=
stride
anchor_sizes
[
level
]
=
anchor_size
*
stride
anchor_gen
=
anchor_generator
.
AnchorGenerator
(
strides
[
str
(
level
)
]
=
stride
anchor_sizes
[
str
(
level
)
]
=
anchor_size
*
stride
anchor_gen
=
keras_cv
.
ops
.
AnchorGenerator
(
anchor_sizes
=
anchor_sizes
,
scales
=
scales
,
aspect_ratios
=
aspect_ratios
,
...
...
official/vision/beta/ops/anchor_test.py
View file @
b0ccdb11
...
...
@@ -124,7 +124,7 @@ class AnchorTest(parameterized.TestCase, tf.test.TestCase):
# Uses the first anchors as ground truth. The ground truth should map to
# two anchors with two intermediate scales at the same location.
gt_boxes
=
anchor_boxes
[
3
][
0
:
1
,
0
,
0
:
4
]
gt_boxes
=
anchor_boxes
[
'3'
][
0
:
1
,
0
,
0
:
4
]
gt_classes
=
tf
.
constant
([[
ground_truth_class_id
]],
dtype
=
tf
.
float32
)
(
cls_targets
,
box_targets
,
_
,
box_weights
)
=
anchor_labeler
.
label_anchors
(
...
...
@@ -137,7 +137,7 @@ class AnchorTest(parameterized.TestCase, tf.test.TestCase):
box_weights
=
box_weights
.
numpy
()
anchor_locations
=
np
.
vstack
(
np
.
where
(
cls_targets
[
min_level
]
>
-
1
)).
transpose
()
np
.
where
(
cls_targets
[
str
(
min_level
)
]
>
-
1
)).
transpose
()
self
.
assertAllClose
(
expected_anchor_locations
,
anchor_locations
)
# Two anchor boxes on min_level got matched to the gt_boxes.
self
.
assertAllClose
(
tf
.
reduce_sum
(
box_weights
),
2
)
...
...
official/vision/beta/ops/box_ops_test.py
deleted
100644 → 0
View file @
e61588cd
# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Tests for box_ops.py."""
# Import libraries
import
numpy
as
np
import
tensorflow
as
tf
from
official.vision.beta.ops
import
box_ops
def
_transform_boxes_on_tpu_and_cpu
(
transform_fn
,
boxes
,
*
args
):
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
transformed_op_tpu
=
transform_fn
(
boxes
,
*
args
)
transfomred_boxes_tpu
=
tf
.
nest
.
map_structure
(
lambda
x
:
x
.
numpy
(),
transformed_op_tpu
)
# Runs on CPU.
transfomred_op_cpu
=
transform_fn
(
boxes
,
*
args
)
transfomred_boxes_cpu
=
tf
.
nest
.
map_structure
(
lambda
x
:
x
.
numpy
(),
transfomred_op_cpu
)
return
transfomred_boxes_tpu
,
transfomred_boxes_cpu
class
ConvertBoxesTest
(
tf
.
test
.
TestCase
):
def
testConvertBoxes
(
self
):
# y1, x1, y2, x2.
boxes
=
np
.
array
([[
0
,
0
,
1
,
2
],
[
0.2
,
0.1
,
1.2
,
1.1
]])
# x1, y1, width, height
target
=
np
.
array
([[
0
,
0
,
2
,
1
],
[
0.1
,
0.2
,
1
,
1
]])
outboxes
=
box_ops
.
yxyx_to_xywh
(
boxes
)
self
.
assertNDArrayNear
(
outboxes
,
target
,
1e-7
)
class
JitterBoxesTest
(
tf
.
test
.
TestCase
):
def
testJitterBoxes
(
self
):
boxes_data
=
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]]
boxes_np
=
np
.
array
(
boxes_data
,
dtype
=
np
.
float32
)
max_size
=
max
(
np
.
amax
(
boxes_np
[:,
3
]
-
boxes_np
[:,
1
]),
np
.
amax
(
boxes_np
[:,
2
]
-
boxes_np
[:,
0
]))
noise_scale
=
0.025
boxes
=
tf
.
constant
(
boxes_np
)
def
jitter_fn
(
input_boxes
,
arg_noise_scale
):
return
box_ops
.
jitter_boxes
(
input_boxes
,
arg_noise_scale
)
jittered_boxes_tpu
,
jittered_boxes_cpu
=
_transform_boxes_on_tpu_and_cpu
(
jitter_fn
,
boxes
,
noise_scale
)
# Test that the jittered box is within 10 stds from the inputs.
self
.
assertNDArrayNear
(
jittered_boxes_tpu
,
boxes_np
,
noise_scale
*
max_size
*
10
)
self
.
assertNDArrayNear
(
jittered_boxes_cpu
,
boxes_np
,
noise_scale
*
max_size
*
10
)
class
NormalizeBoxesTest
(
tf
.
test
.
TestCase
):
def
testNormalizeBoxes1DWithImageShapeAsList
(
self
):
boxes
=
tf
.
constant
([
10
,
30
,
40
,
90
],
tf
.
float32
)
image_shape
=
[
50
,
100
]
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[
0.2
,
0.3
,
0.8
,
0.9
],
1e-5
)
def
testNormalizeBoxes1DWithImageShapeAsTensor
(
self
):
boxes
=
tf
.
constant
([
10
,
30
,
40
,
90
],
tf
.
float32
)
image_shape
=
tf
.
constant
([
50
,
100
],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[
0.2
,
0.3
,
0.8
,
0.9
],
1e-5
)
def
testNormalizeBoxes2DWithImageShapeAsList
(
self
):
boxes
=
tf
.
constant
([[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
tf
.
float32
)
image_shape
=
[
50
,
100
]
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
1e-5
)
def
testNormalizeBoxes2DWithImageShapeAsVector
(
self
):
boxes
=
tf
.
constant
([[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
tf
.
float32
)
image_shape
=
tf
.
constant
([
50
,
100
],
dtype
=
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
1e-5
)
def
testNormalizeBoxes2DWithImageShapeAsBroadcastableTensor
(
self
):
boxes
=
tf
.
constant
([[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
tf
.
float32
)
image_shape
=
tf
.
constant
([[
50
,
100
]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
1e-5
)
def
testNormalizeBoxes2DWithImageShapeAsSameShapeTensor
(
self
):
boxes
=
tf
.
constant
([[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
tf
.
float32
)
image_shape
=
tf
.
constant
([[
50
,
100
],
[
50
,
100
]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
1e-5
)
def
testNormalizeBoxes3DWithImageShapeAsList
(
self
):
boxes
=
tf
.
constant
([[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
tf
.
float32
)
image_shape
=
[
50
,
100
]
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.4
,
0.4
,
1.0
,
0.8
],
[
0.6
,
0.5
,
0.8
,
0.9
]]],
1e-5
)
def
testNormalizeBoxes3DWithImageShapeAsVector
(
self
):
boxes
=
tf
.
constant
([[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
tf
.
float32
)
image_shape
=
tf
.
constant
([
50
,
100
],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.4
,
0.4
,
1.0
,
0.8
],
[
0.6
,
0.5
,
0.8
,
0.9
]]],
1e-5
)
def
testNormalizeBoxes3DWithImageShapeAsBroadcastableTensor
(
self
):
boxes
=
tf
.
constant
([[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
tf
.
float32
)
image_shape
=
tf
.
constant
([[[
50
,
100
]],
[[
500
,
1000
]]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.04
,
0.04
,
0.1
,
0.08
],
[
0.06
,
0.05
,
0.08
,
0.09
]]],
1e-5
)
def
testNormalizeBoxes3DWithImageShapeAsSameShapeTensor
(
self
):
boxes
=
tf
.
constant
([[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
tf
.
float32
)
image_shape
=
tf
.
constant
(
[[[
50
,
100
],
[
50
,
100
]],
[[
500
,
1000
],
[
500
,
1000
]]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
normalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.04
,
0.04
,
0.1
,
0.08
],
[
0.06
,
0.05
,
0.08
,
0.09
]]],
1e-5
)
class
DenormalizeBoxesTest
(
tf
.
test
.
TestCase
):
def
testDenormalizeBoxes1DWithImageShapeAsList
(
self
):
boxes
=
tf
.
constant
([
0.2
,
0.3
,
0.8
,
0.9
],
tf
.
float32
)
image_shape
=
[
50
,
100
]
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[
10
,
30
,
40
,
90
],
1e-5
)
def
testDenormalizeBoxes1DWithImageShapeAsTensor
(
self
):
boxes
=
tf
.
constant
([
0.2
,
0.3
,
0.8
,
0.9
],
tf
.
float32
)
image_shape
=
tf
.
constant
([
50
,
100
],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[
10
,
30
,
40
,
90
],
1e-5
)
def
testDenormalizeBoxes2DWithImageShapeAsList
(
self
):
boxes
=
tf
.
constant
([[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
tf
.
float32
)
image_shape
=
[
50
,
100
]
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
1e-5
)
def
testDenormalizeBoxes2DWithImageShapeAsVector
(
self
):
boxes
=
tf
.
constant
([[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
tf
.
float32
)
image_shape
=
tf
.
constant
([
50
,
100
],
dtype
=
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
1e-5
)
def
testDenormalizeBoxes2DWithImageShapeAsBroadcastableTensor
(
self
):
boxes
=
tf
.
constant
([[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
tf
.
float32
)
image_shape
=
tf
.
constant
([[
50
,
100
]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
1e-5
)
def
testDenormalizeBoxes2DWithImageShapeAsSameShapeTensor
(
self
):
boxes
=
tf
.
constant
([[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
tf
.
float32
)
image_shape
=
tf
.
constant
([[
50
,
100
],
[
50
,
100
]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
1e-5
)
def
testDenormalizeBoxes3DWithImageShapeAsList
(
self
):
boxes
=
tf
.
constant
([[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.4
,
0.4
,
1.0
,
0.8
],
[
0.6
,
0.5
,
0.8
,
0.9
]]],
tf
.
float32
)
image_shape
=
[
50
,
100
]
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
1e-5
)
def
testDenormalizeBoxes3DWithImageShapeAsVector
(
self
):
boxes
=
tf
.
constant
([[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.4
,
0.4
,
1.0
,
0.8
],
[
0.6
,
0.5
,
0.8
,
0.9
]]],
tf
.
float32
)
image_shape
=
tf
.
constant
([
50
,
100
],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
1e-5
)
def
testDenormalizeBoxes3DWithImageShapeAsBroadcastableTensor
(
self
):
boxes
=
tf
.
constant
([[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.04
,
0.04
,
0.1
,
0.08
],
[
0.06
,
0.05
,
0.08
,
0.09
]]],
tf
.
float32
)
image_shape
=
tf
.
constant
([[[
50
,
100
]],
[[
500
,
1000
]]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
1e-5
)
def
testDenormalizeBoxes3DWithImageShapeAsSameShapeTensor
(
self
):
boxes
=
tf
.
constant
([[[
0.2
,
0.3
,
0.8
,
0.9
],
[
0.6
,
0.1
,
0.8
,
0.5
]],
[[
0.04
,
0.04
,
0.1
,
0.08
],
[
0.06
,
0.05
,
0.08
,
0.09
]]],
tf
.
float32
)
image_shape
=
tf
.
constant
(
[[[
50
,
100
],
[
50
,
100
]],
[[
500
,
1000
],
[
500
,
1000
]]],
tf
.
int32
)
normalized_boxes_tpu
,
normalized_boxes_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
denormalize_boxes
,
boxes
,
image_shape
))
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
normalized_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
normalized_boxes_tpu
,
[[[
10
,
30
,
40
,
90
],
[
30
,
10
,
40
,
50
]],
[[
20
,
40
,
50
,
80
],
[
30
,
50
,
40
,
90
]]],
1e-5
)
class
ClipBoxesTest
(
tf
.
test
.
TestCase
):
def
testClipBoxesImageShapeAsList
(
self
):
boxes_data
=
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]]
image_shape
=
[
3
,
3
]
boxes
=
tf
.
constant
(
boxes_data
)
clipped_boxes_tpu
,
clipped_boxes_cpu
=
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
clip_boxes
,
boxes
,
image_shape
)
self
.
assertAllClose
(
clipped_boxes_tpu
,
clipped_boxes_cpu
)
self
.
assertAllClose
(
clipped_boxes_tpu
,
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]])
def
testClipBoxesImageShapeAsVector
(
self
):
boxes_data
=
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]]
boxes
=
tf
.
constant
(
boxes_data
)
image_shape
=
np
.
array
([
3
,
3
],
dtype
=
np
.
float32
)
clipped_boxes_tpu
,
clipped_boxes_cpu
=
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
clip_boxes
,
boxes
,
image_shape
)
self
.
assertAllClose
(
clipped_boxes_tpu
,
clipped_boxes_cpu
)
self
.
assertAllClose
(
clipped_boxes_tpu
,
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]])
def
testClipBoxesImageShapeAsTensor
(
self
):
boxes_data
=
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]]
boxes
=
tf
.
constant
(
boxes_data
)
image_shape
=
tf
.
constant
([[
3
,
3
],
[
3
,
3
],
[
3
,
3
],
[
3
,
3
],
[
3
,
3
],
[
3
,
3
]],
dtype
=
tf
.
float32
)
clipped_boxes_tpu
,
clipped_boxes_cpu
=
_transform_boxes_on_tpu_and_cpu
(
box_ops
.
clip_boxes
,
boxes
,
image_shape
)
self
.
assertAllClose
(
clipped_boxes_tpu
,
clipped_boxes_cpu
)
self
.
assertAllClose
(
clipped_boxes_tpu
,
[[
0
,
0
,
1
,
1
],
[
0
,
0.1
,
1
,
1.1
],
[
0
,
0.3
,
1
,
1.3
],
[
0
,
0.5
,
1
,
1.5
],
[
0
,
0.7
,
1
,
1.7
],
[
0
,
1.9
,
1
,
1.9
]])
class
EncodeDecodeBoxesTest
(
tf
.
test
.
TestCase
):
def
test_encode_decode_boxes
(
self
):
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
3.0
,
4.0
],
[
2.0
,
3.0
,
4.0
,
5.0
]],
[[
4.0
,
5.0
,
6.0
,
7.0
],
[
5.0
,
6.0
,
7.0
,
8.0
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
anchors
=
tf
.
constant
([[[
1.5
,
2.5
,
3.5
,
4.5
],
[
2.5
,
3.5
,
4.5
,
5.5
]],
[[
1.5
,
2.5
,
3.5
,
4.5
],
[
2.5
,
3.5
,
4.5
,
5.5
]]],
dtype
=
tf
.
float32
)
weights
=
[
1.0
,
1.0
,
1.0
,
1.0
]
def
test_fn
(
boxes
,
anchors
):
encoded_boxes
=
box_ops
.
encode_boxes
(
boxes
,
anchors
,
weights
)
decoded_boxes
=
box_ops
.
decode_boxes
(
encoded_boxes
,
anchors
,
weights
)
return
decoded_boxes
decoded_boxes_tpu
,
decoded_boxes_cpu
=
_transform_boxes_on_tpu_and_cpu
(
test_fn
,
boxes
,
anchors
)
self
.
assertNDArrayNear
(
decoded_boxes_tpu
,
decoded_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
decoded_boxes_tpu
,
boxes_np
,
1e-5
)
def
test_encode_decode_boxes_batch_broadcast
(
self
):
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
3.0
,
4.0
],
[
2.0
,
3.0
,
4.0
,
5.0
]],
[[
4.0
,
5.0
,
6.0
,
7.0
],
[
5.0
,
6.0
,
7.0
,
8.0
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
anchors
=
tf
.
constant
([[[
1.5
,
2.5
,
3.5
,
4.5
],
[
2.5
,
3.5
,
4.5
,
5.5
]]],
dtype
=
tf
.
float32
)
weights
=
[
1.0
,
1.0
,
1.0
,
1.0
]
def
test_fn
(
boxes
,
anchors
):
encoded_boxes
=
box_ops
.
encode_boxes
(
boxes
,
anchors
,
weights
)
decoded_boxes
=
box_ops
.
decode_boxes
(
encoded_boxes
,
anchors
,
weights
)
return
decoded_boxes
decoded_boxes_tpu
,
decoded_boxes_cpu
=
_transform_boxes_on_tpu_and_cpu
(
test_fn
,
boxes
,
anchors
)
self
.
assertNDArrayNear
(
decoded_boxes_tpu
,
decoded_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
decoded_boxes_tpu
,
boxes_np
,
1e-5
)
class
FilterBoxesTest
(
tf
.
test
.
TestCase
):
def
test_filter_boxes_batch
(
self
):
# boxes -> [[small, good, outside], [outside, small, good]]
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
filtered_boxes_np
=
np
.
array
([[[
0.0
,
0.0
,
0.0
,
0.0
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
0.0
,
0.0
,
0.0
,
0.0
]],
[[
0.0
,
0.0
,
0.0
,
0.0
],
[
0.0
,
0.0
,
0.0
,
0.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
scores_np
=
np
.
array
([[
0.9
,
0.7
,
0.5
],
[
0.11
,
0.22
,
0.33
]])
filtered_scores_np
=
np
.
array
([[
0.0
,
0.7
,
0.0
],
[
0.0
,
0.0
,
0.33
]])
scores
=
tf
.
constant
(
scores_np
,
dtype
=
tf
.
float32
)
image_shape
=
tf
.
expand_dims
(
tf
.
constant
([[
8
,
8
],
[
8
,
8
]],
dtype
=
tf
.
int32
),
axis
=
1
)
min_size_threshold
=
2.0
def
test_fn
(
boxes
,
scores
,
image_shape
):
filtered_boxes
,
filtered_scores
=
box_ops
.
filter_boxes
(
boxes
,
scores
,
image_shape
,
min_size_threshold
)
return
filtered_boxes
,
filtered_scores
filtered_results_tpu
,
filtered_results_cpu
=
(
_transform_boxes_on_tpu_and_cpu
(
test_fn
,
boxes
,
scores
,
image_shape
))
filtered_boxes_tpu
,
filtered_scores_tpu
=
filtered_results_tpu
filtered_boxes_cpu
,
filtered_scores_cpu
=
filtered_results_cpu
self
.
assertNDArrayNear
(
filtered_boxes_tpu
,
filtered_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
filtered_scores_tpu
,
filtered_scores_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
filtered_boxes_tpu
,
filtered_boxes_np
,
1e-5
)
self
.
assertNDArrayNear
(
filtered_scores_tpu
,
filtered_scores_np
,
1e-5
)
class
FilterBoxesByScoresTest
(
tf
.
test
.
TestCase
):
def
test_filter_boxes_by_scores_batch
(
self
):
# boxes -> [[small, good, outside], [outside, small, good]]
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
filtered_boxes_np
=
np
.
array
([[[
0.0
,
0.0
,
0.0
,
0.0
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]],
[[
0.0
,
0.0
,
0.0
,
0.0
],
[
0.0
,
0.0
,
0.0
,
0.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
scores_np
=
np
.
array
([[
0.1
,
0.7
,
0.6
],
[
0.11
,
0.22
,
0.53
]])
filtered_scores_np
=
np
.
array
([[
-
1.0
,
0.7
,
0.6
],
[
-
1.0
,
-
1.0
,
0.53
]])
scores
=
tf
.
constant
(
scores_np
,
dtype
=
tf
.
float32
)
min_score_threshold
=
0.5
def
test_fn
(
boxes
,
scores
):
filtered_boxes
,
filtered_scores
=
box_ops
.
filter_boxes_by_scores
(
boxes
,
scores
,
min_score_threshold
)
return
filtered_boxes
,
filtered_scores
filtered_results_tpu
,
filtered_results_cpu
=
_transform_boxes_on_tpu_and_cpu
(
test_fn
,
boxes
,
scores
)
filtered_boxes_tpu
,
filtered_scores_tpu
=
filtered_results_tpu
filtered_boxes_cpu
,
filtered_scores_cpu
=
filtered_results_cpu
self
.
assertNDArrayNear
(
filtered_boxes_tpu
,
filtered_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
filtered_scores_tpu
,
filtered_scores_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
filtered_boxes_tpu
,
filtered_boxes_np
,
1e-5
)
self
.
assertNDArrayNear
(
filtered_scores_tpu
,
filtered_scores_np
,
1e-5
)
class
GatherInstancesTest
(
tf
.
test
.
TestCase
):
def
test_gather_instances
(
self
):
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
indices_np
=
np
.
array
([[
2
,
0
],
[
0
,
1
]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
indices
=
tf
.
constant
(
indices_np
,
dtype
=
tf
.
int32
)
selected_boxes
=
box_ops
.
gather_instances
(
indices
,
boxes
)
expected_selected_boxes
=
np
.
array
(
[[[
7.0
,
4.0
,
9.5
,
6.5
],
[
1.0
,
2.0
,
1.5
,
2.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
]]])
self
.
assertNDArrayNear
(
expected_selected_boxes
,
selected_boxes
,
1e-5
)
def
test_gather_instances_with_multiple_inputs
(
self
):
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
classes_np
=
np
.
array
([[
1
,
2
,
3
],
[
20
,
30
,
40
]])
indices_np
=
np
.
array
([[
2
,
0
],
[
0
,
1
]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
classes
=
tf
.
constant
(
classes_np
,
dtype
=
tf
.
int32
)
indices
=
tf
.
constant
(
indices_np
,
dtype
=
tf
.
int32
)
selected_boxes
,
selected_classes
=
box_ops
.
gather_instances
(
indices
,
boxes
,
classes
)
expected_selected_boxes
=
np
.
array
(
[[[
7.0
,
4.0
,
9.5
,
6.5
],
[
1.0
,
2.0
,
1.5
,
2.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
]]])
expected_selected_classes
=
np
.
array
(
[[
3
,
1
],
[
20
,
30
]])
self
.
assertNDArrayNear
(
expected_selected_boxes
,
selected_boxes
,
1e-5
)
self
.
assertAllEqual
(
expected_selected_classes
,
selected_classes
)
class
TopKBoxesTest
(
tf
.
test
.
TestCase
):
def
test_top_k_boxes_batch1
(
self
):
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
scores_np
=
np
.
array
([[
0.9
,
0.5
,
0.7
]])
scores
=
tf
.
constant
(
scores_np
,
dtype
=
tf
.
float32
)
top_k_boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]]])
top_k_scores_np
=
np
.
array
([[
0.9
,
0.7
]])
def
test_fn
(
boxes
,
scores
):
top_k_boxes
,
top_k_scores
=
box_ops
.
top_k_boxes
(
boxes
,
scores
,
k
=
2
)
return
top_k_boxes
,
top_k_scores
top_k_results_tpu
,
top_k_results_cpu
=
_transform_boxes_on_tpu_and_cpu
(
test_fn
,
boxes
,
scores
)
top_k_boxes_tpu
,
top_k_scores_tpu
=
top_k_results_tpu
top_k_boxes_cpu
,
top_k_scores_cpu
=
top_k_results_cpu
self
.
assertNDArrayNear
(
top_k_boxes_tpu
,
top_k_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
top_k_scores_tpu
,
top_k_scores_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
top_k_boxes_tpu
,
top_k_boxes_np
,
1e-5
)
self
.
assertNDArrayNear
(
top_k_scores_tpu
,
top_k_scores_np
,
1e-5
)
def
test_top_k_boxes_batch2
(
self
):
boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
],
[
7.0
,
4.0
,
9.5
,
6.5
]],
[[
-
2.0
,
5.0
,
0.0
,
7.5
],
[
5.0
,
6.0
,
5.1
,
6.0
],
[
4.0
,
1.0
,
7.0
,
4.0
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
scores_np
=
np
.
array
([[
0.9
,
0.7
,
0.5
],
[
0.11
,
0.22
,
0.33
]])
scores
=
tf
.
constant
(
scores_np
,
dtype
=
tf
.
float32
)
top_k_boxes_np
=
np
.
array
([[[
1.0
,
2.0
,
1.5
,
2.5
],
[
2.0
,
3.0
,
4.5
,
5.5
]],
[[
4.0
,
1.0
,
7.0
,
4.0
],
[
5.0
,
6.0
,
5.1
,
6.0
]]])
top_k_scores_np
=
np
.
array
([[
0.9
,
0.7
],
[
0.33
,
0.22
]])
def
test_fn
(
boxes
,
scores
):
top_k_boxes
,
top_k_scores
=
box_ops
.
top_k_boxes
(
boxes
,
scores
,
k
=
2
)
return
top_k_boxes
,
top_k_scores
top_k_results_tpu
,
top_k_results_cpu
=
_transform_boxes_on_tpu_and_cpu
(
test_fn
,
boxes
,
scores
)
top_k_boxes_tpu
,
top_k_scores_tpu
=
top_k_results_tpu
top_k_boxes_cpu
,
top_k_scores_cpu
=
top_k_results_cpu
self
.
assertNDArrayNear
(
top_k_boxes_tpu
,
top_k_boxes_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
top_k_scores_tpu
,
top_k_scores_cpu
,
1e-5
)
self
.
assertNDArrayNear
(
top_k_boxes_tpu
,
top_k_boxes_np
,
1e-5
)
self
.
assertNDArrayNear
(
top_k_scores_tpu
,
top_k_scores_np
,
1e-5
)
class
BboxeOverlapTest
(
tf
.
test
.
TestCase
):
def
testBBoxeOverlapOpCorrectness
(
self
):
boxes_data
=
[[[
0
,
0
,
0.1
,
1
],
[
0
,
0.2
,
0.2
,
1.2
],
[
0
,
0.3
,
0.3
,
1.3
],
[
0
,
0.5
,
0.4
,
1.5
],
[
0
,
0.7
,
0.5
,
1.7
],
[
0
,
0.9
,
0.6
,
1.9
],
[
0
,
0.1
,
0.1
,
1.1
],
[
0
,
0.3
,
0.7
,
1.3
],
[
0
,
0.9
,
2
,
1.9
]],
[[
0
,
0
,
1
,
0.2
],
[
0
,
0.2
,
0.5
,
1.2
],
[
0
,
0.4
,
0.9
,
1.4
],
[
0
,
0.6
,
1.1
,
1.6
],
[
0
,
0.8
,
1.2
,
1.8
],
[
0
,
1
,
1.5
,
2
],
[
0
,
0.5
,
1
,
1
],
[
0.5
,
0.8
,
1
,
1.8
],
[
-
1
,
-
1
,
-
1
,
-
1
]]]
boxes_np
=
np
.
array
(
boxes_data
,
dtype
=
np
.
float32
)
gt_boxes_data
=
[[[
0
,
0.1
,
0.1
,
1.1
],
[
0
,
0.3
,
0.7
,
1.3
],
[
0
,
0.9
,
2
,
1.9
]],
[[
0
,
0.5
,
1
,
1
],
[
0.5
,
0.8
,
1
,
1.8
],
[
-
1
,
-
1
,
-
1
,
-
1
]]]
gt_boxes_np
=
np
.
array
(
gt_boxes_data
,
dtype
=
np
.
float32
)
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
boxes
=
tf
.
constant
(
boxes_np
)
gt_boxes
=
tf
.
constant
(
gt_boxes_np
)
iou
=
box_ops
.
bbox_overlap
(
boxes
=
boxes
,
gt_boxes
=
gt_boxes
)
iou
=
iou
.
numpy
()
self
.
assertEqual
(
iou
.
shape
,
(
2
,
9
,
3
))
self
.
assertAllEqual
(
np
.
argmax
(
iou
,
axis
=
2
),
[[
0
,
0
,
1
,
1
,
1
,
2
,
0
,
1
,
2
],
[
0
,
0
,
0
,
0
,
1
,
1
,
0
,
1
,
0
]])
def
testBBoxeOverlapOpCheckShape
(
self
):
batch_size
=
2
rpn_post_nms_topn
=
2000
gt_max_instances
=
100
boxes_np
=
np
.
random
.
rand
(
batch_size
,
rpn_post_nms_topn
,
4
).
astype
(
np
.
float32
)
gt_boxes_np
=
np
.
random
.
rand
(
batch_size
,
gt_max_instances
,
4
).
astype
(
np
.
float32
)
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
boxes
=
tf
.
constant
(
boxes_np
)
gt_boxes
=
tf
.
constant
(
gt_boxes_np
)
iou
=
box_ops
.
bbox_overlap
(
boxes
=
boxes
,
gt_boxes
=
gt_boxes
)
iou
=
iou
.
numpy
()
self
.
assertEqual
(
iou
.
shape
,
(
batch_size
,
(
rpn_post_nms_topn
),
gt_max_instances
))
def
testBBoxeOverlapOpCorrectnessWithNegativeData
(
self
):
boxes_data
=
[[[
0
,
-
0.01
,
0.1
,
1.1
],
[
0
,
0.2
,
0.2
,
5.0
],
[
0
,
-
0.01
,
0.1
,
1.
],
[
-
1
,
-
1
,
-
1
,
-
1
]]]
boxes_np
=
np
.
array
(
boxes_data
,
dtype
=
np
.
float32
)
gt_boxes_np
=
boxes_np
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
boxes
=
tf
.
constant
(
boxes_np
)
gt_boxes
=
tf
.
constant
(
gt_boxes_np
)
iou
=
box_ops
.
bbox_overlap
(
boxes
=
boxes
,
gt_boxes
=
gt_boxes
)
iou
=
iou
.
numpy
()
expected
=
np
.
array
([[[
0.99999994
,
0.0917431
,
0.9099099
,
-
1.
],
[
0.0917431
,
1.
,
0.08154944
,
-
1.
],
[
0.9099099
,
0.08154944
,
1.
,
-
1.
],
[
-
1.
,
-
1.
,
-
1.
,
-
1.
]]])
self
.
assertAllClose
(
expected
,
iou
)
class
BoxMatchingTest
(
tf
.
test
.
TestCase
):
def
test_box_matching_single
(
self
):
boxes_np
=
np
.
array
(
[[[
0
,
0
,
5
,
5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
5
,
5
,
10
,
10
],
[
7.5
,
7.5
,
12.5
,
12.5
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
gt_boxes_np
=
np
.
array
(
[[[
10
,
10
,
15
,
15
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
-
1
,
-
1
,
-
1
,
-
1
]]])
gt_boxes
=
tf
.
constant
(
gt_boxes_np
,
dtype
=
tf
.
float32
)
gt_classes_np
=
np
.
array
([[
2
,
10
,
-
1
]])
gt_classes
=
tf
.
constant
(
gt_classes_np
,
dtype
=
tf
.
int32
)
matched_gt_boxes_np
=
np
.
array
(
[[[
2.5
,
2.5
,
7.5
,
7.5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
10
,
10
,
15
,
15
]]])
matched_gt_classes_np
=
np
.
array
([[
10
,
10
,
10
,
2
]])
matched_gt_indices_np
=
np
.
array
([[
1
,
1
,
1
,
0
]])
matched_iou_np
=
np
.
array
(
[[
0.142857142857
,
1.0
,
0.142857142857
,
0.142857142857
]])
iou_np
=
np
.
array
(
[[[
0
,
0.142857142857
,
-
1.0
],
[
0
,
1.0
,
-
1.0
],
[
0
,
0.142857142857
,
-
1.0
],
[
0.142857142857
,
0
,
-
1.0
]]])
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
(
matched_gt_boxes_tpu
,
matched_gt_classes_tpu
,
matched_gt_indices_tpu
,
matched_iou_tpu
,
iou_tpu
)
=
(
box_ops
.
box_matching
(
boxes
,
gt_boxes
,
gt_classes
))
# Runs on CPU.
(
matched_gt_boxes_cpu
,
matched_gt_classes_cpu
,
matched_gt_indices_cpu
,
matched_iou_cpu
,
iou_cpu
)
=
(
box_ops
.
box_matching
(
boxes
,
gt_boxes
,
gt_classes
))
# consistency.
self
.
assertNDArrayNear
(
matched_gt_boxes_tpu
.
numpy
(),
matched_gt_boxes_cpu
.
numpy
(),
1e-5
)
self
.
assertAllEqual
(
matched_gt_classes_tpu
.
numpy
(),
matched_gt_classes_cpu
.
numpy
())
self
.
assertAllEqual
(
matched_gt_indices_tpu
.
numpy
(),
matched_gt_indices_cpu
.
numpy
())
self
.
assertNDArrayNear
(
matched_iou_tpu
.
numpy
(),
matched_iou_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
iou_tpu
.
numpy
(),
iou_cpu
.
numpy
(),
1e-5
)
# correctness.
self
.
assertNDArrayNear
(
matched_gt_boxes_tpu
.
numpy
(),
matched_gt_boxes_np
,
1e-5
)
self
.
assertAllEqual
(
matched_gt_classes_tpu
.
numpy
(),
matched_gt_classes_np
)
self
.
assertAllEqual
(
matched_gt_indices_tpu
.
numpy
(),
matched_gt_indices_np
)
self
.
assertNDArrayNear
(
matched_iou_tpu
.
numpy
(),
matched_iou_np
,
1e-5
)
self
.
assertNDArrayNear
(
iou_tpu
.
numpy
(),
iou_np
,
1e-5
)
def
test_box_matching_single_no_gt
(
self
):
boxes_np
=
np
.
array
(
[[[
0
,
0
,
5
,
5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
5
,
5
,
10
,
10
],
[
7.5
,
7.5
,
12.5
,
12.5
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
gt_boxes_np
=
np
.
array
(
[[[
-
1
,
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
,
-
1
]]])
gt_boxes
=
tf
.
constant
(
gt_boxes_np
,
dtype
=
tf
.
float32
)
gt_classes_np
=
np
.
array
([[
-
1
,
-
1
,
-
1
]])
gt_classes
=
tf
.
constant
(
gt_classes_np
,
dtype
=
tf
.
int32
)
matched_gt_boxes_np
=
np
.
array
(
[[[
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
0
]]])
matched_gt_classes_np
=
np
.
array
([[
0
,
0
,
0
,
0
]])
matched_gt_indices_np
=
np
.
array
([[
-
1
,
-
1
,
-
1
,
-
1
]])
matched_iou_np
=
np
.
array
([[
-
1
,
-
1
,
-
1
,
-
1
]])
iou_np
=
np
.
array
(
[[[
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
]]])
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
(
matched_gt_boxes_tpu
,
matched_gt_classes_tpu
,
matched_gt_indices_tpu
,
matched_iou_tpu
,
iou_tpu
)
=
(
box_ops
.
box_matching
(
boxes
,
gt_boxes
,
gt_classes
))
# Runs on CPU.
(
matched_gt_boxes_cpu
,
matched_gt_classes_cpu
,
matched_gt_indices_cpu
,
matched_iou_cpu
,
iou_cpu
)
=
(
box_ops
.
box_matching
(
boxes
,
gt_boxes
,
gt_classes
))
# consistency.
self
.
assertNDArrayNear
(
matched_gt_boxes_tpu
.
numpy
(),
matched_gt_boxes_cpu
.
numpy
(),
1e-5
)
self
.
assertAllEqual
(
matched_gt_classes_tpu
.
numpy
(),
matched_gt_classes_cpu
.
numpy
())
self
.
assertAllEqual
(
matched_gt_indices_tpu
.
numpy
(),
matched_gt_indices_cpu
.
numpy
())
self
.
assertNDArrayNear
(
matched_iou_tpu
.
numpy
(),
matched_iou_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
iou_tpu
.
numpy
(),
iou_cpu
.
numpy
(),
1e-5
)
# correctness.
self
.
assertNDArrayNear
(
matched_gt_boxes_tpu
.
numpy
(),
matched_gt_boxes_np
,
1e-5
)
self
.
assertAllEqual
(
matched_gt_classes_tpu
.
numpy
(),
matched_gt_classes_np
)
self
.
assertAllEqual
(
matched_gt_indices_tpu
.
numpy
(),
matched_gt_indices_np
)
self
.
assertNDArrayNear
(
matched_iou_tpu
.
numpy
(),
matched_iou_np
,
1e-5
)
self
.
assertNDArrayNear
(
iou_tpu
.
numpy
(),
iou_np
,
1e-5
)
def
test_box_matching_batch
(
self
):
boxes_np
=
np
.
array
(
[[[
0
,
0
,
5
,
5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
5
,
5
,
10
,
10
],
[
7.5
,
7.5
,
12.5
,
12.5
]],
[[
0
,
0
,
5
,
5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
5
,
5
,
10
,
10
],
[
7.5
,
7.5
,
12.5
,
12.5
]]])
boxes
=
tf
.
constant
(
boxes_np
,
dtype
=
tf
.
float32
)
gt_boxes_np
=
np
.
array
(
[[[
10
,
10
,
15
,
15
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
-
1
,
-
1
,
-
1
,
-
1
]],
[[
-
1
,
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
,
-
1
]]])
gt_boxes
=
tf
.
constant
(
gt_boxes_np
,
dtype
=
tf
.
float32
)
gt_classes_np
=
np
.
array
([[
2
,
10
,
-
1
],
[
-
1
,
-
1
,
-
1
]])
gt_classes
=
tf
.
constant
(
gt_classes_np
,
dtype
=
tf
.
int32
)
matched_gt_boxes_np
=
np
.
array
(
[[[
2.5
,
2.5
,
7.5
,
7.5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
2.5
,
2.5
,
7.5
,
7.5
],
[
10
,
10
,
15
,
15
]],
[[
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
0
]]])
matched_gt_classes_np
=
np
.
array
(
[[
10
,
10
,
10
,
2
],
[
0
,
0
,
0
,
0
]])
matched_gt_indices_np
=
np
.
array
(
[[
1
,
1
,
1
,
0
],
[
-
1
,
-
1
,
-
1
,
-
1
]])
matched_iou_np
=
np
.
array
(
[[
0.142857142857
,
1.0
,
0.142857142857
,
0.142857142857
],
[
-
1
,
-
1
,
-
1
,
-
1
]])
iou_np
=
np
.
array
(
[[[
0
,
0.142857142857
,
-
1.0
],
[
0
,
1.0
,
-
1.0
],
[
0
,
0.142857142857
,
-
1.0
],
[
0.142857142857
,
0
,
-
1.0
]],
[[
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
],
[
-
1
,
-
1
,
-
1
]]])
# Runs on TPU.
strategy
=
tf
.
distribute
.
experimental
.
TPUStrategy
()
with
strategy
.
scope
():
(
matched_gt_boxes_tpu
,
matched_gt_classes_tpu
,
matched_gt_indices_tpu
,
matched_iou_tpu
,
iou_tpu
)
=
(
box_ops
.
box_matching
(
boxes
,
gt_boxes
,
gt_classes
))
# Runs on CPU.
(
matched_gt_boxes_cpu
,
matched_gt_classes_cpu
,
matched_gt_indices_cpu
,
matched_iou_cpu
,
iou_cpu
)
=
(
box_ops
.
box_matching
(
boxes
,
gt_boxes
,
gt_classes
))
# consistency.
self
.
assertNDArrayNear
(
matched_gt_boxes_tpu
.
numpy
(),
matched_gt_boxes_cpu
.
numpy
(),
1e-5
)
self
.
assertAllEqual
(
matched_gt_classes_tpu
.
numpy
(),
matched_gt_classes_cpu
.
numpy
())
self
.
assertAllEqual
(
matched_gt_indices_tpu
.
numpy
(),
matched_gt_indices_cpu
.
numpy
())
self
.
assertNDArrayNear
(
matched_iou_tpu
.
numpy
(),
matched_iou_cpu
.
numpy
(),
1e-5
)
self
.
assertNDArrayNear
(
iou_tpu
.
numpy
(),
iou_cpu
.
numpy
(),
1e-5
)
# correctness.
self
.
assertNDArrayNear
(
matched_gt_boxes_tpu
.
numpy
(),
matched_gt_boxes_np
,
1e-5
)
self
.
assertAllEqual
(
matched_gt_classes_tpu
.
numpy
(),
matched_gt_classes_np
)
self
.
assertAllEqual
(
matched_gt_indices_tpu
.
numpy
(),
matched_gt_indices_np
)
self
.
assertNDArrayNear
(
matched_iou_tpu
.
numpy
(),
matched_iou_np
,
1e-5
)
self
.
assertNDArrayNear
(
iou_tpu
.
numpy
(),
iou_np
,
1e-5
)
if
__name__
==
'__main__'
:
tf
.
test
.
main
()
Prev
1
…
3
4
5
6
7
8
9
10
11
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment