Esempio n. 1
0
    def test_populate_create_from_metadata_info_should_succeed(self):
        model_buffer = test_utils.load_file(_MODEL)
        general_md = metadata_info.GeneralMd(name=_MODEL_NAME)
        input_md = metadata_info.TensorMd(name=_INPUT_NAME)
        output_md = metadata_info.TensorMd(name=_OUTPUT_NAME)

        writer = metadata_writer.MetadataWriter.create_from_metadata_info(
            model_buffer, general_md, [input_md], [output_md], [_LABEL_FILE])
        model_with_metadata = writer.populate()

        self._assert_correct_metadata(model_with_metadata,
                                      _EXPECTED_META_INFO_JSON)
Esempio n. 2
0
 def add_embedding_output(self,
                          name: str = _OUTPUT_EMBEDDING_NAME,
                          description: str = _OUTPUT_EMBEDDING_DESCRIPTION):
     """Marks the next output tensor as embedding."""
     output_md = metadata_info.TensorMd(name=name, description=description)
     self._output_mds.append(output_md)
     return self
  def test_create_from_metadata_info_with_input_tensor_name_should_succeed(
      self):
    model_buffer = test_utils.load_file(_MULTI_INPUTS_MODEL)
    # The input tensors in the model are: input_ids, input_mask, segment_ids.
    input_md_1 = metadata_info.TensorMd(name="ids", tensor_name="input_ids")
    input_md_2 = metadata_info.TensorMd(name="mask", tensor_name="input_mask")
    input_md_3 = metadata_info.TensorMd(
        name="segment", tensor_name="segment_ids")

    # Create input metadata in a different order to test if MetadataWriter can
    # correct it.
    writer = metadata_writer.MetadataWriter.create_from_metadata_info(
        model_buffer, input_md=[input_md_2, input_md_3, input_md_1])
    model_with_metadata = writer.populate()

    self._assert_correct_metadata(model_with_metadata,
                                  _EXPECTED_MULTI_INPUTS_JSON)
  def test_create_from_metadata_info_with_output_tensor_name_should_succeed(
      self):
    model_buffer = test_utils.load_file(_MULTI_OUTPUTS_MODEL)
    # The output tensors in the model are: Identity, Identity_1
    output_md_1 = metadata_info.TensorMd(
        name="Identity", tensor_name="Identity")
    output_md_2 = metadata_info.TensorMd(
        name="Identity 1", tensor_name="Identity_1")

    # Create output metadata in a different order to test if MetadataWriter can
    # correct it.
    writer = metadata_writer.MetadataWriter.create_from_metadata_info(
        model_buffer, output_md=[output_md_2, output_md_1])
    model_with_metadata = writer.populate()

    self._assert_correct_metadata(model_with_metadata,
                                  _EXPECTED_MULTI_OUTPUTS_JSON)
 def test_create_from_metadata_info_fails_with_wrong_output_tesnor_name(self):
   model_buffer = test_utils.load_file(_MODEL)
   output_md = metadata_info.TensorMd(tensor_name="wrong_tensor_name")
   with self.assertRaises(ValueError) as error:
     metadata_writer.MetadataWriter.create_from_metadata_info(
         model_buffer, output_md=[output_md])
   self.assertEqual(
       "The tensor names from arguments (['wrong_tensor_name']) do not match"
       " the tensor names read from the model (['output']).",
       str(error.exception))
    def create_from_metadata_info(
            cls,
            model_buffer: bytearray,
            general_md: Optional[metadata_info.GeneralMd] = None,
            input_md: Optional[metadata_info.InputImageTensorMd] = None,
            output_md: Optional[metadata_info.TensorMd] = None):
        """Creates MetadataWriter based on general/input/outputs information.

    Args:
      model_buffer: valid buffer of the model file.
      general_md: general infromation about the model.
      input_md: input image tensor informaton.
      output_md: output segmentation mask tensor informaton. This tensor is a
        multidimensional array of [1 x mask_height x mask_width x num_classes],
        where mask_width and mask_height are the dimensions of the segmentation
        masks produced by the model, and num_classes is the number of classes
        supported by the model.

    Returns:
      A MetadataWriter object.
    """

        if general_md is None:
            general_md = metadata_info.GeneralMd(
                name=_MODEL_NAME, description=_MODEL_DESCRIPTION)

        if input_md is None:
            input_md = metadata_info.InputImageTensorMd(
                name=_INPUT_NAME,
                description=_INPUT_DESCRIPTION,
                color_space_type=_metadata_fb.ColorSpaceType.RGB)

        if output_md is None:
            output_md = metadata_info.TensorMd(name=_OUTPUT_NAME,
                                               description=_OUTPUT_DESCRIPTION)

        if output_md.associated_files is None:
            output_md.associated_files = []

        return super().create_from_metadata(
            model_buffer,
            model_metadata=general_md.create_metadata(),
            input_metadata=[input_md.create_metadata()],
            output_metadata=[_create_segmentation_masks_metadata(output_md)],
            associated_files=[
                file.file_path for file in output_md.associated_files
            ])
    def create_for_inference(cls, model_buffer: bytearray,
                             input_norm_mean: List[float],
                             input_norm_std: List[float],
                             label_file_paths: List[str]):
        """Creates mandatory metadata for TFLite Support inference.

    The parameters required in this method are mandatory when using TFLite
    Support features, such as Task library and Codegen tool (Android Studio ML
    Binding). Other metadata fields will be set to default. If other fields need
    to be filled, use the method `create_from_metadata_info` to edit them.

    Args:
      model_buffer: valid buffer of the model file.
      input_norm_mean: the mean value used in the input tensor normalization
        [1].
      input_norm_std: the std value used in the input tensor normalizarion [1].
      label_file_paths: paths to the label files [2] in the category tensor.
        Pass in an empty list, If the model does not have any label file.
      [1]:
        https://www.tensorflow.org/lite/convert/metadata#normalization_and_quantization_parameters
      [2]:
        https://github.com/tensorflow/tflite-support/blob/b80289c4cd1224d0e1836c7654e82f070f9eefaa/tensorflow_lite_support/metadata/metadata_schema.fbs#L108

    Returns:
      A MetadataWriter object.
    """
        input_md = metadata_info.InputImageTensorMd(
            name=_INPUT_NAME,
            description=_INPUT_DESCRIPTION,
            norm_mean=input_norm_mean,
            norm_std=input_norm_std,
            color_space_type=_metadata_fb.ColorSpaceType.RGB,
            tensor_type=writer_utils.get_input_tensor_types(model_buffer)[0])

        output_md = metadata_info.TensorMd(
            name=_OUTPUT_NAME,
            description=_OUTPUT_DESCRIPTION,
            associated_files=[
                metadata_info.LabelFileMd(file_path=file_path)
                for file_path in label_file_paths
            ])

        return cls.create_from_metadata_info(model_buffer,
                                             input_md=input_md,
                                             output_md=output_md)
    def test_create_metadata_should_succeed(self, content_type, golden_json):
        associated_file1 = metadata_info.AssociatedFileMd(
            file_path=self._LABEL_FILE_EN, locale="en")
        associated_file2 = metadata_info.AssociatedFileMd(
            file_path=self._LABEL_FILE_CN, locale="cn")

        tensor_md = metadata_info.TensorMd(
            name=self._TENSOR_NAME,
            description=self._TENSOR_DESCRIPTION,
            min_values=[self._TENSOR_MIN],
            max_values=[self._TENSOR_MAX],
            content_type=content_type,
            associated_files=[associated_file1, associated_file2])
        tensor_metadata = tensor_md.create_metadata()

        metadata_json = _metadata.convert_to_json(
            _create_dummy_model_metadata(tensor_metadata))
        expected_json = test_utils.load_file(golden_json, "r")
        self.assertEqual(metadata_json, expected_json)
