import warnings
from typing import Dict

import numpy as np

from ..utils import ExplicitEnum, add_end_docstrings, is_tf_available, is_torch_available
from .base import PIPELINE_INIT_ARGS, GenericTensor, Pipeline


if is_tf_available():
							from ..models.auto.modeling_tf_auto import TF_MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING

if is_torch_available():
							from ..models.auto.modeling_auto import MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING





def 	__lowerCamelCase							(UpperCAmelCase__     :							Dict  ):
					return 1.0 / (1.0 + np.exp(-_outputs  ))





def 	__lowerCamelCase							(UpperCAmelCase__     :							Optional[Any]  ):
					SCREAMING_SNAKE_CASE    			=       np.max(_outputs      , axis=-1      , keepdims=UpperCAmelCase__  )
					SCREAMING_SNAKE_CASE    			=       np.exp(_outputs - maxes  )
					return shifted_exp / shifted_exp.sum(axis=-1      , keepdims=UpperCAmelCase__  )


class 						lowercase    (     a     ):
							lowercase__						:       List[str]								=							"""sigmoid"""
							lowercase__						:       str								=							"""softmax"""
							lowercase__						:       List[Any]								=							"""none"""



@add_end_docstrings(
    a				,       R"""
        return_all_scores (`bool`, *optional*, defaults to `False`):
            Whether to return all prediction scores or just the one of the predicted class.
        function_to_apply (`str`, *optional*, defaults to `\"default\"`):
            The function to apply to the model outputs in order to retrieve the scores. Accepts four different values:

            - `\"default\"`: if the model has a single label, will apply the sigmoid function on the output. If the model
              has several labels, will apply the softmax function on the output.
            - `\"sigmoid\"`: Applies the sigmoid function on the output.
            - `\"softmax\"`: Applies the softmax function on the output.
            - `\"none\"`: Does not apply any function on the output.
    """				,       )
