CoolFace
Apppublic

karolmajek/maxdeeplab

sourceHugging Faceupdated 5y agoView on Hugging Face
0likes
panoptic_deeplab.py446 linesDownload Raw Back to decoder
1# coding=utf-82# Copyright 2021 The Deeplab2 Authors.3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8#     http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.15 16"""This file contains code to build a Panoptic-DeepLab decoder.17 18Reference:19  - [Panoptic-DeepLab: A Simple, Strong, and Fast Baseline for Bottom-Up20      Panoptic Segmentation](https://arxiv.org/pdf/1911.10194)21"""22from absl import logging23 24import tensorflow as tf25 26from deeplab2 import common27from deeplab2.model import utils28from deeplab2.model.decoder import aspp29from deeplab2.model.layers import convolutions30 31 32layers = tf.keras.layers33 34 35class PanopticDeepLabSingleDecoder(layers.Layer):36  """A single Panoptic-DeepLab decoder layer.37 38  This layer takes low- and high-level features as input and uses an ASPP39  followed by a fusion block to decode features for a single task, e.g.,40  semantic segmentation or instance segmentation.41  """42 43  def __init__(self,44               high_level_feature_name,45               low_level_feature_names,46               low_level_channels_project,47               aspp_output_channels,48               decoder_output_channels,49               atrous_rates,50               name,51               aspp_use_only_1x1_proj_conv=False,52               decoder_conv_type='depthwise_separable_conv',53               bn_layer=tf.keras.layers.BatchNormalization):54    """Initializes a single Panoptic-DeepLab decoder of layers.Layer.55 56    Args:57      high_level_feature_name: A string specifying the name of the high-level58        feature coming from an encoder.59      low_level_feature_names: A list of strings specifying the name of the60        low-level features coming from an encoder. An order from highest to61        lower level is expected, e.g. ['res3', 'res2'].62      low_level_channels_project: A list of integer specifying the number of63        filters used for processing each low_level features.64      aspp_output_channels: An integer specifying the number of filters in the65        ASPP convolution layers.66      decoder_output_channels: An integer specifying the number of filters in67        the decoder convolution layers.68      atrous_rates: A list of three integers specifying the atrous rate for the69        ASPP layers.70      name: A string specifying the name of the layer.71      aspp_use_only_1x1_proj_conv: Boolean, specifying if the ASPP five branches72        are turned off or not. If True, the ASPP module is degenerated to one73        1x1 convolution, projecting the input channels to `output_channels`.74      decoder_conv_type: String, specifying decoder convolution type. Support75        'depthwise_separable_conv' and 'standard_conv'.76      bn_layer: An optional tf.keras.layers.Layer that computes the77        normalization (default: tf.keras.layers.BatchNormalization).78 79    Raises:80      ValueError: An error occurs when the length of low_level_feature_names81        differs from the length of low_level_channels_project.82    """83    super(PanopticDeepLabSingleDecoder, self).__init__(name=name)84    self._channel_axis = 385 86    self._aspp = aspp.ASPP(87        aspp_output_channels,88        atrous_rates,89        aspp_use_only_1x1_proj_conv=aspp_use_only_1x1_proj_conv,90        name='aspp',91        bn_layer=bn_layer)92    self._high_level_feature_name = high_level_feature_name93 94    if len(low_level_feature_names) != len(low_level_channels_project):95      raise ValueError('The Panoptic-DeepLab decoder requires the same number '96                       'of low-level features as the number of low-level '97                       'projection channels. But got %d and %d.'98                       % (len(low_level_feature_names),99                          len(low_level_channels_project)))100 101    self._low_level_feature_names = low_level_feature_names102 103    for i, channels_project in enumerate(low_level_channels_project):104      # Check if channel sizes increases and issue a warning.105      if i > 0 and low_level_channels_project[i - 1] < channels_project:106        logging.warning(107            'The low level projection channels usually do not '108            'increase for features with higher spatial resolution. '109            'Please make sure, this behavior is intended.')110      current_low_level_conv_name, current_fusion_conv_name = (111          utils.get_low_level_conv_fusion_conv_current_names(i))112      utils.safe_setattr(113          self, current_low_level_conv_name, convolutions.Conv2DSame(114              channels_project,115              kernel_size=1,116              name=utils.get_layer_name(current_low_level_conv_name),117              use_bias=False,118              use_bn=True,119              bn_layer=bn_layer,120              activation='relu'))121 122      utils.safe_setattr(123          self, current_fusion_conv_name, convolutions.StackedConv2DSame(124              conv_type=decoder_conv_type,125              num_layers=1,126              output_channels=decoder_output_channels,127              kernel_size=5,128              name=utils.get_layer_name(current_fusion_conv_name),129              use_bias=False,130              use_bn=True,131              bn_layer=bn_layer,132              activation='relu'))133 134  def call(self, features, training=False):135    """Performs a forward pass.136 137    Args:138      features: An input dict of tf.Tensor with shape [batch, height, width,139        channels]. Different keys should point to different features extracted140        by the encoder, e.g. low-level or high-level features.141      training: A boolean flag indicating whether training behavior should be142        used (default: False).143 144    Returns:145      Refined features as instance of tf.Tensor.146    """147 148    high_level_features = features[self._high_level_feature_name]149    combined_features = self._aspp(high_level_features, training=training)150 151    # Fuse low-level features with high-level features.152    for i in range(len(self._low_level_feature_names)):153      current_low_level_conv_name, current_fusion_conv_name = (154          utils.get_low_level_conv_fusion_conv_current_names(i))155      # Iterate from the highest level of the low level features to the lowest156      # level, i.e. take the features with the smallest spatial size first.157      low_level_features = features[self._low_level_feature_names[i]]158      low_level_features = getattr(self, current_low_level_conv_name)(159          low_level_features, training=training)160 161      target_h = tf.shape(low_level_features)[1]162      target_w = tf.shape(low_level_features)[2]163      source_h = tf.shape(combined_features)[1]164      source_w = tf.shape(combined_features)[2]165 166      tf.assert_less(167          source_h - 1,168          target_h,169          message='Features are down-sampled during decoder.')170      tf.assert_less(171          source_w - 1,172          target_w,173          message='Features are down-sampled during decoder.')174 175      combined_features = utils.resize_align_corners(combined_features,176                                                     [target_h, target_w])177 178      combined_features = tf.concat([combined_features, low_level_features],179                                    self._channel_axis)180      combined_features = getattr(self, current_fusion_conv_name)(181          combined_features, training=training)182 183    return combined_features184 185  def reset_pooling_layer(self):186    """Resets the ASPP pooling layer to global average pooling."""187    self._aspp.reset_pooling_layer()188 189  def set_pool_size(self, pool_size):190    """Sets the pooling size of the ASPP pooling layer.191 192    Args:193      pool_size: A tuple specifying the pooling size of the ASPP pooling layer.194    """195    self._aspp.set_pool_size(pool_size)196 197  def get_pool_size(self):198    return self._aspp.get_pool_size()199 200 201class PanopticDeepLabSingleHead(layers.Layer):202  """A single PanopticDeepLab head layer.203 204  This layer takes in the enriched features from a decoder and adds two205  convolutions on top.206  """207 208  def __init__(self,209               intermediate_channels,210               output_channels,211               pred_key,212               name,213               conv_type='depthwise_separable_conv',214               bn_layer=tf.keras.layers.BatchNormalization):215    """Initializes a single PanopticDeepLab head.216 217    Args:218      intermediate_channels: An integer specifying the number of filters of the219        first 5x5 convolution.220      output_channels: An integer specifying the number of filters of the second221        1x1 convolution.222      pred_key: A string specifying the key of the output dictionary.223      name: A string specifying the name of this head.224      conv_type: String, specifying head convolution type. Support225        'depthwise_separable_conv' and 'standard_conv'.226      bn_layer: An optional tf.keras.layers.Layer that computes the227        normalization (default: tf.keras.layers.BatchNormalization).228    """229    super(PanopticDeepLabSingleHead, self).__init__(name=name)230    self._pred_key = pred_key231 232    self.conv_block = convolutions.StackedConv2DSame(233        conv_type=conv_type,234        num_layers=1,235        output_channels=intermediate_channels,236        kernel_size=5,237        name='conv_block',238        use_bias=False,239        use_bn=True,240        bn_layer=bn_layer,241        activation='relu')242    self.final_conv = layers.Conv2D(243        output_channels,244        kernel_size=1,245        name='final_conv',246        kernel_initializer=tf.keras.initializers.TruncatedNormal(stddev=0.01))247 248  def call(self, features, training=False):249    """Performs a forward pass.250 251    Args:252      features: A tf.Tensor with shape [batch, height, width, channels].253      training: A boolean flag indicating whether training behavior should be254        used (default: False).255 256    Returns:257      The dictionary containing the predictions under the specified key.258    """259    x = self.conv_block(features, training=training)260    return {self._pred_key: self.final_conv(x)}261 262 263class PanopticDeepLab(layers.Layer):264  """A Panoptic-DeepLab decoder layer.265 266  This layer takes low- and high-level features as input and uses a dual-ASPP267  and dual-decoder structure to aggregate features for semantic and instance268  segmentation. On top of the decoders, three heads are used to predict semantic269  segmentation, instance center probabilities, and instance center regression270  per pixel.271  """272 273  def __init__(self,274               decoder_options,275               panoptic_deeplab_options,276               bn_layer=tf.keras.layers.BatchNormalization):277    """Initializes a Panoptic-DeepLab decoder.278 279    Args:280      decoder_options: Decoder options as defined in config_pb2.DecoderOptions.281      panoptic_deeplab_options: Model options as defined in282        config_pb2.ModelOptions.PanopticDeeplabOptions.283      bn_layer: An optional tf.keras.layers.Layer that computes the284        normalization (default: tf.keras.layers.BatchNormalization).285    """286    super(PanopticDeepLab, self).__init__(name='PanopticDeepLab')287 288    low_level_feature_keys = [289        item.feature_key for item in panoptic_deeplab_options.low_level290    ]291    low_level_channels_project = [292        item.channels_project for item in panoptic_deeplab_options.low_level293    ]294 295    self._semantic_decoder = PanopticDeepLabSingleDecoder(296        high_level_feature_name=decoder_options.feature_key,297        low_level_feature_names=low_level_feature_keys,298        low_level_channels_project=low_level_channels_project,299        aspp_output_channels=decoder_options.aspp_channels,300        decoder_output_channels=decoder_options.decoder_channels,301        atrous_rates=decoder_options.atrous_rates,302        name='semantic_decoder',303        aspp_use_only_1x1_proj_conv=decoder_options.aspp_use_only_1x1_proj_conv,304        decoder_conv_type=decoder_options.decoder_conv_type,305        bn_layer=bn_layer)306    self._semantic_head = PanopticDeepLabSingleHead(307        panoptic_deeplab_options.semantic_head.head_channels,308        panoptic_deeplab_options.semantic_head.output_channels,309        common.PRED_SEMANTIC_LOGITS_KEY,310        name='semantic_head',311        conv_type=panoptic_deeplab_options.semantic_head.head_conv_type,312        bn_layer=bn_layer)313 314    self._instance_decoder = None315    self._instance_center_head = None316    self._instance_regression_head = None317 318    if panoptic_deeplab_options.instance.enable:319      if panoptic_deeplab_options.instance.low_level_override:320        low_level_options = panoptic_deeplab_options.instance.low_level_override321      else:322        low_level_options = panoptic_deeplab_options.low_level323 324      # If instance_decoder is set, use those options; otherwise reuse the325      # architecture as defined for the semantic decoder.326      if panoptic_deeplab_options.instance.HasField(327          'instance_decoder_override'):328        decoder_options = (panoptic_deeplab_options.instance329                           .instance_decoder_override)330 331      low_level_feature_keys = [item.feature_key for item in low_level_options]332      low_level_channels_project = [333          item.channels_project for item in low_level_options334      ]335 336      self._instance_decoder = PanopticDeepLabSingleDecoder(337          high_level_feature_name=decoder_options.feature_key,338          low_level_feature_names=low_level_feature_keys,339          low_level_channels_project=low_level_channels_project,340          aspp_output_channels=decoder_options.aspp_channels,341          decoder_output_channels=decoder_options.decoder_channels,342          atrous_rates=decoder_options.atrous_rates,343          name='instance_decoder',344          aspp_use_only_1x1_proj_conv=(345              decoder_options.aspp_use_only_1x1_proj_conv),346          decoder_conv_type=decoder_options.decoder_conv_type,347          bn_layer=bn_layer)348      self._instance_center_head = PanopticDeepLabSingleHead(349          panoptic_deeplab_options.instance.center_head.head_channels,350          panoptic_deeplab_options.instance.center_head.output_channels,351          common.PRED_CENTER_HEATMAP_KEY,352          name='instance_center_head',353          conv_type=(354              panoptic_deeplab_options.instance.center_head.head_conv_type),355          bn_layer=bn_layer)356      self._instance_regression_head = PanopticDeepLabSingleHead(357          panoptic_deeplab_options.instance.regression_head.head_channels,358          panoptic_deeplab_options.instance.regression_head.output_channels,359          common.PRED_OFFSET_MAP_KEY,360          name='instance_regression_head',361          conv_type=(362              panoptic_deeplab_options.instance.regression_head.head_conv_type),363          bn_layer=bn_layer)364 365  def reset_pooling_layer(self):366    """Resets the ASPP pooling layers to global average pooling."""367    self._semantic_decoder.reset_pooling_layer()368    if self._instance_decoder is not None:369      self._instance_decoder.reset_pooling_layer()370 371  def set_pool_size(self, pool_size):372    """Sets the pooling size of the ASPP pooling layers.373 374    Args:375      pool_size: A tuple specifying the pooling size of the ASPP pooling layers.376    """377    self._semantic_decoder.set_pool_size(pool_size)378    if self._instance_decoder is not None:379      self._instance_decoder.set_pool_size(pool_size)380 381  def get_pool_size(self):382    return self._semantic_decoder.get_pool_size()383 384  @property385  def checkpoint_items(self):386    items = {387        common.CKPT_SEMANTIC_DECODER:388            self._semantic_decoder,389        common.CKPT_SEMANTIC_HEAD_WITHOUT_LAST_LAYER:390            self._semantic_head.conv_block,391        common.CKPT_SEMANTIC_LAST_LAYER:392            self._semantic_head.final_conv393    }394    if self._instance_decoder is not None:395      instance_items = {396          common.CKPT_INSTANCE_DECODER:397              self._instance_decoder,398          common.CKPT_INSTANCE_CENTER_HEAD_WITHOUT_LAST_LAYER:399              self._instance_center_head.conv_block,400          common.CKPT_INSTANCE_CENTER_HEAD_LAST_LAYER:401              self._instance_center_head.final_conv,402          common.CKPT_INSTANCE_REGRESSION_HEAD_WITHOUT_LAST_LAYER:403              self._instance_regression_head.conv_block,404          common.CKPT_INSTANCE_REGRESSION_HEAD_LAST_LAYER:405              self._instance_regression_head.final_conv,406      }407      items.update(instance_items)408    return items409 410  def call(self, features, training=False):411    """Performs a forward pass.412 413    Args:414      features: An input dict of tf.Tensor with shape [batch, height, width,415        channels]. Different keys should point to different features extracted416        by the encoder, e.g. low-level or high-level features.417      training: A boolean flag indicating whether training behavior should be418        used (default: False).419 420    Returns:421      A dictionary containing the results of the semantic segmentation head and422        depending on the configuration also of the instance segmentation head.423    """424 425    semantic_features = self._semantic_decoder(features, training=training)426    results = self._semantic_head(semantic_features, training=training)427 428    if self._instance_decoder is not None:429      instance_features = self._instance_decoder(features, training=training)430      instance_center_predictions = self._instance_center_head(431          instance_features, training=training)432      instance_regression_predictions = self._instance_regression_head(433          instance_features, training=training)434 435      if results.keys() & instance_center_predictions.keys():436        raise ValueError('The keys of the semantic branch and the instance '437                         'center branch overlap. Please use unique keys.')438      results.update(instance_center_predictions)439 440      if results.keys() & instance_regression_predictions.keys():441        raise ValueError('The keys of the semantic branch and the instance '442                         'regression branch overlap. Please use unique keys.')443      results.update(instance_regression_predictions)444 445    return results446