
import copy
from typing import Any, Dict, List, Optional, Union

import numpy as np
import torch

from ...audio_utils import mel_filter_bank, spectrogram, window_function
from ...feature_extraction_sequence_utils import SequenceFeatureExtractor
from ...feature_extraction_utils import BatchFeature
from ...utils import TensorType, logging


snake_case_ :  str     =					logging.get_logger(__name__)


class 						lowercase__	(  snake_case_   ):






   '''simple docstring'''







   _snake_case		   =							['''input_features''', '''is_longer''']







   def __init__(			self ,   lowerCamelCase__=6_4 ,   lowerCamelCase__=4_8_0_0_0 ,   lowerCamelCase__=4_8_0 ,   lowerCamelCase__=1_0 ,   lowerCamelCase__=1_0_2_4 ,   lowerCamelCase__=0.0 ,   lowerCamelCase__=False ,   lowerCamelCase__ = 0 ,   lowerCamelCase__ = 1_4_0_0_0 ,   lowerCamelCase__ = None ,   lowerCamelCase__ = "fusion" ,   lowerCamelCase__ = "repeatpad" ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      super().__init__(
          feature_size=lowerCamelCase__ ,   sampling_rate=lowerCamelCase__ ,   padding_value=lowerCamelCase__ ,   return_attention_mask=lowerCamelCase__ ,   **lowerCamelCase__ ,   )
      UpperCamelCase       =  top_db
      UpperCamelCase       =  truncation
      UpperCamelCase       =  padding
      UpperCamelCase       =  fft_window_size
      UpperCamelCase       =  (fft_window_size >> 1) + 1
      UpperCamelCase       =  hop_length
      UpperCamelCase       =  max_length_s
      UpperCamelCase       =  max_length_s * sampling_rate
      UpperCamelCase       =  sampling_rate
      UpperCamelCase       =  frequency_min
      UpperCamelCase       =  frequency_max
      UpperCamelCase       =  mel_filter_bank(
          num_frequency_bins=self.nb_frequency_bins ,   num_mel_filters=lowerCamelCase__ ,   min_frequency=lowerCamelCase__ ,   max_frequency=lowerCamelCase__ ,   sampling_rate=lowerCamelCase__ ,   norm=lowerCamelCase__ ,   mel_scale='''htk''' ,   )
      UpperCamelCase       =  mel_filter_bank(
          num_frequency_bins=self.nb_frequency_bins ,   num_mel_filters=lowerCamelCase__ ,   min_frequency=lowerCamelCase__ ,   max_frequency=lowerCamelCase__ ,   sampling_rate=lowerCamelCase__ ,   norm='''slaney''' ,   mel_scale='''slaney''' ,   )







   def       UpperCAmelCase				(			self   ):

      '''simple docstring'''







      UpperCamelCase       =  copy.deepcopy(self.__dict__   )
      UpperCamelCase       =  self.__class__.__name__
      if "mel_filters" in output:
         del output["mel_filters"]
      if "mel_filters_slaney" in output:
         del output["mel_filters_slaney"]
      return output







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ = None   ):

      '''simple docstring'''







      UpperCamelCase       =  spectrogram(
          lowerCamelCase__ ,   window_function(self.fft_window_size ,   '''hann'''   ) ,   frame_length=self.fft_window_size ,   hop_length=self.hop_length ,   power=2.0 ,   mel_filters=lowerCamelCase__ ,   log_mel='''dB''' ,   )
      return log_mel_spectrogram.T







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__   ):

      '''simple docstring'''







      UpperCamelCase       =  np.array_split(list(range(0 ,   total_frames - chunk_frames + 1   )   ) ,   3   )
      if len(ranges[1]   ) == 0:
         # if the audio is too short, we just use the first chunk
         UpperCamelCase       =  [0]
      if len(ranges[2]   ) == 0:
         # if the audio is too short, we just use the first chunk
         UpperCamelCase       =  [0]
      # randomly choose index for each part
      UpperCamelCase       =  np.random.choice(ranges[0]   )
      UpperCamelCase       =  np.random.choice(ranges[1]   )
      UpperCamelCase       =  np.random.choice(ranges[2]   )

      UpperCamelCase       =  mel[idx_front : idx_front + chunk_frames, :]
      UpperCamelCase       =  mel[idx_middle : idx_middle + chunk_frames, :]
      UpperCamelCase       =  mel[idx_back : idx_back + chunk_frames, :]

      UpperCamelCase       =  torch.tensor(mel[None, None, :]   )
      UpperCamelCase       =  torch.nn.functional.interpolate(
          lowerCamelCase__ ,   size=[chunk_frames, 6_4] ,   mode='''bilinear''' ,   align_corners=lowerCamelCase__   )
      UpperCamelCase       =  mel_shrink[0][0].numpy()
      UpperCamelCase       =  np.stack([mel_shrink, mel_chunk_front, mel_chunk_middle, mel_chunk_back] ,   axis=0   )
      return mel_fusion







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__   ):

      '''simple docstring'''







      if waveform.shape[0] > max_length:
         if truncation == "rand_trunc":
            UpperCamelCase       =  True
            # random crop to max_length (for compatibility) -> this should be handled by self.pad
            UpperCamelCase       =  len(lowerCamelCase__   ) - max_length
            UpperCamelCase       =  np.random.randint(0 ,   overflow + 1   )
            UpperCamelCase       =  waveform[idx : idx + max_length]
            UpperCamelCase       =  self._np_extract_fbank_features(lowerCamelCase__ ,   self.mel_filters_slaney   )[None, :]
         elif truncation == "fusion":
            UpperCamelCase       =  self._np_extract_fbank_features(lowerCamelCase__ ,   self.mel_filters   )
            UpperCamelCase       =  max_length // self.hop_length + 1  # the +1 related to how the spectrogram is computed
            UpperCamelCase       =  mel.shape[0]
            if chunk_frames == total_frames:
               # there is a corner case where the audio length is larger than max_length but smaller than max_length+hop_length.
               # In this case, we just use the whole audio.
               UpperCamelCase       =  np.stack([mel, mel, mel, mel] ,   axis=0   )
               UpperCamelCase       =  False
            else:
               UpperCamelCase       =  self._random_mel_fusion(lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__   )
               UpperCamelCase       =  True
         else:
            raise NotImplementedError(f'data_truncating {truncation} not implemented'   )

      else:
         UpperCamelCase       =  False
         # only use repeat as a new possible value for padding. you repeat the audio before applying the usual max_length padding
         if waveform.shape[0] < max_length:
            if padding == "repeat":
               UpperCamelCase       =  int(max_length / len(lowerCamelCase__   )   )
               UpperCamelCase       =  np.stack(np.tile(lowerCamelCase__ ,   n_repeat + 1   )   )[:max_length]
            if padding == "repeatpad":
               UpperCamelCase       =  int(max_length / len(lowerCamelCase__   )   )
               UpperCamelCase       =  np.stack(np.tile(lowerCamelCase__ ,   lowerCamelCase__   )   )
            UpperCamelCase       =  np.pad(lowerCamelCase__ ,   (0, max_length - waveform.shape[0]) ,   mode='''constant''' ,   constant_values=0   )

         if truncation == "fusion":
            UpperCamelCase       =  self._np_extract_fbank_features(lowerCamelCase__ ,   self.mel_filters   )
            UpperCamelCase       =  np.stack([input_mel, input_mel, input_mel, input_mel] ,   axis=0   )
         else:
            UpperCamelCase       =  self._np_extract_fbank_features(lowerCamelCase__ ,   self.mel_filters_slaney   )[None, :]

      return input_mel, longer







   def __call__(			self ,   lowerCamelCase__ ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      UpperCamelCase       =  truncation if truncation is not None else self.truncation
      UpperCamelCase       =  padding if padding else self.padding

      if sampling_rate is not None:
         if sampling_rate != self.sampling_rate:
            raise ValueError(
                f'The model corresponding to this feature extractor: {self.__class__.__name__} was trained using a'
                f' sampling rate of {self.sampling_rate}. Please make sure that the provided `raw_speech` input'
                f' was sampled with {self.sampling_rate} and not {sampling_rate}.'   )
      else:
         logger.warning(
             '''It is strongly recommended to pass the `sampling_rate` argument to this function. '''
             '''Failing to do so can result in silent errors that might be hard to debug.'''   )

      UpperCamelCase       =  isinstance(lowerCamelCase__ ,   np.ndarray   ) and len(raw_speech.shape   ) > 1
      if is_batched_numpy and len(raw_speech.shape   ) > 2:
         raise ValueError(f'Only mono-channel audio is supported for input to {self}'   )
      UpperCamelCase       =  is_batched_numpy or (
          isinstance(lowerCamelCase__ ,   (list, tuple)   ) and (isinstance(raw_speech[0] ,   (np.ndarray, tuple, list)   ))
      )

      if is_batched:
         UpperCamelCase       =  [np.asarray(lowerCamelCase__ ,   dtype=np.floataa   ) for speech in raw_speech]
      elif not is_batched and not isinstance(lowerCamelCase__ ,   np.ndarray   ):
         UpperCamelCase       =  np.asarray(lowerCamelCase__ ,   dtype=np.floataa   )
      elif isinstance(lowerCamelCase__ ,   np.ndarray   ) and raw_speech.dtype is np.dtype(np.floataa   ):
         UpperCamelCase       =  raw_speech.astype(np.floataa   )

      # always return batch
      if not is_batched:
         UpperCamelCase       =  [np.asarray(lowerCamelCase__   )]

      # convert to mel spectrogram, truncate and pad if needed.
      UpperCamelCase       =  [
          self._get_input_mel(lowerCamelCase__ ,   max_length if max_length else self.nb_max_samples ,   lowerCamelCase__ ,   lowerCamelCase__   )
          for waveform in raw_speech
      ]

      UpperCamelCase       =  []
      UpperCamelCase       =  []
      for mel, longer in padded_inputs:
         input_mel.append(lowerCamelCase__   )
         is_longer.append(lowerCamelCase__   )

      if truncation == "fusion" and sum(lowerCamelCase__   ) == 0:
         # if no audio is longer than 10s, then randomly select one audio to be longer
         UpperCamelCase       =  np.random.randint(0 ,   len(lowerCamelCase__   )   )
         UpperCamelCase       =  True

      if isinstance(input_mel[0] ,   lowerCamelCase__   ):
         UpperCamelCase       =  [np.asarray(lowerCamelCase__ ,   dtype=np.floataa   ) for feature in input_mel]

      # is_longer is a list of bool
      UpperCamelCase       =  [[longer] for longer in is_longer]

      UpperCamelCase       =  {'''input_features''': input_mel, '''is_longer''': is_longer}
      UpperCamelCase       =  BatchFeature(lowerCamelCase__   )

      if return_tensors is not None:
         UpperCamelCase       =  input_features.convert_to_tensors(lowerCamelCase__   )

      return input_features







'''simple docstring'''


from typing import Dict, Iterable, Optional, Union

import numpy as np

from ...image_processing_utils import BaseImageProcessor, BatchFeature, get_size_dict
from ...image_transforms import normalize, rescale, resize, to_channel_dimension_format, to_pil_image
from ...image_utils import (
    IMAGENET_STANDARD_MEAN,
    IMAGENET_STANDARD_STD,
    ChannelDimension,
    ImageInput,
    PILImageResampling,
    make_list_of_images,
    to_numpy_array,
    valid_images,
)
from ...utils import TensorType, is_pytesseract_available, is_vision_available, logging, requires_backends


if is_vision_available():
   import PIL

# soft dependency
if is_pytesseract_available():
   import pytesseract

snake_case_ :  Tuple     =					logging.get_logger(__name__)



def  __snake_case     (    _UpperCAmelCase					:       str,      _UpperCAmelCase					:       int,      _UpperCAmelCase					:       Optional[int]):
   return [
       int(1000 * (box[0] / width)),
       int(1000 * (box[1] / height)),
       int(1000 * (box[2] / width)),
       int(1000 * (box[3] / height)),
   ]



def  __snake_case     (    _UpperCAmelCase					:       np.ndarray,      _UpperCAmelCase					:       Optional[str],      _UpperCAmelCase					:       Optional[str]):
   UpperCamelCase       =  to_pil_image(_UpperCAmelCase)
   UpperCamelCase     , UpperCamelCase       =  pil_image.size
   UpperCamelCase       =  pytesseract.image_to_data(_UpperCAmelCase,      lang=_UpperCAmelCase,      output_type='''dict''',      config=_UpperCAmelCase)
   UpperCamelCase     , UpperCamelCase     , UpperCamelCase     , UpperCamelCase     , UpperCamelCase       =  data['''text'''], data['''left'''], data['''top'''], data['''width'''], data['''height''']

   # filter empty words and corresponding coordinates
   UpperCamelCase       =  [idx for idx, word in enumerate(_UpperCAmelCase) if not word.strip()]
   UpperCamelCase       =  [word for idx, word in enumerate(_UpperCAmelCase) if idx not in irrelevant_indices]
   UpperCamelCase       =  [coord for idx, coord in enumerate(_UpperCAmelCase) if idx not in irrelevant_indices]
   UpperCamelCase       =  [coord for idx, coord in enumerate(_UpperCAmelCase) if idx not in irrelevant_indices]
   UpperCamelCase       =  [coord for idx, coord in enumerate(_UpperCAmelCase) if idx not in irrelevant_indices]
   UpperCamelCase       =  [coord for idx, coord in enumerate(_UpperCAmelCase) if idx not in irrelevant_indices]

   # turn coordinates into (left, top, left+width, top+height) format
   UpperCamelCase       =  []
   for x, y, w, h in zip(_UpperCAmelCase,      _UpperCAmelCase,      _UpperCAmelCase,      _UpperCAmelCase):
      UpperCamelCase       =  [x, y, x + w, y + h]
      actual_boxes.append(_UpperCAmelCase)

   # finally, normalize the bounding boxes
   UpperCamelCase       =  []
   for box in actual_boxes:
      normalized_boxes.append(normalize_box(_UpperCAmelCase,      _UpperCAmelCase,      _UpperCAmelCase))

   assert len(_UpperCAmelCase) == len(_UpperCAmelCase), "Not as many words as there are bounding boxes"

   return words, normalized_boxes


class 						lowercase__	(  snake_case_   ):






   '''simple docstring'''







   _snake_case		   =							['''pixel_values''']







   def __init__(			self ,   lowerCamelCase__ = True ,   lowerCamelCase__ = None ,   lowerCamelCase__ = PILImageResampling.BILINEAR ,   lowerCamelCase__ = True ,   lowerCamelCase__ = 1 / 2_5_5 ,   lowerCamelCase__ = True ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = True ,   lowerCamelCase__ = None ,   lowerCamelCase__ = "" ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      super().__init__(**lowerCamelCase__   )
      UpperCamelCase       =  size if size is not None else {'''height''': 2_2_4, '''width''': 2_2_4}
      UpperCamelCase       =  get_size_dict(lowerCamelCase__   )

      UpperCamelCase       =  do_resize
      UpperCamelCase       =  size
      UpperCamelCase       =  resample
      UpperCamelCase       =  do_rescale
      UpperCamelCase       =  rescale_value
      UpperCamelCase       =  do_normalize
      UpperCamelCase       =  image_mean if image_mean is not None else IMAGENET_STANDARD_MEAN
      UpperCamelCase       =  image_std if image_std is not None else IMAGENET_STANDARD_STD
      UpperCamelCase       =  apply_ocr
      UpperCamelCase       =  ocr_lang
      UpperCamelCase       =  tesseract_config







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__ = PILImageResampling.BILINEAR ,   lowerCamelCase__ = None ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      UpperCamelCase       =  get_size_dict(lowerCamelCase__   )
      if "height" not in size or "width" not in size:
         raise ValueError(f'The size dictionary must contain the keys \'height\' and \'width\'. Got {size.keys()}'   )
      UpperCamelCase       =  (size['''height'''], size['''width'''])
      return resize(lowerCamelCase__ ,   size=lowerCamelCase__ ,   resample=lowerCamelCase__ ,   data_format=lowerCamelCase__ ,   **lowerCamelCase__   )







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__ = None ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      return rescale(lowerCamelCase__ ,   scale=lowerCamelCase__ ,   data_format=lowerCamelCase__ ,   **lowerCamelCase__   )







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__ = None ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      return normalize(lowerCamelCase__ ,   mean=lowerCamelCase__ ,   std=lowerCamelCase__ ,   data_format=lowerCamelCase__ ,   **lowerCamelCase__   )







   def       UpperCAmelCase				(			self ,   lowerCamelCase__ ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__=None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = None ,   lowerCamelCase__ = ChannelDimension.FIRST ,   **lowerCamelCase__ ,   ):

      '''simple docstring'''







      UpperCamelCase       =  do_resize if do_resize is not None else self.do_resize
      UpperCamelCase       =  size if size is not None else self.size
      UpperCamelCase       =  get_size_dict(lowerCamelCase__   )
      UpperCamelCase       =  resample if resample is not None else self.resample
      UpperCamelCase       =  do_rescale if do_rescale is not None else self.do_rescale
      UpperCamelCase       =  rescale_factor if rescale_factor is not None else self.rescale_factor
      UpperCamelCase       =  do_normalize if do_normalize is not None else self.do_normalize
      UpperCamelCase       =  image_mean if image_mean is not None else self.image_mean
      UpperCamelCase       =  image_std if image_std is not None else self.image_std
      UpperCamelCase       =  apply_ocr if apply_ocr is not None else self.apply_ocr
      UpperCamelCase       =  ocr_lang if ocr_lang is not None else self.ocr_lang
      UpperCamelCase       =  tesseract_config if tesseract_config is not None else self.tesseract_config

      UpperCamelCase       =  make_list_of_images(lowerCamelCase__   )

      if not valid_images(lowerCamelCase__   ):
         raise ValueError(
             '''Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, '''
             '''torch.Tensor, tf.Tensor or jax.ndarray.'''   )

      if do_resize and size is None:
         raise ValueError('''Size must be specified if do_resize is True.'''   )

      if do_rescale and rescale_factor is None:
         raise ValueError('''Rescale factor must be specified if do_rescale is True.'''   )

      if do_normalize and (image_mean is None or image_std is None):
         raise ValueError('''If do_normalize is True, image_mean and image_std must be specified.'''   )

      # All transformations expect numpy arrays.
      UpperCamelCase       =  [to_numpy_array(lowerCamelCase__   ) for image in images]

      # Tesseract OCR to get words + normalized bounding boxes
      if apply_ocr:
         requires_backends(self ,   '''pytesseract'''   )
         UpperCamelCase       =  []
         UpperCamelCase       =  []
         for image in images:
            UpperCamelCase     , UpperCamelCase       =  apply_tesseract(lowerCamelCase__ ,   lowerCamelCase__ ,   lowerCamelCase__   )
            words_batch.append(lowerCamelCase__   )
            boxes_batch.append(lowerCamelCase__   )

      if do_resize:
         UpperCamelCase       =  [self.resize(image=lowerCamelCase__ ,   size=lowerCamelCase__ ,   resample=lowerCamelCase__   ) for image in images]

      if do_rescale:
         UpperCamelCase       =  [self.rescale(image=lowerCamelCase__ ,   scale=lowerCamelCase__   ) for image in images]

      if do_normalize:
         UpperCamelCase       =  [self.normalize(image=lowerCamelCase__ ,   mean=lowerCamelCase__ ,   std=lowerCamelCase__   ) for image in images]

      UpperCamelCase       =  [to_channel_dimension_format(lowerCamelCase__ ,   lowerCamelCase__   ) for image in images]

      UpperCamelCase       =  BatchFeature(data={'''pixel_values''': images} ,   tensor_type=lowerCamelCase__   )

      if apply_ocr:
         UpperCamelCase       =  words_batch
         UpperCamelCase       =  boxes_batch
      return data





