class_docstr: Batch processing op that assembles mosaic images.
  
  The op expects three batch dimensions:
  [device count, local batch size, (mosaic size) ** 2].
  
  The op then concatenates the examples from the third batch dim into mosaic
  images and merges labels.
  
  Mosaic approach:
  1. Run deterministic_data.create_dataset with standard preprocessing and
     batch to num_tiles. But do not apply GV-to-Scenic conversion.
  2. Convert each batch into one single image.
  3. Apply another round of pad-or-crop preprocessing.
  4. Apply GV-to-Sceinic conversion.
  5. Batch to final batch size as in deterministic_data.create_dataset.
code: def __call__(
      self, features: image_ops.Features
  ) -> image_ops.Features:
      # Merge images:
      features[modalities.IMAGE] = _image_tiles_to_mosaic(
          features[modalities.IMAGE], self.mosaic_size
      )
  
      # Merge scalar features:
      instance_padding_mask = tf.not_equal(
          features[modalities.INSTANCE_LABELS], -1
      )
  
      for k in self.instance_feature_keys:
          if k in features:
              features[k] = _merge_instances(
                  features[k], instance_padding_mask
              )
  
      # Special cases:
      if modalities.NEGATIVE_LABELS in features:
          features[modalities.NEGATIVE_LABELS] = _merge_instances(
              features[modalities.NEGATIVE_LABELS],
              tf.not_equal(features[modalities.NEGATIVE_LABELS], -1),
          )
  
          # Update negative labels to account for instances in all tiles:
          features[modalities.NEGATIVE_LABELS] = tf.sparse.to_dense(
              tf.sets.difference(
                  features[modalities.NEGATIVE_LABELS][tf.newaxis, ...],
                  tf.cast(
                      features[modalities.INSTANCE_LABELS][
                          tf.newaxis, ...
                      ],
                      features[modalities.NEGATIVE_LABELS].dtype,
                  ),
              )
          )[
              0
          ]  # pytype: disable=attribute-error  # allow-recursive-types
  
      if modalities.NEGATIVE_TEXT_LABELS in features:
          features[modalities.NEGATIVE_TEXT_LABELS] = _merge_instances(
              features[modalities.NEGATIVE_TEXT_LABELS],
              tf.not_equal(
                  features[modalities.NEGATIVE_TEXT_LABELS], ""
              ),
          )
  
          # Update negative labels to account for instances in all tiles:
          features[
              modalities.NEGATIVE_TEXT_LABELS
          ] = tf.sparse.to_dense(
              tf.sets.difference(
                  features[modalities.NEGATIVE_TEXT_LABELS][
                      tf.newaxis, ...
                  ],
                  features[modalities.INSTANCE_TEXT_LABELS][
                      tf.newaxis, ...
                  ],
              )
          )[
              0
          ]
  
      if modalities.NOT_EXHAUSTIVE_LABELS in features:
          features[modalities.NOT_EXHAUSTIVE_LABELS] = _merge_instances(
              features[modalities.NOT_EXHAUSTIVE_LABELS],
              tf.not_equal(
                  features[modalities.NOT_EXHAUSTIVE_LABELS], -1
              ),
          )
  
      if modalities.CROWD in features:
          features[modalities.CROWD] = _merge_instances(
              features[modalities.CROWD],
              tf.not_equal(features[modalities.CROWD], -1),
          )
  
      # Merge boxes:
      if modalities.BOXES in features:
          features[modalities.BOXES] = _box_tiles_to_mosaic(
              features[modalities.BOXES],
              self.mosaic_size,
              instance_padding_mask,
          )
  
      if image_ops.SEED_KEY in features:
          features[image_ops.SEED_KEY] = features[image_ops.SEED_KEY][0]
  
      return features
  
file_path: scenic/scenic/projects/owl_vit/preprocessing/mosaic.py
imports: import dataclasses
  from typing import Tuple
  from scenic.projects.owl_vit.preprocessing import image_ops
  from scenic.projects.owl_vit.preprocessing import modalities
  import tensorflow
label_desc: Use image node_id 1 for calling the CreateMosaic obj's underlying member method code with example usage: obj.__call__(features) and returns: features