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
c18fc1bb
Unverified
Commit
c18fc1bb
authored
Oct 09, 2021
by
srihari-humbarwadi
Browse files
added `PanopticFPNFusion`
parent
d3998b07
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
174 additions
and
18 deletions
+174
-18
official/vision/beta/configs/semantic_segmentation.py
official/vision/beta/configs/semantic_segmentation.py
+4
-2
official/vision/beta/modeling/heads/segmentation_heads.py
official/vision/beta/modeling/heads/segmentation_heads.py
+34
-6
official/vision/beta/modeling/heads/segmentation_heads_test.py
...ial/vision/beta/modeling/heads/segmentation_heads_test.py
+26
-9
official/vision/beta/modeling/layers/nn_layers.py
official/vision/beta/modeling/layers/nn_layers.py
+110
-1
No files found.
official/vision/beta/configs/semantic_segmentation.py
View file @
c18fc1bb
...
@@ -65,11 +65,13 @@ class SegmentationHead(hyperparams.Config):
...
@@ -65,11 +65,13 @@ class SegmentationHead(hyperparams.Config):
use_depthwise_convolution
:
bool
=
False
use_depthwise_convolution
:
bool
=
False
prediction_kernel_size
:
int
=
1
prediction_kernel_size
:
int
=
1
upsample_factor
:
int
=
1
upsample_factor
:
int
=
1
feature_fusion
:
Optional
[
str
]
=
None
# None, deeplabv3plus, or pyramid_fusion
feature_fusion
:
Optional
[
str
]
=
None
# None, deeplabv3plus,
panoptic_fpn_fusion
or pyramid_fusion
# deeplabv3plus feature fusion params
# deeplabv3plus feature fusion params
low_level
:
Union
[
int
,
str
]
=
2
low_level
:
Union
[
int
,
str
]
=
2
low_level_num_filters
:
int
=
48
low_level_num_filters
:
int
=
48
# panoptic_fpn_fusion params
decoder_min_level
:
Optional
[
Union
[
int
,
str
]]
=
None
decoder_max_level
:
Optional
[
Union
[
int
,
str
]]
=
None
@
dataclasses
.
dataclass
@
dataclasses
.
dataclass
class
SemanticSegmentationModel
(
hyperparams
.
Config
):
class
SemanticSegmentationModel
(
hyperparams
.
Config
):
...
...
official/vision/beta/modeling/heads/segmentation_heads.py
View file @
c18fc1bb
...
@@ -21,7 +21,7 @@ from official.vision.beta.modeling.layers import nn_layers
...
@@ -21,7 +21,7 @@ from official.vision.beta.modeling.layers import nn_layers
from
official.vision.beta.ops
import
spatial_transform_ops
from
official.vision.beta.ops
import
spatial_transform_ops
@
tf
.
keras
.
utils
.
register_keras_serializable
(
package
=
'Vision'
)
#
@tf.keras.utils.register_keras_serializable(package='Vision')
class
SegmentationHead
(
tf
.
keras
.
layers
.
Layer
):
class
SegmentationHead
(
tf
.
keras
.
layers
.
Layer
):
"""Creates a segmentation head."""
"""Creates a segmentation head."""
...
@@ -35,8 +35,11 @@ class SegmentationHead(tf.keras.layers.Layer):
...
@@ -35,8 +35,11 @@ class SegmentationHead(tf.keras.layers.Layer):
prediction_kernel_size
:
int
=
1
,
prediction_kernel_size
:
int
=
1
,
upsample_factor
:
int
=
1
,
upsample_factor
:
int
=
1
,
feature_fusion
:
Optional
[
str
]
=
None
,
feature_fusion
:
Optional
[
str
]
=
None
,
decoder_min_level
:
Optional
[
int
]
=
None
,
decoder_max_level
:
Optional
[
int
]
=
None
,
low_level
:
int
=
2
,
low_level
:
int
=
2
,
low_level_num_filters
:
int
=
48
,
low_level_num_filters
:
int
=
48
,
num_decoder_filters
:
int
=
256
,
activation
:
str
=
'relu'
,
activation
:
str
=
'relu'
,
use_sync_bn
:
bool
=
False
,
use_sync_bn
:
bool
=
False
,
norm_momentum
:
float
=
0.99
,
norm_momentum
:
float
=
0.99
,
...
@@ -60,15 +63,24 @@ class SegmentationHead(tf.keras.layers.Layer):
...
@@ -60,15 +63,24 @@ class SegmentationHead(tf.keras.layers.Layer):
prediction layer.
prediction layer.
upsample_factor: An `int` number to specify the upsampling factor to
upsample_factor: An `int` number to specify the upsampling factor to
generate finer mask. Default 1 means no upsampling is applied.
generate finer mask. Default 1 means no upsampling is applied.
feature_fusion: One of `deeplabv3plus`, `pyramid_fusion`, or None. If
feature_fusion: One of `deeplabv3plus`, `pyramid_fusion`,
`deeplabv3plus`, features from decoder_features[level] will be fused
`panoptic_fpn_fusion`, or None. If `deeplabv3plus`, features from
with low level feature maps from backbone. If `pyramid_fusion`,
decoder_features[level] will be fused with low level feature maps from
multiscale features will be resized and fused at the target level.
backbone. If `pyramid_fusion`, multiscale features will be resized and
fused at the target level.
decoder_min_level: An `int` of minimum level from decoder to use in
feature fusion. It is only used when feature_fusion is set to
`panoptic_fpn_fusion`.
decoder_max_level: An `int` of maximum level from decoder to use in
feature fusion. It is only used when feature_fusion is set to
`panoptic_fpn_fusion`.
low_level: An `int` of backbone level to be used for feature fusion. It is
low_level: An `int` of backbone level to be used for feature fusion. It is
used when feature_fusion is set to `deeplabv3plus`.
used when feature_fusion is set to `deeplabv3plus`.
low_level_num_filters: An `int` of reduced number of filters for the low
low_level_num_filters: An `int` of reduced number of filters for the low
level features before fusing it with higher level features. It is only
level features before fusing it with higher level features. It is only
used when feature_fusion is set to `deeplabv3plus`.
used when feature_fusion is set to `deeplabv3plus`.
num_decoder_filters: An `int` of number of filters in the decoder outputs.
It is only used when feature_fusion is set to `panoptic_fpn_fusion`.
activation: A `str` that indicates which activation is used, e.g. 'relu',
activation: A `str` that indicates which activation is used, e.g. 'relu',
'swish', etc.
'swish', etc.
use_sync_bn: A `bool` that indicates whether to use synchronized batch
use_sync_bn: A `bool` that indicates whether to use synchronized batch
...
@@ -91,14 +103,17 @@ class SegmentationHead(tf.keras.layers.Layer):
...
@@ -91,14 +103,17 @@ class SegmentationHead(tf.keras.layers.Layer):
'prediction_kernel_size'
:
prediction_kernel_size
,
'prediction_kernel_size'
:
prediction_kernel_size
,
'upsample_factor'
:
upsample_factor
,
'upsample_factor'
:
upsample_factor
,
'feature_fusion'
:
feature_fusion
,
'feature_fusion'
:
feature_fusion
,
'decoder_min_level'
:
decoder_min_level
,
'decoder_max_level'
:
decoder_max_level
,
'low_level'
:
low_level
,
'low_level'
:
low_level
,
'low_level_num_filters'
:
low_level_num_filters
,
'low_level_num_filters'
:
low_level_num_filters
,
'num_decoder_filters'
:
num_decoder_filters
,
'activation'
:
activation
,
'activation'
:
activation
,
'use_sync_bn'
:
use_sync_bn
,
'use_sync_bn'
:
use_sync_bn
,
'norm_momentum'
:
norm_momentum
,
'norm_momentum'
:
norm_momentum
,
'norm_epsilon'
:
norm_epsilon
,
'norm_epsilon'
:
norm_epsilon
,
'kernel_regularizer'
:
kernel_regularizer
,
'kernel_regularizer'
:
kernel_regularizer
,
'bias_regularizer'
:
bias_regularizer
,
'bias_regularizer'
:
bias_regularizer
}
}
if
tf
.
keras
.
backend
.
image_data_format
()
==
'channels_last'
:
if
tf
.
keras
.
backend
.
image_data_format
()
==
'channels_last'
:
self
.
_bn_axis
=
-
1
self
.
_bn_axis
=
-
1
...
@@ -141,6 +156,17 @@ class SegmentationHead(tf.keras.layers.Layer):
...
@@ -141,6 +156,17 @@ class SegmentationHead(tf.keras.layers.Layer):
self
.
_dlv3p_norm
=
bn_op
(
self
.
_dlv3p_norm
=
bn_op
(
name
=
'segmentation_head_deeplabv3p_fusion_norm'
,
**
bn_kwargs
)
name
=
'segmentation_head_deeplabv3p_fusion_norm'
,
**
bn_kwargs
)
elif
self
.
_config_dict
[
'feature_fusion'
]
==
'panoptic_fpn_fusion'
:
self
.
_panoptic_fpn_fusion
=
nn_layers
.
PanopticFPNFusion
(
min_level
=
self
.
_config_dict
[
'decoder_min_level'
],
max_level
=
self
.
_config_dict
[
'decoder_max_level'
],
target_level
=
self
.
_config_dict
[
'level'
],
num_filters
=
self
.
_config_dict
[
'num_filters'
],
num_fpn_filters
=
self
.
_config_dict
[
'num_decoder_filters'
],
activation
=
self
.
_config_dict
[
'activation'
],
kernel_regularizer
=
self
.
_config_dict
[
'kernel_regularizer'
],
bias_regularizer
=
self
.
_config_dict
[
'bias_regularizer'
])
# Segmentation head layers.
# Segmentation head layers.
self
.
_convs
=
[]
self
.
_convs
=
[]
self
.
_norms
=
[]
self
.
_norms
=
[]
...
@@ -210,6 +236,8 @@ class SegmentationHead(tf.keras.layers.Layer):
...
@@ -210,6 +236,8 @@ class SegmentationHead(tf.keras.layers.Layer):
elif
self
.
_config_dict
[
'feature_fusion'
]
==
'pyramid_fusion'
:
elif
self
.
_config_dict
[
'feature_fusion'
]
==
'pyramid_fusion'
:
x
=
nn_layers
.
pyramid_feature_fusion
(
decoder_output
,
x
=
nn_layers
.
pyramid_feature_fusion
(
decoder_output
,
self
.
_config_dict
[
'level'
])
self
.
_config_dict
[
'level'
])
elif
self
.
_config_dict
[
'feature_fusion'
]
==
'panoptic_fpn_fusion'
:
x
=
self
.
_panoptic_fpn_fusion
(
decoder_output
)
else
:
else
:
x
=
decoder_output
[
str
(
self
.
_config_dict
[
'level'
])]
x
=
decoder_output
[
str
(
self
.
_config_dict
[
'level'
])]
...
...
official/vision/beta/modeling/heads/segmentation_heads_test.py
View file @
c18fc1bb
...
@@ -22,24 +22,41 @@ import tensorflow as tf
...
@@ -22,24 +22,41 @@ import tensorflow as tf
from
official.vision.beta.modeling.heads
import
segmentation_heads
from
official.vision.beta.modeling.heads
import
segmentation_heads
class
SegmentationHeadTest
(
parameterized
.
TestCase
,
tf
.
test
.
TestCase
):
class
SegmentationHeadTest
(
parameterized
.
TestCase
,
tf
.
test
.
TestCase
):
@
parameterized
.
parameters
(
@
parameterized
.
parameters
(
(
2
,
'pyramid_fusion'
),
(
2
,
'pyramid_fusion'
,
None
,
None
),
(
3
,
'pyramid_fusion'
),
(
3
,
'pyramid_fusion'
,
None
,
None
),
)
(
2
,
'panoptic_fpn_fusion'
,
2
,
5
),
def
test_forward
(
self
,
level
,
feature_fusion
):
(
2
,
'panoptic_fpn_fusion'
,
2
,
6
),
head
=
segmentation_heads
.
SegmentationHead
(
(
3
,
'panoptic_fpn_fusion'
,
3
,
5
),
num_classes
=
10
,
level
=
level
,
feature_fusion
=
feature_fusion
)
(
3
,
'panoptic_fpn_fusion'
,
3
,
6
))
def
test_forward
(
self
,
level
,
feature_fusion
,
decoder_min_level
,
decoder_max_level
):
backbone_features
=
{
backbone_features
=
{
'3'
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
'3'
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
'4'
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
'4'
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
'5'
:
np
.
random
.
rand
(
2
,
32
,
32
,
16
),
}
}
decoder_features
=
{
decoder_features
=
{
'3'
:
np
.
random
.
rand
(
2
,
128
,
128
,
16
),
'3'
:
np
.
random
.
rand
(
2
,
128
,
128
,
64
),
'4'
:
np
.
random
.
rand
(
2
,
64
,
64
,
16
),
'4'
:
np
.
random
.
rand
(
2
,
64
,
64
,
64
),
'5'
:
np
.
random
.
rand
(
2
,
32
,
32
,
64
),
'6'
:
np
.
random
.
rand
(
2
,
16
,
16
,
64
),
}
}
if
feature_fusion
==
'panoptic_fpn_fusion'
:
backbone_features
[
'2'
]
=
np
.
random
.
rand
(
2
,
256
,
256
,
16
)
decoder_features
[
'2'
]
=
np
.
random
.
rand
(
2
,
256
,
256
,
64
)
head
=
segmentation_heads
.
SegmentationHead
(
num_classes
=
10
,
level
=
level
,
feature_fusion
=
feature_fusion
,
decoder_min_level
=
decoder_min_level
,
decoder_max_level
=
decoder_max_level
,
num_decoder_filters
=
64
)
logits
=
head
(
backbone_features
,
decoder_features
)
logits
=
head
(
backbone_features
,
decoder_features
)
if
level
in
decoder_features
:
if
level
in
decoder_features
:
...
...
official/vision/beta/modeling/layers/nn_layers.py
View file @
c18fc1bb
...
@@ -13,12 +13,14 @@
...
@@ -13,12 +13,14 @@
# limitations under the License.
# limitations under the License.
"""Contains common building blocks for neural networks."""
"""Contains common building blocks for neural networks."""
from
typing
import
Callable
,
Dict
,
List
,
Optional
,
Tuple
,
Union
from
typing
import
Any
,
Callable
,
Dict
,
List
,
Mapping
,
Optional
,
Tuple
,
Union
from
absl
import
logging
from
absl
import
logging
import
tensorflow
as
tf
import
tensorflow
as
tf
import
tensorflow_addons
as
tfa
from
official.modeling
import
tf_utils
from
official.modeling
import
tf_utils
from
official.vision.beta.ops
import
spatial_transform_ops
# Type annotations.
# Type annotations.
...
@@ -308,6 +310,113 @@ def pyramid_feature_fusion(inputs, target_level):
...
@@ -308,6 +310,113 @@ def pyramid_feature_fusion(inputs, target_level):
return
tf
.
math
.
add_n
(
resampled_feats
)
return
tf
.
math
.
add_n
(
resampled_feats
)
class
PanopticFPNFusion
(
tf
.
keras
.
Model
):
"""Creates a Panoptic FPN feature Fusion layer.
This implements feature fusion for semantic segmentation head from the paper:
Alexander Kirillov, Ross Girshick, Kaiming He and Piotr Dollar.
Panoptic Feature Pyramid Networks.
(https://arxiv.org/pdf/1901.02446.pdf)
"""
def
__init__
(
self
,
min_level
:
int
=
2
,
max_level
:
int
=
5
,
target_level
:
int
=
2
,
num_filters
:
int
=
128
,
num_fpn_filters
:
int
=
256
,
activation
:
str
=
'relu'
,
kernel_regularizer
:
Optional
[
tf
.
keras
.
regularizers
.
Regularizer
]
=
None
,
bias_regularizer
:
Optional
[
tf
.
keras
.
regularizers
.
Regularizer
]
=
None
,
**
kwargs
):
"""Initializes panoptic FPN feature fusion layer.
Args:
min_level: An `int` of minimum level to use in feature fusion.
max_level: An `int` of maximum level to use in feature fusion.
target_level: An `int` of the target feature level for feature fusion..
num_filters: An `int` number of filters in conv2d layers.
num_fpn_filters: An `int` number of filters in the FPN outputs
activation: A `str` name of the activation function.
kernel_regularizer: A `tf.keras.regularizers.Regularizer` object for
Conv2D. Default is None.
bias_regularizer: A `tf.keras.regularizers.Regularizer` object for Conv2D.
**kwargs: Additional keyword arguments to be passed.
Returns:
A `float` `tf.Tensor` of shape [batch_size, feature_height, feature_width,
feature_channel].
"""
if
target_level
>
max_level
:
raise
ValueError
(
'target_level should be less than max_level'
)
self
.
_config_dict
=
{
'min_level'
:
min_level
,
'max_level'
:
max_level
,
'target_level'
:
target_level
,
'num_filters'
:
num_filters
,
'num_fpn_filters'
:
num_fpn_filters
,
'activation'
:
activation
,
'kernel_regularizer'
:
kernel_regularizer
,
'bias_regularizer'
:
bias_regularizer
,
}
norm
=
tfa
.
layers
.
GroupNormalization
conv2d
=
tf
.
keras
.
layers
.
Conv2D
activation_fn
=
tf
.
keras
.
layers
.
Activation
(
tf_utils
.
get_activation
(
activation
))
if
tf
.
keras
.
backend
.
image_data_format
()
==
'channels_last'
:
norm_axis
=
-
1
else
:
norm_axis
=
1
inputs
=
self
.
_build_inputs
(
num_fpn_filters
,
min_level
,
max_level
)
upscaled_features
=
[]
for
level
in
range
(
min_level
,
max_level
+
1
):
num_conv_layers
=
max
(
1
,
level
-
target_level
)
x
=
inputs
[
str
(
level
)]
for
i
in
range
(
num_conv_layers
):
x
=
conv2d
(
filters
=
num_filters
,
kernel_size
=
3
,
padding
=
'same'
,
kernel_initializer
=
tf
.
keras
.
initializers
.
VarianceScaling
(),
kernel_regularizer
=
kernel_regularizer
,
bias_regularizer
=
bias_regularizer
)(
x
)
x
=
norm
(
groups
=
32
,
axis
=
norm_axis
)(
x
)
x
=
activation_fn
(
x
)
if
not
level
==
target_level
:
x
=
spatial_transform_ops
.
nearest_upsampling
(
x
,
scale
=
2
)
upscaled_features
.
append
(
x
)
fused_features
=
tf
.
math
.
add_n
(
upscaled_features
)
self
.
_output_specs
=
{
str
(
target_level
):
fused_features
.
get_shape
()}
super
(
PanopticFPNFusion
,
self
).
__init__
(
inputs
=
inputs
,
outputs
=
fused_features
,
**
kwargs
)
def
_build_inputs
(
self
,
num_filters
:
int
,
min_level
:
int
,
max_level
:
int
):
inputs
=
{}
for
level
in
range
(
min_level
,
max_level
+
1
):
inputs
[
str
(
level
)]
=
tf
.
keras
.
Input
(
shape
=
[
None
,
None
,
num_filters
])
return
inputs
def
get_config
(
self
)
->
Mapping
[
str
,
Any
]:
return
self
.
_config_dict
@
classmethod
def
from_config
(
cls
,
config
,
custom_objects
=
None
):
return
cls
(
**
config
)
@
property
def
output_specs
(
self
)
->
Mapping
[
str
,
tf
.
TensorShape
]:
"""A dict of {level: TensorShape} pairs for the model output."""
return
self
.
_output_specs
@
tf
.
keras
.
utils
.
register_keras_serializable
(
package
=
'Vision'
)
@
tf
.
keras
.
utils
.
register_keras_serializable
(
package
=
'Vision'
)
class
Scale
(
tf
.
keras
.
layers
.
Layer
):
class
Scale
(
tf
.
keras
.
layers
.
Layer
):
"""Scales the input by a trainable scalar weight.
"""Scales the input by a trainable scalar weight.
...
...
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