"""simple docstring"""




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 			UpperCamelCase__(	__A       ):
						lowerCAmelCase__     :  Union[str, Any]  							=						["image_processor"]
						lowerCAmelCase__     :  Optional[Any]  							=						"SamImageProcessor"





						def __init__(				self						,__UpperCAmelCase   )    -> Dict:
													super().__init__(UpperCAmelCase__   )
													A__		   =							self.image_processor
													A__		   =							-10
													A__		   =							self.image_processor.size['longest_edge']





						def __call__(				self						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,__UpperCAmelCase = None						,**__UpperCAmelCase						,)    -> str:
													A__		   =							self.image_processor(
													    UpperCAmelCase__						,return_tensors=UpperCAmelCase__						,**UpperCAmelCase__						,)

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

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

													A__   ,     A__   ,     A__		   =							self._check_and_preprocess_points(
													    input_points=UpperCAmelCase__						,input_labels=UpperCAmelCase__						,input_boxes=UpperCAmelCase__						,)

													A__		   =							self._normalize_and_convert(
													    UpperCAmelCase__						,UpperCAmelCase__						,input_points=UpperCAmelCase__						,input_labels=UpperCAmelCase__						,input_boxes=UpperCAmelCase__						,return_tensors=UpperCAmelCase__						,)

													return encoding_image_processor





						def  snake_case__		(				self						,__UpperCAmelCase						,__UpperCAmelCase						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,__UpperCAmelCase="pt"						,)    -> List[str]:
													if input_points is not None:
																				if len(UpperCAmelCase__   ) != len(UpperCAmelCase__   ):
																											A__		   =							[
																											    self._normalize_coordinates(self.target_size						,UpperCAmelCase__						,original_sizes[0]   ) for point in input_points
																											]
																				else:
																											A__		   =							[
																											    self._normalize_coordinates(self.target_size						,UpperCAmelCase__						,UpperCAmelCase__   )
																											    for point, original_size in zip(UpperCAmelCase__						,UpperCAmelCase__   )
																											]
																				# 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:
																																		A__   ,     A__		   =							self._pad_points_and_labels(UpperCAmelCase__						,UpperCAmelCase__   )

																				A__		   =							np.array(UpperCAmelCase__   )

													if input_labels is not None:
																				A__		   =							np.array(UpperCAmelCase__   )

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

													if input_boxes is not None:
																				if return_tensors == "pt":
																											A__		   =							torch.from_numpy(UpperCAmelCase__   )
																											# boxes batch size of 1 by default
																											A__		   =							input_boxes.unsqueeze(1   ) if len(input_boxes.shape   ) != 3 else input_boxes
																				elif return_tensors == "tf":
																											A__		   =							tf.convert_to_tensor(UpperCAmelCase__   )
																											# boxes batch size of 1 by default
																											A__		   =							tf.expand_dims(UpperCAmelCase__						,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":
																											A__		   =							torch.from_numpy(UpperCAmelCase__   )
																											# point batch size of 1 by default
																											A__		   =							input_points.unsqueeze(1   ) if len(input_points.shape   ) != 4 else input_points
																				elif return_tensors == "tf":
																											A__		   =							tf.convert_to_tensor(UpperCAmelCase__   )
																											# point batch size of 1 by default
																											A__		   =							tf.expand_dims(UpperCAmelCase__						,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":
																											A__		   =							torch.from_numpy(UpperCAmelCase__   )
																											# point batch size of 1 by default
																											A__		   =							input_labels.unsqueeze(1   ) if len(input_labels.shape   ) != 3 else input_labels
																				elif return_tensors == "tf":
																											A__		   =							tf.convert_to_tensor(UpperCAmelCase__   )
																											# point batch size of 1 by default
																											A__		   =							tf.expand_dims(UpperCAmelCase__						,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						,__UpperCAmelCase						,__UpperCAmelCase   )    -> Optional[int]:
													A__		   =							max([point.shape[0] for point in input_points]   )
													A__		   =							[]
													for i, point in enumerate(UpperCAmelCase__   ):
																				if point.shape[0] != expected_nb_points:
																											A__		   =							np.concatenate(
																											    [point, np.zeros((expected_nb_points - point.shape[0], 2)   ) + self.point_pad_value]						,axis=0   )
																											A__		   =							np.append(input_labels[i]						,[self.point_pad_value]   )
																				processed_input_points.append(UpperCAmelCase__   )
													A__		   =							processed_input_points
													return input_points, input_labels





						def  snake_case__		(				self						,__UpperCAmelCase						,__UpperCAmelCase						,__UpperCAmelCase						,__UpperCAmelCase=False   )    -> Union[str, Any]:
													A__   ,     A__		   =							original_size
													A__   ,     A__		   =							self.image_processor._get_preprocess_shape(UpperCAmelCase__						,longest_edge=UpperCAmelCase__   )
													A__		   =							deepcopy(UpperCAmelCase__   ).astype(UpperCAmelCase__   )

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

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

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

													return coords





						def  snake_case__		(				self						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,__UpperCAmelCase=None						,)    -> List[Any]:
													if input_points is not None:
																				if hasattr(UpperCAmelCase__						,'numpy'   ):  # Checks for TF or Torch tensor
																											A__		   =							input_points.numpy().tolist()

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

													if input_labels is not None:
																				if hasattr(UpperCAmelCase__						,'numpy'   ):
																											A__		   =							input_labels.numpy().tolist()

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

													if input_boxes is not None:
																				if hasattr(UpperCAmelCase__						,'numpy'   ):
																											A__		   =							input_boxes.numpy().tolist()

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

													return input_points, input_labels, input_boxes





						@property
						def  snake_case__		(				self   )    -> Union[str, Any]:
													A__		   =							self.image_processor.model_input_names
													return list(dict.fromkeys(UpperCAmelCase__   )   )





						def  snake_case__		(				self						,*__UpperCAmelCase						,**__UpperCAmelCase   )    -> Tuple:
													return self.image_processor.post_process_masks(*UpperCAmelCase__						,**UpperCAmelCase__   )








"""simple docstring"""





import unittest

from transformers import MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING, AutoTokenizer, is_vision_available
from transformers.pipelines import pipeline
from transformers.pipelines.document_question_answering import apply_tesseract
from transformers.testing_utils import (
    is_pipeline_test,
    nested_simplify,
    require_detectrona,
    require_pytesseract,
    require_tf,
    require_torch,
    require_vision,
    slow,
)

from .test_pipelines_common import ANY


if is_vision_available():
   from PIL import Image

   from transformers.image_utils import load_image
else:




   class 					_lowerCAmelCase  :







    """simple docstring"""







    @staticmethod
    def 					_lowercase (			*UpperCAmelCase__							:			Tuple,					**UpperCAmelCase__							:			List[Any]	):
       pass







   def   _A  (  UpperCamelCase_     :       Union[str, Any])	->						Any:
      '''simple docstring'''


      return None


# This is a pinned image from a specific revision of a document question answering space, hosted by HuggingFace,
# so we can expect it to be available.
_a       =							(
    'https://huggingface.co/spaces/impira/docquery/resolve/2f6c96314dc84dfda62d40de9da55f2f5165d403/invoice.png'
)




@is_pipeline_test
@require_torch
@require_vision
class 					_lowerCAmelCase  (	unittest.TestCase   ):







 """simple docstring"""







 __UpperCAmelCase	:					Tuple   		=	MODEL_FOR_DOCUMENT_QUESTION_ANSWERING_MAPPING


 @require_pytesseract
 @require_vision
 def 					_lowercase (			self							:			Optional[Any],					UpperCAmelCase__							:			Optional[Any],					UpperCAmelCase__							:			Dict,					UpperCAmelCase__							:			Optional[Any]	):
    __lowercase								=						pipeline(
        "document-question-answering",					model=UpperCAmelCase__,					tokenizer=UpperCAmelCase__,					image_processor=UpperCAmelCase__	)

    __lowercase								=						INVOICE_URL
    __lowercase								=						list(zip(*apply_tesseract(load_image(UpperCAmelCase__	),					UpperCAmelCase__,					""	)	)	)
    __lowercase								=						"What is the placebo?"
    __lowercase								=						[
        {
            "image": load_image(UpperCAmelCase__	),
            "question": question,
        },
        {
            "image": image,
            "question": question,
        },
        {
            "image": image,
            "question": question,
            "word_boxes": word_boxes,
        },
    ]
    return dqa_pipeline, examples


 def 					_lowercase (			self							:			int,					UpperCAmelCase__							:			Tuple,					UpperCAmelCase__							:			Any	):
    __lowercase								=						dqa_pipeline(UpperCAmelCase__,					top_k=2	)
    self.assertEqual(
        UpperCAmelCase__,					[
            [
                {"score": ANY(UpperCAmelCase__	), "answer": ANY(UpperCAmelCase__	), "start": ANY(UpperCAmelCase__	), "end": ANY(UpperCAmelCase__	)},
                {"score": ANY(UpperCAmelCase__	), "answer": ANY(UpperCAmelCase__	), "start": ANY(UpperCAmelCase__	), "end": ANY(UpperCAmelCase__	)},
            ]
        ]
        * 3,					)


 @require_torch
 @require_detectrona
 @require_pytesseract
 def 					_lowercase (			self							:			Dict	):
    __lowercase								=						pipeline("document-question-answering",					model="hf-internal-testing/tiny-random-layoutlmv2"	)
    __lowercase								=						INVOICE_URL
    __lowercase								=						"How many cats are there?"

    __lowercase								=						[
        {"score": 0.0_001, "answer": "oy 2312/2019", "start": 3_8, "end": 3_9},
        {"score": 0.0_001, "answer": "oy 2312/2019 DUE", "start": 3_8, "end": 4_0},
    ]
    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(nested_simplify(UpperCAmelCase__,					decimals=4	),					UpperCAmelCase__	)

    __lowercase								=						dqa_pipeline({"image": image, "question": question},					top_k=2	)
    self.assertEqual(nested_simplify(UpperCAmelCase__,					decimals=4	),					UpperCAmelCase__	)

    # This image does not detect ANY text in it, meaning layoutlmv2 should fail.
    # Empty answer probably
    __lowercase								=						"./tests/fixtures/tests_samples/COCO/000000039769.png"
    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(UpperCAmelCase__,					[]	)

    # We can optionnally pass directly the words and bounding boxes
    __lowercase								=						"./tests/fixtures/tests_samples/COCO/000000039769.png"
    __lowercase								=						[]
    __lowercase								=						[]
    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					words=UpperCAmelCase__,					boxes=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(UpperCAmelCase__,					[]	)


 @slow
 @require_torch
 @require_detectrona
 @require_pytesseract
 def 					_lowercase (			self							:			List[str]	):
    __lowercase								=						pipeline(
        "document-question-answering",					model="tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa",					revision="9977165",					)
    __lowercase								=						INVOICE_URL
    __lowercase								=						"What is the invoice number?"

    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.9_944, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.0_009, "answer": "us-001", "start": 1_6, "end": 1_6},
        ],					)

    __lowercase								=						dqa_pipeline({"image": image, "question": question},					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.9_944, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.0_009, "answer": "us-001", "start": 1_6, "end": 1_6},
        ],					)

    __lowercase								=						dqa_pipeline(
        [{"image": image, "question": question}, {"image": image, "question": question}],					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            [
                {"score": 0.9_944, "answer": "us-001", "start": 1_6, "end": 1_6},
                {"score": 0.0_009, "answer": "us-001", "start": 1_6, "end": 1_6},
            ],
        ]
        * 2,					)


 @slow
 @require_torch
 @require_detectrona
 @require_pytesseract
 def 					_lowercase (			self							:			Dict	):
    __lowercase								=						pipeline(
        "document-question-answering",					model="tiennvcs/layoutlmv2-base-uncased-finetuned-docvqa",					revision="9977165",					max_seq_len=5_0,					)
    __lowercase								=						INVOICE_URL
    __lowercase								=						"What is the invoice number?"

    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.9_974, "answer": "1110212019", "start": 2_3, "end": 2_3},
            {"score": 0.9_948, "answer": "us-001", "start": 1_6, "end": 1_6},
        ],					)

    __lowercase								=						dqa_pipeline({"image": image, "question": question},					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.9_974, "answer": "1110212019", "start": 2_3, "end": 2_3},
            {"score": 0.9_948, "answer": "us-001", "start": 1_6, "end": 1_6},
        ],					)

    __lowercase								=						dqa_pipeline(
        [{"image": image, "question": question}, {"image": image, "question": question}],					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            [
                {"score": 0.9_974, "answer": "1110212019", "start": 2_3, "end": 2_3},
                {"score": 0.9_948, "answer": "us-001", "start": 1_6, "end": 1_6},
            ]
        ]
        * 2,					)


 @slow
 @require_torch
 @require_pytesseract
 @require_vision
 def 					_lowercase (			self							:			Optional[Any]	):
    __lowercase								=						AutoTokenizer.from_pretrained(
        "impira/layoutlm-document-qa",					revision="3dc6de3",					add_prefix_space=UpperCAmelCase__	)
    __lowercase								=						pipeline(
        "document-question-answering",					model="impira/layoutlm-document-qa",					tokenizer=UpperCAmelCase__,					revision="3dc6de3",					)
    __lowercase								=						INVOICE_URL
    __lowercase								=						"What is the invoice number?"

    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.4_251, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.0_819, "answer": "1110212019", "start": 2_3, "end": 2_3},
        ],					)

    __lowercase								=						dqa_pipeline({"image": image, "question": question},					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.4_251, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.0_819, "answer": "1110212019", "start": 2_3, "end": 2_3},
        ],					)

    __lowercase								=						dqa_pipeline(
        [{"image": image, "question": question}, {"image": image, "question": question}],					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            [
                {"score": 0.4_251, "answer": "us-001", "start": 1_6, "end": 1_6},
                {"score": 0.0_819, "answer": "1110212019", "start": 2_3, "end": 2_3},
            ]
        ]
        * 2,					)

    __lowercase								=						list(zip(*apply_tesseract(load_image(UpperCAmelCase__	),					UpperCAmelCase__,					""	)	)	)

    # This model should also work if `image` is set to None
    __lowercase								=						dqa_pipeline({"image": None, "word_boxes": word_boxes, "question": question},					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.4_251, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.0_819, "answer": "1110212019", "start": 2_3, "end": 2_3},
        ],					)


 @slow
 @require_torch
 @require_pytesseract
 @require_vision
 def 					_lowercase (			self							:			Union[str, Any]	):
    __lowercase								=						AutoTokenizer.from_pretrained(
        "impira/layoutlm-document-qa",					revision="3dc6de3",					add_prefix_space=UpperCAmelCase__	)
    __lowercase								=						pipeline(
        "document-question-answering",					model="impira/layoutlm-document-qa",					tokenizer=UpperCAmelCase__,					revision="3dc6de3",					max_seq_len=5_0,					)
    __lowercase								=						INVOICE_URL
    __lowercase								=						"What is the invoice number?"

    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.9_999, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.9_998, "answer": "us-001", "start": 1_6, "end": 1_6},
        ],					)

    __lowercase								=						dqa_pipeline(
        [{"image": image, "question": question}, {"image": image, "question": question}],					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            [
                {"score": 0.9_999, "answer": "us-001", "start": 1_6, "end": 1_6},
                {"score": 0.9_998, "answer": "us-001", "start": 1_6, "end": 1_6},
            ]
        ]
        * 2,					)

    __lowercase								=						list(zip(*apply_tesseract(load_image(UpperCAmelCase__	),					UpperCAmelCase__,					""	)	)	)

    # This model should also work if `image` is set to None
    __lowercase								=						dqa_pipeline({"image": None, "word_boxes": word_boxes, "question": question},					top_k=2	)
    self.assertEqual(
        nested_simplify(UpperCAmelCase__,					decimals=4	),					[
            {"score": 0.9_999, "answer": "us-001", "start": 1_6, "end": 1_6},
            {"score": 0.9_998, "answer": "us-001", "start": 1_6, "end": 1_6},
        ],					)


 @slow
 @require_torch
 def 					_lowercase (			self							:			Dict	):
    __lowercase								=						pipeline(
        "document-question-answering",					model="naver-clova-ix/donut-base-finetuned-docvqa",					tokenizer=AutoTokenizer.from_pretrained("naver-clova-ix/donut-base-finetuned-docvqa"	),					feature_extractor="naver-clova-ix/donut-base-finetuned-docvqa",					)

    __lowercase								=						INVOICE_URL
    __lowercase								=						"What is the invoice number?"
    __lowercase								=						dqa_pipeline(image=UpperCAmelCase__,					question=UpperCAmelCase__,					top_k=2	)
    self.assertEqual(nested_simplify(UpperCAmelCase__,					decimals=4	),					[{"answer": "us-001"}]	)



 @require_tf
 @unittest.skip("Document question answering not implemented in TF"	)
 def 					_lowercase (			self							:			List[Any]	):
    pass