class 						lowercase    (     a     ):
							lowercase__						:       Optional[int]								=							False
							lowercase__						:       int								=							ClassificationFunction.NONE




							def __init__(						self   :					Optional[Any]	,							**_UpperCamelCase   :					List[str]      )					->				List[str]:



												'''simple docstring'''

												super().__init__(**_UpperCamelCase      )

												self.check_model_type(
												    TF_MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING
												    if self.framework == "tf"
												    else MODEL_FOR_SEQUENCE_CLASSIFICATION_MAPPING      )




							def 	__snake_case(						self   :					int	,							_UpperCamelCase   :					List[str]=None	,							_UpperCamelCase   :					Tuple=None	,							_UpperCamelCase   :					str=""	,							**_UpperCamelCase   :					Any      )					->				List[str]:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE    			=       tokenizer_kwargs

												SCREAMING_SNAKE_CASE    			=       {}
												if hasattr(self.model.config	,							"return_all_scores"      ) and return_all_scores is None:
																	SCREAMING_SNAKE_CASE    			=       self.model.config.return_all_scores

												if isinstance(_UpperCamelCase	,							_UpperCamelCase      ) or top_k is None:
																	SCREAMING_SNAKE_CASE    			=       top_k
																	SCREAMING_SNAKE_CASE    			=       False
												elif return_all_scores is not None:
																	warnings.warn(
																	    "`return_all_scores` is now deprecated,  if want a similar functionality use `top_k=None` instead of"
																	    " `return_all_scores=True` or `top_k=1` instead of `return_all_scores=False`."	,							_UpperCamelCase	,							)
																	if return_all_scores:
																						SCREAMING_SNAKE_CASE    			=       None
																	else:
																						SCREAMING_SNAKE_CASE    			=       1

												if isinstance(_UpperCamelCase	,							_UpperCamelCase      ):
																	SCREAMING_SNAKE_CASE    			=       ClassificationFunction[function_to_apply.upper()]

												if function_to_apply is not None:
																	SCREAMING_SNAKE_CASE    			=       function_to_apply
												return preprocess_params, {}, postprocess_params




							def __call__(						self   :					Any	,							*_UpperCamelCase   :					List[str]	,							**_UpperCamelCase   :					List[Any]      )					->				Dict:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE    			=       super().__call__(*_UpperCamelCase	,							**_UpperCamelCase      )
												# TODO try and retrieve it in a nicer way from _sanitize_parameters.
												SCREAMING_SNAKE_CASE    			=       "top_k" not in kwargs
												if isinstance(args[0]	,							_UpperCamelCase      ) and _legacy:
																	# This pipeline is odd, and return a list when single item is run
																	return [result]
												else:
																	return result




							def 	__snake_case(						self   :					Optional[Any]	,							_UpperCamelCase   :					str	,							**_UpperCamelCase   :					List[Any]      )					->				Dict[str, GenericTensor]:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE    			=       self.framework
												if isinstance(_UpperCamelCase	,							_UpperCamelCase      ):
																	return self.tokenizer(**_UpperCamelCase	,							return_tensors=_UpperCamelCase	,							**_UpperCamelCase      )
												elif isinstance(_UpperCamelCase	,							_UpperCamelCase      ) and len(_UpperCamelCase      ) == 1 and isinstance(inputs[0]	,							_UpperCamelCase      ) and len(inputs[0]      ) == 2:
																	# It used to be valid to use a list of list of list for text pairs, keeping this path for BC
																	return self.tokenizer(
																	    text=inputs[0][0]	,							text_pair=inputs[0][1]	,							return_tensors=_UpperCamelCase	,							**_UpperCamelCase      )
												elif isinstance(_UpperCamelCase	,							_UpperCamelCase      ):
																	# This is likely an invalid usage of the pipeline attempting to pass text pairs.
																	raise ValueError(
																	    "The pipeline received invalid inputs, if you are trying to send text pairs, you can try to send a"
																	    " dictionary `{\"text\": \"My text\", \"text_pair\": \"My pair\"}` in order to send a text pair."      )
												return self.tokenizer(_UpperCamelCase	,							return_tensors=_UpperCamelCase	,							**_UpperCamelCase      )




							def 	__snake_case(						self   :					List[Any]	,							_UpperCamelCase   :					List[Any]      )					->				Optional[Any]:



												'''simple docstring'''

												return self.model(**_UpperCamelCase      )





							def 	__snake_case(						self   :					Tuple	,							_UpperCamelCase   :					Tuple	,							_UpperCamelCase   :					Any=None	,							_UpperCamelCase   :					Optional[int]=1	,							_UpperCamelCase   :					Any=True      )					->				Tuple:



												'''simple docstring'''

												if function_to_apply is None:
																	if self.model.config.problem_type == "multi_label_classification" or self.model.config.num_labels == 1:
																						SCREAMING_SNAKE_CASE    			=       ClassificationFunction.SIGMOID
																	elif self.model.config.problem_type == "single_label_classification" or self.model.config.num_labels > 1:
																						SCREAMING_SNAKE_CASE    			=       ClassificationFunction.SOFTMAX
																	elif hasattr(self.model.config	,							"function_to_apply"      ) and function_to_apply is None:
																						SCREAMING_SNAKE_CASE    			=       self.model.config.function_to_apply
																	else:
																						SCREAMING_SNAKE_CASE    			=       ClassificationFunction.NONE

												SCREAMING_SNAKE_CASE    			=       model_outputs["logits"][0]
												SCREAMING_SNAKE_CASE    			=       outputs.numpy()

												if function_to_apply == ClassificationFunction.SIGMOID:
																	SCREAMING_SNAKE_CASE    			=       sigmoid(_UpperCamelCase      )
												elif function_to_apply == ClassificationFunction.SOFTMAX:
																	SCREAMING_SNAKE_CASE    			=       softmax(_UpperCamelCase      )
												elif function_to_apply == ClassificationFunction.NONE:
																	SCREAMING_SNAKE_CASE    			=       outputs
												else:
																	raise ValueError(F"Unrecognized `function_to_apply` argument: {function_to_apply}"      )

												if top_k == 1 and _legacy:
																	return {"label": self.model.config.idalabel[scores.argmax().item()], "score": scores.max().item()}

												SCREAMING_SNAKE_CASE    			=       [
												    {"label": self.model.config.idalabel[i], "score": score.item()} for i, score in enumerate(_UpperCamelCase      )
												]
												if not _legacy:
																	dict_scores.sort(key=lambda _UpperCamelCase      : x["score"]	,							reverse=_UpperCamelCase      )
																	if top_k is not None:
																						SCREAMING_SNAKE_CASE    			=       dict_scores[:top_k]
												return dict_scores