Esempio n. 9
0
    def create_from_metadata_info(
            cls,
            model_buffer: bytearray,
            general_md: Optional[metadata_info.GeneralMd] = None,
            input_md: Optional[metadata_info.InputImageTensorMd] = None,
            output_location_md: Optional[metadata_info.TensorMd] = None,
            output_category_md: Optional[
                metadata_info.CategoryTensorMd] = None,
            output_score_md: Union[
                None, metadata_info.TensorMd,
                metadata_info.ClassificationTensorMd] = None,
            output_number_md: Optional[metadata_info.TensorMd] = None):
        """Creates MetadataWriter based on general/input/outputs information.

    Args:
      model_buffer: valid buffer of the model file.
      general_md: general infromation about the model.
      input_md: input image tensor informaton.
      output_location_md: output location tensor informaton. The location tensor
        is a multidimensional array of [N][4] floating point values between 0
        and 1, the inner arrays representing bounding boxes in the form [top,
        left, bottom, right].
      output_category_md: output category tensor information. The category
        tensor is an array of N integers (output as floating point values) each
        indicating the index of a class label from the labels file.
      output_score_md: output score tensor information. The score tensor is an
        array of N floating point values between 0 and 1 representing
        probability that a class was detected. Use ClassificationTensorMd to
        calibrate score.
      output_number_md: output number of detections tensor information. This
        tensor is an integer value of N.

    Returns:
      A MetadataWriter object.
    """
        if general_md is None:
            general_md = metadata_info.GeneralMd(
                name=_MODEL_NAME, description=_MODEL_DESCRIPTION)

        if input_md is None:
            input_md = metadata_info.InputImageTensorMd(
                name=_INPUT_NAME,
                description=_INPUT_DESCRIPTION,
                color_space_type=_metadata_fb.ColorSpaceType.RGB)

        warn_message_format = (
            "The output name isn't the default string \"%s\". This may cause the "
            "model not work in the TFLite Task Library since the tensor name will "
            "be used to handle the output order in the TFLite Task Library.")
        if output_location_md is None:
            output_location_md = metadata_info.TensorMd(
                name=_OUTPUT_LOCATION_NAME,
                description=_OUTPUT_LOCATION_DESCRIPTION)
        elif output_location_md.name != _OUTPUT_LOCATION_NAME:
            logging.warning(warn_message_format, _OUTPUT_LOCATION_NAME)

        if output_category_md is None:
            output_category_md = metadata_info.CategoryTensorMd(
                name=_OUTPUT_CATRGORY_NAME,
                description=_OUTPUT_CATEGORY_DESCRIPTION)
        elif output_category_md.name != _OUTPUT_CATRGORY_NAME:
            logging.warning(warn_message_format, _OUTPUT_CATRGORY_NAME)

        if output_score_md is None:
            output_score_md = metadata_info.ClassificationTensorMd(
                name=_OUTPUT_SCORE_NAME,
                description=_OUTPUT_SCORE_DESCRIPTION,
            )
        elif output_score_md.name != _OUTPUT_SCORE_NAME:
            logging.warning(warn_message_format, _OUTPUT_SCORE_NAME)

        if output_number_md is None:
            output_number_md = metadata_info.TensorMd(
                name=_OUTPUT_NUMBER_NAME,
                description=_OUTPUT_NUMBER_DESCRIPTION)
        elif output_number_md.name != _OUTPUT_NUMBER_NAME:
            logging.warning(warn_message_format, _OUTPUT_NUMBER_NAME)

        # Create output tensor group info.
        group = _metadata_fb.TensorGroupT()
        group.name = _GROUP_NAME
        group.tensorNames = [
            output_location_md.name, output_category_md.name,
            output_score_md.name
        ]

        # Gets the tensor inidces of tflite outputs and then gets the order of the
        # output metadata by the value of tensor indices. For instance, if the
        # output indices are [601, 599, 598, 600], tensor names and indices aligned
        # are:
        #   - location: 598
        #   - category: 599
        #   - score: 600
        #   - number of detections: 601
        # because of the op's ports of TFLITE_DETECTION_POST_PROCESS
        # (https://github.com/tensorflow/tensorflow/blob/a4fe268ea084e7d323133ed7b986e0ae259a2bc7/tensorflow/lite/kernels/detection_postprocess.cc#L47-L50).
        # Thus, the metadata of tensors are sorted in this way, according to
        # output_tensor_indicies correctly.
        output_tensor_indices = _get_tflite_outputs(model_buffer)
        metadata_list = [
            _create_location_metadata(output_location_md),
            _create_metadata_with_value_range(output_category_md),
            _create_metadata_with_value_range(output_score_md),
            output_number_md.create_metadata()
        ]

        # Align indices with tensors.
        sorted_indices = sorted(output_tensor_indices)
        indices_to_tensors = dict(zip(sorted_indices, metadata_list))

        # Output metadata according to output_tensor_indices.
        output_metadata = [
            indices_to_tensors[i] for i in output_tensor_indices
        ]

        # Create subgraph info.
        subgraph_metadata = _metadata_fb.SubGraphMetadataT()
        subgraph_metadata.inputTensorMetadata = [input_md.create_metadata()]
        subgraph_metadata.outputTensorMetadata = output_metadata
        subgraph_metadata.outputTensorGroups = [group]

        # Create model metadata
        model_metadata = general_md.create_metadata()
        model_metadata.subgraphMetadata = [subgraph_metadata]

        b = flatbuffers.Builder(0)
        b.Finish(model_metadata.Pack(b),
                 _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)

        associated_files = []
        _extend_new_files(associated_files,
                          output_category_md.associated_files)
        _extend_new_files(associated_files, output_score_md.associated_files)
        return cls(model_buffer, b.Output(), associated_files=associated_files)
  def create_from_metadata_info(
      cls,
      model_buffer: bytearray,
      general_md: Optional[metadata_info.GeneralMd] = None,
      input_md: Optional[metadata_info.InputImageTensorMd] = None,
      output_location_md: Optional[metadata_info.TensorMd] = None,
      output_category_md: Optional[metadata_info.CategoryTensorMd] = None,
      output_score_md: Optional[metadata_info.TensorMd] = None,
      output_number_md: Optional[metadata_info.TensorMd] = None):
    """Creates MetadataWriter based on general/input/outputs information.

    Args:
      model_buffer: valid buffer of the model file.
      general_md: general infromation about the model.
      input_md: input image tensor informaton.
      output_location_md: output location tensor informaton. The location tensor
        is a multidimensional array of [N][4] floating point values between 0
        and 1, the inner arrays representing bounding boxes in the form [top,
        left, bottom, right].
      output_category_md: output category tensor information. The category
        tensor is an array of N integers (output as floating point values) each
        indicating the index of a class label from the labels file.
      output_score_md: output score tensor information. The score tensor is an
        array of N floating point values between 0 and 1 representing
        probability that a class was detected.
      output_number_md: output number of dections tensor information. This
        tensor is an integer value of N.

    Returns:
      A MetadataWriter object.
    """

    if general_md is None:
      general_md = metadata_info.GeneralMd(
          name=_MODEL_NAME, description=_MODEL_DESCRIPTION)

    if input_md is None:
      input_md = metadata_info.InputImageTensorMd(
          name=_INPUT_NAME,
          description=_INPUT_DESCRIPTION,
          color_space_type=_metadata_fb.ColorSpaceType.RGB)

    if output_location_md is None:
      output_location_md = metadata_info.TensorMd(
          name=_OUTPUT_LOCATION_NAME, description=_OUTPUT_LOCATION_DESCRIPTION)

    if output_category_md is None:
      output_category_md = metadata_info.CategoryTensorMd(
          name=_OUTPUT_CATRGORY_NAME, description=_OUTPUT_CATEGORY_DESCRIPTION)

    if output_score_md is None:
      output_score_md = metadata_info.TensorMd(
          name=_OUTPUT_SCORE_NAME, description=_OUTPUT_SCORE_DESCRIPTION)

    if output_number_md is None:
      output_number_md = metadata_info.TensorMd(
          name=_OUTPUT_NUMBER_NAME, description=_OUTPUT_NUMBER_DESCRIPTION)

    if output_category_md.associated_files is None:
      output_category_md.associated_files = []

    return super().create_from_metadata(
        model_buffer,
        model_metadata=general_md.create_metadata(),
        input_metadata=[input_md.create_metadata()],
        output_metadata=[
            _create_location_metadata(output_location_md),
            _create_metadata_with_value_range(output_category_md),
            _create_metadata_with_value_range(output_score_md),
            output_number_md.create_metadata()
        ],
        associated_files=[
            file.file_path for file in output_category_md.associated_files
        ])
  def create_from_metadata_info(
      cls,
      model_buffer: bytearray,
      general_md: Optional[metadata_info.GeneralMd] = None,
      input_md: Optional[metadata_info.InputImageTensorMd] = None,
      output_location_md: Optional[metadata_info.TensorMd] = None,
      output_category_md: Optional[metadata_info.CategoryTensorMd] = None,
      output_score_md: Optional[metadata_info.TensorMd] = None,
      output_number_md: Optional[metadata_info.TensorMd] = None):
    """Creates MetadataWriter based on general/input/outputs information.

    Args:
      model_buffer: valid buffer of the model file.
      general_md: general infromation about the model.
      input_md: input image tensor informaton.
      output_location_md: output location tensor informaton. The location tensor
        is a multidimensional array of [N][4] floating point values between 0
        and 1, the inner arrays representing bounding boxes in the form [top,
        left, bottom, right].
      output_category_md: output category tensor information. The category
        tensor is an array of N integers (output as floating point values) each
        indicating the index of a class label from the labels file.
      output_score_md: output score tensor information. The score tensor is an
        array of N floating point values between 0 and 1 representing
        probability that a class was detected.
      output_number_md: output number of dections tensor information. This
        tensor is an integer value of N.

    Returns:
      A MetadataWriter object.
    """

    if general_md is None:
      general_md = metadata_info.GeneralMd(
          name=_MODEL_NAME, description=_MODEL_DESCRIPTION)

    if input_md is None:
      input_md = metadata_info.InputImageTensorMd(
          name=_INPUT_NAME,
          description=_INPUT_DESCRIPTION,
          color_space_type=_metadata_fb.ColorSpaceType.RGB)

    if output_location_md is None:
      output_location_md = metadata_info.TensorMd(
          name=_OUTPUT_LOCATION_NAME, description=_OUTPUT_LOCATION_DESCRIPTION)

    if output_category_md is None:
      output_category_md = metadata_info.CategoryTensorMd(
          name=_OUTPUT_CATRGORY_NAME, description=_OUTPUT_CATEGORY_DESCRIPTION)

    if output_score_md is None:
      output_score_md = metadata_info.TensorMd(
          name=_OUTPUT_SCORE_NAME, description=_OUTPUT_SCORE_DESCRIPTION)

    if output_number_md is None:
      output_number_md = metadata_info.TensorMd(
          name=_OUTPUT_NUMBER_NAME, description=_OUTPUT_NUMBER_DESCRIPTION)

    if output_category_md.associated_files is None:
      output_category_md.associated_files = []

    # Create output tensor group info.
    group = _metadata_fb.TensorGroupT()
    group.name = _GROUP_NAME
    group.tensorNames = [
        output_location_md.name, output_category_md.name, output_score_md.name
    ]

    # Create subgraph info.
    subgraph_metadata = _metadata_fb.SubGraphMetadataT()
    subgraph_metadata.inputTensorMetadata = [input_md.create_metadata()]
    subgraph_metadata.outputTensorMetadata = [
        _create_location_metadata(output_location_md),
        _create_metadata_with_value_range(output_category_md),
        _create_metadata_with_value_range(output_score_md),
        output_number_md.create_metadata()
    ]
    subgraph_metadata.outputTensorGroups = [group]

    # Create model metadata
    model_metadata = general_md.create_metadata()
    model_metadata.subgraphMetadata = [subgraph_metadata]

    b = flatbuffers.Builder(0)
    b.Finish(
        model_metadata.Pack(b),
        _metadata.MetadataPopulator.METADATA_FILE_IDENTIFIER)

    return cls(
        model_buffer,
        b.Output(),
        associated_files=[
            file.file_path for file in output_category_md.associated_files
        ])