from typing import Dict, List, Optional, Union

import numpy as np

from .feature_extraction_utils import BatchFeature, FeatureExtractionMixin
from .utils import PaddingStrategy, TensorType, is_tf_tensor, is_torch_tensor, logging, to_numpy


lowerCAmelCase__     						=			logging.get_logger(__name__)
class     a_			(						SCREAMING_SNAKE_CASE						):






 '''simple docstring'''






 def __init__(      self :  Union[str, Any]      ,   lowercase__ :  int      ,   lowercase__ :  int      ,   lowercase__ :  float      ,   **lowercase__ :  Any):







        '''simple docstring'''



        lowerCAmelCase__					     = feature_size
        lowerCAmelCase__					     = sampling_rate
        lowerCAmelCase__					     = padding_value

        lowerCAmelCase__					     = kwargs.pop('padding_side'      ,   'right')
        lowerCAmelCase__					     = kwargs.pop('return_attention_mask'      ,   lowercase__)

        super().__init__(**lowercase__)




 def 		__snake_case						(      self :  Union[str, Any]      ,   lowercase__ :  Union[
         BatchFeature,
         List[BatchFeature],
         Dict[str, BatchFeature],
         Dict[str, List[BatchFeature]],
         List[Dict[str, BatchFeature]],
     ]      ,   lowercase__ :  Union[bool, str, PaddingStrategy] = True      ,   lowercase__ :  Optional[int] = None      ,   lowercase__ :  bool = False      ,   lowercase__ :  Optional[int] = None      ,   lowercase__ :  Optional[bool] = None      ,   lowercase__ :  Optional[Union[str, TensorType]] = None      ,   ):







        '''simple docstring'''



        if isinstance(lowercase__      ,   (list, tuple)) and isinstance(processed_features[0]      ,   (dict, BatchFeature)):
               lowerCAmelCase__					     = {
                   key: [example[key] for example in processed_features] for key in processed_features[0].keys()
               }

        # The model's main input name, usually `input_values`, has be passed for padding
        if self.model_input_names[0] not in processed_features:
               raise ValueError(
                   'You should supply an instance of `transformers.BatchFeature` or list of `transformers.BatchFeature`'
                   F""" to this method that includes {self.model_input_names[0]}, but you provided"""
                   F""" {list(processed_features.keys())}""")

        lowerCAmelCase__					     = processed_features[self.model_input_names[0]]
        lowerCAmelCase__					     = (
            return_attention_mask if return_attention_mask is not None else self.return_attention_mask
        )

        if len(lowercase__) == 0:
               if return_attention_mask:
                      lowerCAmelCase__					     = []
               return processed_features

        # If we have PyTorch/TF tensors or lists as inputs, we cast them as Numpy arrays
        # and rebuild them afterwards if no return_tensors is specified
        # Note that we lose the specific device the tensor may be on for PyTorch

        lowerCAmelCase__					     = required_input[0]
        if isinstance(lowercase__      ,   (list, tuple)):
               # first_element might be an empty list/tuple in some edge cases so we grab the first non empty element.
               lowerCAmelCase__					     = 0
               while len(required_input[index]) == 0:
                      index += 1
               if index < len(lowercase__):
                      lowerCAmelCase__					     = required_input[index][0]

        if return_tensors is None:
               if is_tf_tensor(lowercase__):
                      lowerCAmelCase__					     = 'tf'
               elif is_torch_tensor(lowercase__):
                      lowerCAmelCase__					     = 'pt'
               elif isinstance(lowercase__      ,   (int, float, list, tuple, np.ndarray)):
                      lowerCAmelCase__					     = 'np'
               else:
                      raise ValueError(
                          F"""type of {first_element} unknown: {type(lowercase__)}. """
                          'Should be one of a python, numpy, pytorch or tensorflow object.')

        for key, value in processed_features.items():
               if isinstance(value[0]      ,   (int, float)):
                      lowerCAmelCase__					     = to_numpy(lowercase__)
               else:
                      lowerCAmelCase__					     = [to_numpy(lowercase__) for v in value]

        # Convert padding_strategy in PaddingStrategy
        lowerCAmelCase__					     = self._get_padding_strategies(padding=lowercase__      ,   max_length=lowercase__)

        lowerCAmelCase__					     = processed_features[self.model_input_names[0]]

        lowerCAmelCase__					     = len(lowercase__)
        if not all(len(lowercase__) == batch_size for v in processed_features.values()):
               raise ValueError('Some items in the output dictionary have a different batch size than others.')

        lowerCAmelCase__					     = []
        for i in range(lowercase__):
               lowerCAmelCase__					     = {k: v[i] for k, v in processed_features.items()}
               # truncation
               lowerCAmelCase__					     = self._truncate(
                   lowercase__      ,   max_length=lowercase__      ,   pad_to_multiple_of=lowercase__      ,   truncation=lowercase__      ,   )
               truncated_inputs.append(lowercase__)

        if padding_strategy == PaddingStrategy.LONGEST:
               # make sure that `max_length` cannot be longer than the longest truncated length
               lowerCAmelCase__					     = max(len(input_slice[self.model_input_names[0]]) for input_slice in truncated_inputs)
               lowerCAmelCase__					     = PaddingStrategy.MAX_LENGTH

        lowerCAmelCase__					     = {}
        for i in range(lowercase__):
               # padding
               lowerCAmelCase__					     = self._pad(
                   truncated_inputs[i]      ,   max_length=lowercase__      ,   padding_strategy=lowercase__      ,   pad_to_multiple_of=lowercase__      ,   return_attention_mask=lowercase__      ,   )

               for key, value in outputs.items():
                      if key not in batch_outputs:
                             lowerCAmelCase__					     = []
                      if value.dtype is np.dtype(np.floataa):
                             lowerCAmelCase__					     = value.astype(np.floataa)
                      batch_outputs[key].append(lowercase__)

        return BatchFeature(lowercase__      ,   tensor_type=lowercase__)




 def 		__snake_case						(      self :  List[str]      ,   lowercase__ :  Union[Dict[str, np.ndarray], BatchFeature]      ,   lowercase__ :  Optional[int] = None      ,   lowercase__ :  PaddingStrategy = PaddingStrategy.DO_NOT_PAD      ,   lowercase__ :  Optional[int] = None      ,   lowercase__ :  Optional[bool] = None      ,   ):







        '''simple docstring'''



        lowerCAmelCase__					     = processed_features[self.model_input_names[0]]

        if padding_strategy == PaddingStrategy.LONGEST:
               lowerCAmelCase__					     = len(lowercase__)

        if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
               lowerCAmelCase__					     = ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of

        lowerCAmelCase__					     = padding_strategy != PaddingStrategy.DO_NOT_PAD and len(lowercase__) < max_length

        if return_attention_mask and "attention_mask" not in processed_features:
               lowerCAmelCase__					     = np.ones(len(lowercase__)      ,   dtype=np.intaa)

        if needs_to_be_padded:
               lowerCAmelCase__					     = max_length - len(lowercase__)
               if self.padding_side == "right":
                      if return_attention_mask:
                             lowerCAmelCase__					     = np.pad(
                                 processed_features['attention_mask']      ,   (0, difference))
                      lowerCAmelCase__					     = ((0, difference), (0, 0)) if self.feature_size > 1 else (0, difference)
                      lowerCAmelCase__					     = np.pad(
                          lowercase__      ,   lowercase__      ,   'constant'      ,   constant_values=self.padding_value)
               elif self.padding_side == "left":
                      if return_attention_mask:
                             lowerCAmelCase__					     = np.pad(
                                 processed_features['attention_mask']      ,   (difference, 0))
                      lowerCAmelCase__					     = ((difference, 0), (0, 0)) if self.feature_size > 1 else (difference, 0)
                      lowerCAmelCase__					     = np.pad(
                          lowercase__      ,   lowercase__      ,   'constant'      ,   constant_values=self.padding_value)
               else:
                      raise ValueError('Invalid padding strategy:' + str(self.padding_side))

        return processed_features




 def 		__snake_case						(      self :  Union[str, Any]      ,   lowercase__ :  Union[Dict[str, np.ndarray], BatchFeature]      ,   lowercase__ :  Optional[int] = None      ,   lowercase__ :  Optional[int] = None      ,   lowercase__ :  Optional[bool] = None      ,   ):







        '''simple docstring'''



        if not truncation:
               return processed_features
        elif truncation and max_length is None:
               raise ValueError('When setting ``truncation=True``, make sure that ``max_length`` is defined.')

        lowerCAmelCase__					     = processed_features[self.model_input_names[0]]

        # find `max_length` that fits `pad_to_multiple_of`
        if max_length is not None and pad_to_multiple_of is not None and (max_length % pad_to_multiple_of != 0):
               lowerCAmelCase__					     = ((max_length // pad_to_multiple_of) + 1) * pad_to_multiple_of

        lowerCAmelCase__					     = len(lowercase__) > max_length

        if needs_to_be_truncated:
               lowerCAmelCase__					     = processed_features[self.model_input_names[0]][:max_length]
               if "attention_mask" in processed_features:
                      lowerCAmelCase__					     = processed_features['attention_mask'][:max_length]

        return processed_features




 def 		__snake_case						(      self :  int      ,   lowercase__ :  Dict=False      ,   lowercase__ :  Union[str, Any]=None):







        '''simple docstring'''



        if padding is not False:
               if padding is True:
                      lowerCAmelCase__					     = PaddingStrategy.LONGEST  # Default to pad to the longest sequence in the batch
               elif not isinstance(lowercase__      ,   lowercase__):
                      lowerCAmelCase__					     = PaddingStrategy(lowercase__)
               elif isinstance(lowercase__      ,   lowercase__):
                      lowerCAmelCase__					     = padding
        else:
               lowerCAmelCase__					     = PaddingStrategy.DO_NOT_PAD

        # Set max length if needed
        if max_length is None:
               if padding_strategy == PaddingStrategy.MAX_LENGTH:
                      raise ValueError(
                          F"""When setting ``padding={PaddingStrategy.MAX_LENGTH}``, make sure that max_length is defined""")

        # Test if we have a padding value
        if padding_strategy != PaddingStrategy.DO_NOT_PAD and (self.padding_value is None):
               raise ValueError(
                   'Asking to pad but the feature_extractor does not have a padding value. Please select a value to use'
                   ' as `padding_value`. For example: `feature_extractor.padding_value = 0.0`.')

        return padding_strategy

from copy import deepcopy
from typing import Optional, Union

import numpy as np

from ...processing_utils import ProcessorMixin
from ...tokenization_utils_base import BatchEncoding
from ...utils import TensorType, is_tf_available, is_torch_available


if is_torch_available():
    import torch

if is_tf_available():
    import tensorflow as tf
class     a_			(						SCREAMING_SNAKE_CASE						):






 '''simple docstring'''






 UpperCAmelCase_     			= ['image_processor']
 UpperCAmelCase_     			= 'SamImageProcessor'




 def __init__(      self :  Tuple      ,   lowercase__ :  Dict):







        '''simple docstring'''



        super().__init__(lowercase__)
        lowerCAmelCase__					     = self.image_processor
        lowerCAmelCase__					     = -10
        lowerCAmelCase__					     = self.image_processor.size['longest_edge']




 def __call__(      self :  List[Any]      ,   lowercase__ :  Optional[int]=None      ,   lowercase__ :  Any=None      ,   lowercase__ :  Tuple=None      ,   lowercase__ :  List[str]=None      ,   lowercase__ :  Optional[Union[str, TensorType]] = None      ,   **lowercase__ :  Dict      ,   ):







        '''simple docstring'''



        lowerCAmelCase__					     = self.image_processor(
            lowercase__      ,   return_tensors=lowercase__      ,   **lowercase__      ,   )

        # pop arguments that are not used in the foward but used nevertheless
        lowerCAmelCase__					     = encoding_image_processor['original_sizes']

        if hasattr(lowercase__      ,   'numpy'):  # Checks if Torch or TF tensor
               lowerCAmelCase__					     = original_sizes.numpy()

        lowerCAmelCase__     , lowerCAmelCase__     , lowerCAmelCase__					     = self._check_and_preprocess_points(
            input_points=lowercase__      ,   input_labels=lowercase__      ,   input_boxes=lowercase__      ,   )

        lowerCAmelCase__					     = self._normalize_and_convert(
            lowercase__      ,   lowercase__      ,   input_points=lowercase__      ,   input_labels=lowercase__      ,   input_boxes=lowercase__      ,   return_tensors=lowercase__      ,   )

        return encoding_image_processor




 def 		__snake_case						(      self :  Optional[Any]      ,   lowercase__ :  List[str]      ,   lowercase__ :  List[str]      ,   lowercase__ :  str=None      ,   lowercase__ :  Optional[int]=None      ,   lowercase__ :  str=None      ,   lowercase__ :  Optional[Any]="pt"      ,   ):







        '''simple docstring'''



        if input_points is not None:
               if len(lowercase__) != len(lowercase__):
                      lowerCAmelCase__					     = [
                          self._normalize_coordinates(self.target_size      ,   lowercase__      ,   original_sizes[0]) for point in input_points
                      ]
               else:
                      lowerCAmelCase__					     = [
                          self._normalize_coordinates(self.target_size      ,   lowercase__      ,   lowercase__)
                          for point, original_size in zip(lowercase__      ,   lowercase__)
                      ]
               # check that all arrays have the same shape
               if not all(point.shape == input_points[0].shape for point in input_points):
                      if input_labels is not None:
                             lowerCAmelCase__     , lowerCAmelCase__					     = self._pad_points_and_labels(lowercase__      ,   lowercase__)

               lowerCAmelCase__					     = np.array(lowercase__)

        if input_labels is not None:
               lowerCAmelCase__					     = np.array(lowercase__)

        if input_boxes is not None:
               if len(lowercase__) != len(lowercase__):
                      lowerCAmelCase__					     = [
                          self._normalize_coordinates(self.target_size      ,   lowercase__      ,   original_sizes[0]      ,   is_bounding_box=lowercase__)
                          for box in input_boxes
                      ]
               else:
                      lowerCAmelCase__					     = [
                          self._normalize_coordinates(self.target_size      ,   lowercase__      ,   lowercase__      ,   is_bounding_box=lowercase__)
                          for box, original_size in zip(lowercase__      ,   lowercase__)
                      ]
               lowerCAmelCase__					     = np.array(lowercase__)

        if input_boxes is not None:
               if return_tensors == "pt":
                      lowerCAmelCase__					     = torch.from_numpy(lowercase__)
                      # boxes batch size of 1 by default
                      lowerCAmelCase__					     = input_boxes.unsqueeze(1) if len(input_boxes.shape) != 3 else input_boxes
               elif return_tensors == "tf":
                      lowerCAmelCase__					     = tf.convert_to_tensor(lowercase__)
                      # boxes batch size of 1 by default
                      lowerCAmelCase__					     = tf.expand_dims(lowercase__      ,   1) if len(input_boxes.shape) != 3 else input_boxes
               encoding_image_processor.update({'input_boxes': input_boxes})
        if input_points is not None:
               if return_tensors == "pt":
                      lowerCAmelCase__					     = torch.from_numpy(lowercase__)
                      # point batch size of 1 by default
                      lowerCAmelCase__					     = input_points.unsqueeze(1) if len(input_points.shape) != 4 else input_points
               elif return_tensors == "tf":
                      lowerCAmelCase__					     = tf.convert_to_tensor(lowercase__)
                      # point batch size of 1 by default
                      lowerCAmelCase__					     = tf.expand_dims(lowercase__      ,   1) if len(input_points.shape) != 4 else input_points
               encoding_image_processor.update({'input_points': input_points})
        if input_labels is not None:
               if return_tensors == "pt":
                      lowerCAmelCase__					     = torch.from_numpy(lowercase__)
                      # point batch size of 1 by default
                      lowerCAmelCase__					     = input_labels.unsqueeze(1) if len(input_labels.shape) != 3 else input_labels
               elif return_tensors == "tf":
                      lowerCAmelCase__					     = tf.convert_to_tensor(lowercase__)
                      # point batch size of 1 by default
                      lowerCAmelCase__					     = tf.expand_dims(lowercase__      ,   1) if len(input_labels.shape) != 3 else input_labels
               encoding_image_processor.update({'input_labels': input_labels})

        return encoding_image_processor




 def 		__snake_case						(      self :  str      ,   lowercase__ :  Optional[int]      ,   lowercase__ :  Optional[Any]):







        '''simple docstring'''



        lowerCAmelCase__					     = max([point.shape[0] for point in input_points])
        lowerCAmelCase__					     = []
        for i, point in enumerate(lowercase__):
               if point.shape[0] != expected_nb_points:
                      lowerCAmelCase__					     = np.concatenate(
                          [point, np.zeros((expected_nb_points - point.shape[0], 2)) + self.point_pad_value]      ,   axis=0)
                      lowerCAmelCase__					     = np.append(input_labels[i]      ,   [self.point_pad_value])
               processed_input_points.append(lowercase__)
        lowerCAmelCase__					     = processed_input_points
        return input_points, input_labels




 def 		__snake_case						(      self :  Optional[Any]      ,   lowercase__ :  int      ,   lowercase__ :  np.ndarray      ,   lowercase__ :  int      ,   lowercase__ :  Optional[Any]=False):







        '''simple docstring'''



        lowerCAmelCase__     , lowerCAmelCase__					     = original_size
        lowerCAmelCase__     , lowerCAmelCase__					     = self.image_processor._get_preprocess_shape(lowercase__      ,   longest_edge=lowercase__)
        lowerCAmelCase__					     = deepcopy(lowercase__).astype(lowercase__)

        if is_bounding_box:
               lowerCAmelCase__					     = coords.reshape(-1      ,   2      ,   2)

        lowerCAmelCase__					     = coords[..., 0] * (new_w / old_w)
        lowerCAmelCase__					     = coords[..., 1] * (new_h / old_h)

        if is_bounding_box:
               lowerCAmelCase__					     = coords.reshape(-1      ,   4)

        return coords




 def 		__snake_case						(      self :  Dict      ,   lowercase__ :  Optional[Any]=None      ,   lowercase__ :  Tuple=None      ,   lowercase__ :  int=None      ,   ):







        '''simple docstring'''



        if input_points is not None:
               if hasattr(lowercase__      ,   'numpy'):  # Checks for TF or Torch tensor
                      lowerCAmelCase__					     = input_points.numpy().tolist()

               if not isinstance(lowercase__      ,   lowercase__) or not isinstance(input_points[0]      ,   lowercase__):
                      raise ValueError('Input points must be a list of list of floating points.')
               lowerCAmelCase__					     = [np.array(lowercase__) for input_point in input_points]
        else:
               lowerCAmelCase__					     = None

        if input_labels is not None:
               if hasattr(lowercase__      ,   'numpy'):
                      lowerCAmelCase__					     = input_labels.numpy().tolist()

               if not isinstance(lowercase__      ,   lowercase__) or not isinstance(input_labels[0]      ,   lowercase__):
                      raise ValueError('Input labels must be a list of list integers.')
               lowerCAmelCase__					     = [np.array(lowercase__) for label in input_labels]
        else:
               lowerCAmelCase__					     = None

        if input_boxes is not None:
               if hasattr(lowercase__      ,   'numpy'):
                      lowerCAmelCase__					     = input_boxes.numpy().tolist()

               if (
                   not isinstance(lowercase__      ,   lowercase__)
                   or not isinstance(input_boxes[0]      ,   lowercase__)
                   or not isinstance(input_boxes[0][0]      ,   lowercase__)
               ):
                      raise ValueError('Input boxes must be a list of list of list of floating points.')
               lowerCAmelCase__					     = [np.array(lowercase__).astype(np.floataa) for box in input_boxes]
        else:
               lowerCAmelCase__					     = None

        return input_points, input_labels, input_boxes




 @property
 def 		__snake_case						(      self :  List[Any]):







        '''simple docstring'''



        lowerCAmelCase__					     = self.image_processor.model_input_names
        return list(dict.fromkeys(lowercase__))




 def 		__snake_case						(      self :  int      ,   *lowercase__ :  int      ,   **lowercase__ :  int):







        '''simple docstring'''



        return self.image_processor.post_process_masks(*lowercase__      ,   **lowercase__)