from typing import Dict, Optional, Union

import numpy as np

from ...image_processing_utils import BaseImageProcessor, BatchFeature, get_size_dict
from ...image_transforms import flip_channel_order, resize, to_channel_dimension_format, to_pil_image
from ...image_utils import (
    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

_lowerCamelCase					:   Union[str, Any]							=		logging.get_logger(__name__)





def 	__lowerCamelCase							(UpperCAmelCase__     :							List[Any]      , UpperCAmelCase__     :							List[Any]      , UpperCAmelCase__     :							Optional[Any]  ):
					return [
					    int(1_0_0_0 * (box[0] / width)  ),
					    int(1_0_0_0 * (box[1] / height)  ),
					    int(1_0_0_0 * (box[2] / width)  ),
					    int(1_0_0_0 * (box[3] / height)  ),
					]





def 	__lowerCamelCase							(UpperCAmelCase__     :							np.ndarray      , UpperCAmelCase__     :							Optional[str]      , UpperCAmelCase__     :							Optional[str] = None  ):
					SCREAMING_SNAKE_CASE    			=       tesseract_config if tesseract_config is not None else ""

					# apply OCR
					SCREAMING_SNAKE_CASE    			=       to_pil_image(UpperCAmelCase__  )
					SCREAMING_SNAKE_CASE			,   SCREAMING_SNAKE_CASE    			=       pil_image.size
					SCREAMING_SNAKE_CASE    			=       pytesseract.image_to_data(UpperCAmelCase__      , lang=UpperCAmelCase__      , output_type="dict"      , config=UpperCAmelCase__  )
					SCREAMING_SNAKE_CASE			,   SCREAMING_SNAKE_CASE			,   SCREAMING_SNAKE_CASE			,   SCREAMING_SNAKE_CASE			,   SCREAMING_SNAKE_CASE    			=       data["text"], data["left"], data["top"], data["width"], data["height"]

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

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

					# finally, normalize the bounding boxes
					SCREAMING_SNAKE_CASE    			=       []
					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    (     a     ):
							lowercase__						:       Optional[int]								=							["""pixel_values"""]




							def __init__(						self   :					int	,							_UpperCamelCase   :					bool = True	,							_UpperCamelCase   :					Dict[str, int] = None	,							_UpperCamelCase   :					PILImageResampling = PILImageResampling.BILINEAR	,							_UpperCamelCase   :					bool = True	,							_UpperCamelCase   :					Optional[str] = None	,							_UpperCamelCase   :					Optional[str] = ""	,							**_UpperCamelCase   :					Optional[int]	,							)					->				None:



												'''simple docstring'''

												super().__init__(**_UpperCamelCase      )
												SCREAMING_SNAKE_CASE    			=       size if size is not None else {"height": 224, "width": 224}
												SCREAMING_SNAKE_CASE    			=       get_size_dict(_UpperCamelCase      )

												SCREAMING_SNAKE_CASE    			=       do_resize
												SCREAMING_SNAKE_CASE    			=       size
												SCREAMING_SNAKE_CASE    			=       resample
												SCREAMING_SNAKE_CASE    			=       apply_ocr
												SCREAMING_SNAKE_CASE    			=       ocr_lang
												SCREAMING_SNAKE_CASE    			=       tesseract_config




							def 	__snake_case(						self   :					List[Any]	,							_UpperCamelCase   :					np.ndarray	,							_UpperCamelCase   :					Dict[str, int]	,							_UpperCamelCase   :					PILImageResampling = PILImageResampling.BILINEAR	,							_UpperCamelCase   :					Optional[Union[str, ChannelDimension]] = None	,							**_UpperCamelCase   :					Any	,							)					->				np.ndarray:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE    			=       get_size_dict(_UpperCamelCase      )
												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()}"      )
												SCREAMING_SNAKE_CASE    			=       (size["height"], size["width"])
												return resize(_UpperCamelCase	,							size=_UpperCamelCase	,							resample=_UpperCamelCase	,							data_format=_UpperCamelCase	,							**_UpperCamelCase      )





							def 	__snake_case(						self   :					Tuple	,							_UpperCamelCase   :					ImageInput	,							_UpperCamelCase   :					bool = None	,							_UpperCamelCase   :					Dict[str, int] = None	,							_UpperCamelCase   :					PILImageResampling = None	,							_UpperCamelCase   :					bool = None	,							_UpperCamelCase   :					Optional[str] = None	,							_UpperCamelCase   :					Optional[str] = None	,							_UpperCamelCase   :					Optional[Union[str, TensorType]] = None	,							_UpperCamelCase   :					ChannelDimension = ChannelDimension.FIRST	,							**_UpperCamelCase   :					str	,							)					->				PIL.Image.Image:



												'''simple docstring'''

												SCREAMING_SNAKE_CASE    			=       do_resize if do_resize is not None else self.do_resize
												SCREAMING_SNAKE_CASE    			=       size if size is not None else self.size
												SCREAMING_SNAKE_CASE    			=       get_size_dict(_UpperCamelCase      )
												SCREAMING_SNAKE_CASE    			=       resample if resample is not None else self.resample
												SCREAMING_SNAKE_CASE    			=       apply_ocr if apply_ocr is not None else self.apply_ocr
												SCREAMING_SNAKE_CASE    			=       ocr_lang if ocr_lang is not None else self.ocr_lang
												SCREAMING_SNAKE_CASE    			=       tesseract_config if tesseract_config is not None else self.tesseract_config

												SCREAMING_SNAKE_CASE    			=       make_list_of_images(_UpperCamelCase      )

												if not valid_images(_UpperCamelCase      ):
																	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."      )

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

												if apply_ocr:
																	requires_backends(self	,							"pytesseract"      )
																	SCREAMING_SNAKE_CASE    			=       []
																	SCREAMING_SNAKE_CASE    			=       []
																	for image in images:
																						SCREAMING_SNAKE_CASE			,   SCREAMING_SNAKE_CASE    			=       apply_tesseract(_UpperCamelCase	,							_UpperCamelCase	,							_UpperCamelCase      )
																						words_batch.append(_UpperCamelCase      )
																						boxes_batch.append(_UpperCamelCase      )

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

												# flip color channels from RGB to BGR (as Detectron2 requires this)
												SCREAMING_SNAKE_CASE    			=       [flip_channel_order(_UpperCamelCase      ) for image in images]
												SCREAMING_SNAKE_CASE    			=       [to_channel_dimension_format(_UpperCamelCase	,							_UpperCamelCase      ) for image in images]

												SCREAMING_SNAKE_CASE    			=       BatchFeature(data={"pixel_values": images}	,							tensor_type=_UpperCamelCase      )

												if apply_ocr:
																	SCREAMING_SNAKE_CASE    			=       words_batch
																	SCREAMING_SNAKE_CASE    			=       boxes_batch
												return data




