code: def _normalize_number_fields(pb):
      """Normalizes types and precisions of number fields in a protocol buffer.
  
      Due to subtleties in the python protocol buffer implementation, it is possible
      for values to have different types and precision depending on whether they
      were set and retrieved directly or deserialized from a protobuf. This function
      normalizes integer values to ints and longs based on width, 32-bit floats to
      five digits of precision to account for python always storing them as 64-bit,
      and ensures doubles are floating point for when they're set to integers.
      Modifies pb in place. Recurses into nested objects. https://github.com/tensorf
      low/tensorflow/blob/master/tensorflow/python/util/protobuf/compare.py#L118
  
      Args:
        pb: proto2 message.
  
      Returns:
        the given pb, modified in place.
      """
      for desc, values in pb.ListFields():
          is_repeated = True
          if desc.label != descriptor.FieldDescriptor.LABEL_REPEATED:
              is_repeated = False
              values = [values]
  
          normalized_values = None
  
          # We force 32-bit values to int and 64-bit values to long to make
          # alternate implementations where the distinction is more significant
          # (e.g. the C++ implementation) simpler.
          if desc.type in (
              descriptor.FieldDescriptor.TYPE_INT64,
              descriptor.FieldDescriptor.TYPE_UINT64,
              descriptor.FieldDescriptor.TYPE_SINT64,
          ):
              normalized_values = [int(x) for x in values]
          elif desc.type in (
              descriptor.FieldDescriptor.TYPE_INT32,
              descriptor.FieldDescriptor.TYPE_UINT32,
              descriptor.FieldDescriptor.TYPE_SINT32,
              descriptor.FieldDescriptor.TYPE_ENUM,
          ):
              normalized_values = [int(x) for x in values]
          elif desc.type == descriptor.FieldDescriptor.TYPE_FLOAT:
              normalized_values = [round(x, 4) for x in values]
          elif desc.type == descriptor.FieldDescriptor.TYPE_DOUBLE:
              normalized_values = [round(float(x), 6) for x in values]
  
          if normalized_values is not None:
              if is_repeated:
                  pb.ClearField(desc.name)
                  getattr(pb, desc.name).extend(normalized_values)
              else:
                  setattr(pb, desc.name, normalized_values[0])
  
          if (
              desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE
              or desc.type == descriptor.FieldDescriptor.TYPE_GROUP
          ):
              if (
                  desc.type == descriptor.FieldDescriptor.TYPE_MESSAGE
                  and desc.message_type.has_options
                  and desc.message_type.GetOptions().map_entry
              ):
                  # This is a map, only recurse if the values have a message type.
                  if (
                      desc.message_type.fields_by_number[2].type
                      == descriptor.FieldDescriptor.TYPE_MESSAGE
                  ):
                      for v in six.itervalues(values):
                          _normalize_number_fields(v)
              else:
                  for v in values:
                      # recursive step
                      _normalize_number_fields(v)
  
      return pb
  
file_path: mediapipe/mediapipe/tasks/python/test/test_utils.py
imports: import difflib
  import os
  from absl import flags
  import six
  from google.protobuf import descriptor
  from google.protobuf import descriptor_pool
  from google.protobuf import text_format
  from mediapipe.python._framework_bindings import image
  from mediapipe.python._framework_bindings import image_frame
label_desc: Use image node_id 5 for calling a global function with example usage: _normalize_number_fields(pb) and returns: pb