diff --git a/.circleci/config.yml b/.circleci/config.yml index b15462ea21d9..7a7f4aaf7c1b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -175,6 +175,28 @@ jobs: - store_artifacts: path: ~/transformers/installed.txt - run: make check-repository-consistency + - run: + name: "Test import with all backends (torch + PIL + torchvision)" + command: python -c "from transformers import *" || (echo '🚨 import failed with all backends. Fix unprotected imports!! 🚨'; exit 1) + - run: + name: "Test import with torch only (no PIL, no torchvision)" + command: | + uv pip uninstall Pillow torchvision -q + python -c "from transformers import *" || (echo '🚨 import failed with torch only (no PIL). Fix unprotected imports!! 🚨'; exit 1) + uv pip install -e ".[quality]" -q + - run: + name: "Test import with PIL only (no torch, no torchvision)" + command: | + uv pip uninstall torch torchvision torchaudio -q + python -c "from transformers import *" || (echo '🚨 import failed with PIL only (no torch). Fix unprotected imports!! 🚨'; exit 1) + uv pip install -e ".[quality]" -q + - run: + name: "Test import with torch + PIL, no torchvision" + command: | + uv pip uninstall torchvision -q + python -c "from transformers import *" || (echo '🚨 import failed with torch+PIL but no torchvision. Fix unprotected imports!! 🚨'; exit 1) + uv pip install -e ".[quality]" -q + workflows: version: 2 diff --git a/src/transformers/__init__.py b/src/transformers/__init__.py index 4034a06a94ce..7e1296f6ea2e 100755 --- a/src/transformers/__init__.py +++ b/src/transformers/__init__.py @@ -330,7 +330,7 @@ name for name in dir(dummy_vision_objects) if not name.startswith("_") ] else: - _import_structure["image_processing_backends"] = ["PilBackend", "TorchvisionBackend"] + _import_structure["image_processing_backends"] = ["PilBackend"] _import_structure["image_processing_base"] = ["ImageProcessingMixin"] _import_structure["image_processing_utils"] = ["BaseImageProcessor"] _import_structure["image_utils"] = ["ImageFeatureExtractionMixin"] @@ -345,6 +345,8 @@ name for name in dir(dummy_torchvision_objects) if not name.startswith("_") ] else: + _import_structure.setdefault("image_processing_backends", []) + _import_structure["image_processing_backends"] += ["TorchvisionBackend"] _import_structure["video_processing_utils"] = ["BaseVideoProcessor"] # PyTorch-backed objects diff --git a/src/transformers/image_processing_backends.py b/src/transformers/image_processing_backends.py index 73b26a59d1b2..da29f74c6384 100644 --- a/src/transformers/image_processing_backends.py +++ b/src/transformers/image_processing_backends.py @@ -58,9 +58,8 @@ is_torchvision_available, is_vision_available, logging, - requires_backends, ) -from .utils.import_utils import is_rocm_platform, is_torchdynamo_compiling +from .utils.import_utils import is_rocm_platform, is_torchdynamo_compiling, requires if is_vision_available(): @@ -81,11 +80,11 @@ logger = logging.get_logger(__name__) +@requires(backends=("torch", "torchvision")) class TorchvisionBackend(BaseImageProcessor): """Torchvision backend for GPU-accelerated batched image processing.""" def __init__(self, **kwargs: Unpack[ImagesKwargs]): - requires_backends(self, "torchvision") super().__init__(**kwargs) self._set_attributes(**kwargs) @@ -407,6 +406,7 @@ def _preprocess( return BatchFeature(data={"pixel_values": processed_images}, tensor_type=return_tensors) +@requires(backends=("vision",)) class PilBackend(BaseImageProcessor): """PIL/NumPy backend for portable CPU-only image processing.""" diff --git a/src/transformers/models/aria/image_processing_pil_aria.py b/src/transformers/models/aria/image_processing_pil_aria.py index 760c26c640cb..f2209b8dcfd6 100644 --- a/src/transformers/models/aria/image_processing_pil_aria.py +++ b/src/transformers/models/aria/image_processing_pil_aria.py @@ -25,14 +25,12 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_aria import AriaImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class AriaImageProcessorPil(PilBackend): model_input_names = ["pixel_values", "pixel_mask", "num_crops"] @@ -67,7 +65,7 @@ def _resize_for_patching( self, image: np.ndarray, target_resolution: tuple, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", ) -> np.ndarray: """Resize an image to a target resolution while maintaining aspect ratio.""" new_height, new_width = get_patch_output_size( @@ -92,7 +90,7 @@ def get_image_patches( image: np.ndarray, grid_pinpoints: list[list[int]], patch_size: int, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", ) -> list[np.ndarray]: """ Process an image with variable resolutions by dividing it into patches. @@ -104,7 +102,7 @@ def get_image_patches( A list of possible resolutions as (height, width) pairs. patch_size (`int`): Size of each square patch to divide the image into. - resample (`PILImageResampling | tvF.InterpolationMode | int | None`): + resample (`PILImageResampling | int | None`): Resampling filter to use when resizing. Returns: @@ -133,7 +131,7 @@ def _preprocess( min_image_size: int = 336, split_resolutions: list[list[int]] | None = None, split_image: bool = False, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, **kwargs, ) -> BatchFeature: if max_image_size not in [490, 980]: diff --git a/src/transformers/models/beit/image_processing_pil_beit.py b/src/transformers/models/beit/image_processing_pil_beit.py index ffcdbf6dfeca..976e3dfdee33 100644 --- a/src/transformers/models/beit/image_processing_pil_beit.py +++ b/src/transformers/models/beit/image_processing_pil_beit.py @@ -14,6 +14,9 @@ """Image processor class for BEiT.""" import numpy as np +import torch +import torch.nn.functional as F +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -26,19 +29,13 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available +from ...utils import TensorType, auto_docstring, is_torch_available +from ...utils.import_utils import requires from .image_processing_beit import BeitImageProcessorKwargs -if is_torch_available(): - import torch - import torch.nn.functional as F - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class BeitImageProcessorPil(PilBackend): """PIL backend for BEiT with reduce_label support.""" diff --git a/src/transformers/models/bridgetower/image_processing_pil_bridgetower.py b/src/transformers/models/bridgetower/image_processing_pil_bridgetower.py index c65db0554d0d..c9f359f9e8b8 100644 --- a/src/transformers/models/bridgetower/image_processing_pil_bridgetower.py +++ b/src/transformers/models/bridgetower/image_processing_pil_bridgetower.py @@ -24,14 +24,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_bridgetower import BridgeTowerImageProcessorKwargs, get_resize_output_image_size -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class BridgeTowerImageProcessorPil(PilBackend): """PIL backend for BridgeTower with custom resize and center_crop.""" @@ -59,7 +57,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", size_divisor: int = 32, **kwargs, ) -> np.ndarray: @@ -84,7 +82,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/conditional_detr/image_processing_pil_conditional_detr.py b/src/transformers/models/conditional_detr/image_processing_pil_conditional_detr.py index b58d1fa5ba4b..423b5885f301 100644 --- a/src/transformers/models/conditional_detr/image_processing_pil_conditional_detr.py +++ b/src/transformers/models/conditional_detr/image_processing_pil_conditional_detr.py @@ -57,6 +57,7 @@ logging, requires_backends, ) +from ...utils.import_utils import requires from .image_processing_conditional_detr import ( ConditionalDetrImageProcessorKwargs, compute_segments, @@ -262,6 +263,7 @@ def prepare_coco_panoptic_annotation( return new_target +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class ConditionalDetrImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -676,6 +678,7 @@ def _preprocess( ] return encoded_inputs + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None, top_k: int = 100 ): @@ -736,6 +739,7 @@ def post_process_object_detection( return results + @requires(backends=("vision", "torch")) def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple[int, int]] | None = None): """ Converts the output of [`ConditionalDetrForSegmentation`] into semantic segmentation maps. Only supports PyTorch. @@ -784,6 +788,7 @@ def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple[i return semantic_segmentation + @requires(backends=("vision", "torch")) def post_process_instance_segmentation( self, outputs, @@ -872,6 +877,7 @@ def post_process_instance_segmentation( results.append({"segmentation": segmentation, "segments_info": segments}) return results + @requires(backends=("vision", "torch")) def post_process_panoptic_segmentation( self, outputs, diff --git a/src/transformers/models/conditional_detr/modular_conditional_detr.py b/src/transformers/models/conditional_detr/modular_conditional_detr.py index fbdf57697d2e..5a0956cc85ed 100644 --- a/src/transformers/models/conditional_detr/modular_conditional_detr.py +++ b/src/transformers/models/conditional_detr/modular_conditional_detr.py @@ -34,6 +34,7 @@ requires_backends, ) from ...utils.generic import can_return_tuple, merge_with_config_defaults +from ...utils.import_utils import requires from ...utils.output_capturing import OutputRecorder, capture_outputs from ..deformable_detr.modeling_deformable_detr import inverse_sigmoid from ..detr.image_processing_detr import DetrImageProcessor @@ -173,6 +174,7 @@ def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple[i class ConditionalDetrImageProcessorPil(DetrImageProcessorPil): + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None, top_k: int = 100 ): @@ -233,6 +235,7 @@ def post_process_object_detection( return results + @requires(backends=("vision", "torch")) def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple[int, int]] | None = None): """ Converts the output of [`ConditionalDetrForSegmentation`] into semantic segmentation maps. Only supports PyTorch. diff --git a/src/transformers/models/convnext/image_processing_pil_convnext.py b/src/transformers/models/convnext/image_processing_pil_convnext.py index cfe7e991376b..4dc2b9428ac5 100644 --- a/src/transformers/models/convnext/image_processing_pil_convnext.py +++ b/src/transformers/models/convnext/image_processing_pil_convnext.py @@ -26,14 +26,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_convnext import ConvNextImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class ConvNextImageProcessorPil(PilBackend): """PIL backend for ConvNeXT with custom resize.""" @@ -57,7 +55,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", crop_pct: float = 224 / 256, **kwargs, ) -> np.ndarray: @@ -98,7 +96,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/deepseek_vl/image_processing_pil_deepseek_vl.py b/src/transformers/models/deepseek_vl/image_processing_pil_deepseek_vl.py index d29296535277..dd8750cc0690 100644 --- a/src/transformers/models/deepseek_vl/image_processing_pil_deepseek_vl.py +++ b/src/transformers/models/deepseek_vl/image_processing_pil_deepseek_vl.py @@ -34,9 +34,11 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_deepseek_vl import DeepseekVLImageProcessorKwargs +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class DeepseekVLImageProcessorPil(PilBackend): resample = PILImageResampling.BICUBIC diff --git a/src/transformers/models/deepseek_vl_hybrid/image_processing_deepseek_vl_hybrid.py b/src/transformers/models/deepseek_vl_hybrid/image_processing_deepseek_vl_hybrid.py index d9ece27c4dbe..e9b87784a241 100644 --- a/src/transformers/models/deepseek_vl_hybrid/image_processing_deepseek_vl_hybrid.py +++ b/src/transformers/models/deepseek_vl_hybrid/image_processing_deepseek_vl_hybrid.py @@ -22,17 +22,14 @@ from typing import Union import torch +import torchvision.transforms.v2.functional as tvF from ...image_processing_backends import TorchvisionBackend from ...image_processing_utils import BatchFeature, get_size_dict from ...image_transforms import group_images_by_shape, reorder_images from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling, SizeDict from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - import torchvision.transforms.v2.functional as tvF +from ...utils import TensorType, auto_docstring class DeepseekVLHybridImageProcessorKwargs(ImagesKwargs, total=False): @@ -176,8 +173,8 @@ def _preprocess( size: SizeDict, high_res_size: SizeDict, min_size: int, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", - high_res_resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", + high_res_resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/deepseek_vl_hybrid/image_processing_pil_deepseek_vl_hybrid.py b/src/transformers/models/deepseek_vl_hybrid/image_processing_pil_deepseek_vl_hybrid.py index 751c7c6a891d..9365a1a82a02 100644 --- a/src/transformers/models/deepseek_vl_hybrid/image_processing_pil_deepseek_vl_hybrid.py +++ b/src/transformers/models/deepseek_vl_hybrid/image_processing_pil_deepseek_vl_hybrid.py @@ -34,16 +34,16 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available +from ...utils import TensorType, auto_docstring, is_torch_available +from ...utils.import_utils import requires from .image_processing_deepseek_vl_hybrid import DeepseekVLHybridImageProcessorKwargs if is_torch_available(): import torch -if is_torchvision_available(): - import torchvision.transforms.v2.functional as tvF +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class DeepseekVLHybridImageProcessorPil(PilBackend): resample = PILImageResampling.BICUBIC @@ -150,8 +150,8 @@ def _preprocess( size: SizeDict, high_res_size: SizeDict, min_size: int, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", - high_res_resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", + high_res_resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/deepseek_vl_hybrid/modeling_deepseek_vl_hybrid.py b/src/transformers/models/deepseek_vl_hybrid/modeling_deepseek_vl_hybrid.py index 672be5837501..eb85a8d02a76 100644 --- a/src/transformers/models/deepseek_vl_hybrid/modeling_deepseek_vl_hybrid.py +++ b/src/transformers/models/deepseek_vl_hybrid/modeling_deepseek_vl_hybrid.py @@ -29,12 +29,7 @@ from ...modeling_outputs import BaseModelOutputWithPooling, ModelOutput from ...modeling_utils import PreTrainedModel from ...processing_utils import Unpack -from ...utils import ( - TransformersKwargs, - auto_docstring, - can_return_tuple, - torch_compilable_check, -) +from ...utils import TransformersKwargs, auto_docstring, can_return_tuple, torch_compilable_check from ..auto import AutoModel from .configuration_deepseek_vl_hybrid import DeepseekVLHybridConfig diff --git a/src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.py b/src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.py index 5094a139e0bd..e76a9a04f1de 100644 --- a/src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.py +++ b/src/transformers/models/deepseek_vl_hybrid/modular_deepseek_vl_hybrid.py @@ -44,7 +44,6 @@ TransformersKwargs, auto_docstring, can_return_tuple, - is_torchvision_available, logging, ) from ..auto import CONFIG_MAPPING, AutoConfig, AutoModel @@ -61,9 +60,6 @@ from ..sam.modeling_sam import SamLayerNorm, SamVisionNeck -if is_torchvision_available(): - import torchvision.transforms.v2.functional as tvF - logger = logging.get_logger(__name__) @@ -539,8 +535,8 @@ def _preprocess( size: SizeDict, high_res_size: SizeDict, min_size: int, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", - high_res_resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", + high_res_resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, @@ -650,8 +646,8 @@ def _preprocess( size: SizeDict, high_res_size: SizeDict, min_size: int, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", - high_res_resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", + high_res_resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/deformable_detr/image_processing_pil_deformable_detr.py b/src/transformers/models/deformable_detr/image_processing_pil_deformable_detr.py index 022b0c8a9129..87fe051d8a37 100644 --- a/src/transformers/models/deformable_detr/image_processing_pil_deformable_detr.py +++ b/src/transformers/models/deformable_detr/image_processing_pil_deformable_detr.py @@ -49,7 +49,7 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torch_available, is_vision_available -from ...utils.import_utils import requires_backends +from ...utils.import_utils import requires, requires_backends from .image_processing_deformable_detr import DeformableDetrImageProcessorKwargs @@ -246,6 +246,7 @@ def prepare_coco_panoptic_annotation( return new_target +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class DeformableDetrImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -660,6 +661,7 @@ def _preprocess( ] return encoded_inputs + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None, top_k: int = 100 ): diff --git a/src/transformers/models/deformable_detr/modular_deformable_detr.py b/src/transformers/models/deformable_detr/modular_deformable_detr.py index 584516fa6df9..7af635a9ab30 100644 --- a/src/transformers/models/deformable_detr/modular_deformable_detr.py +++ b/src/transformers/models/deformable_detr/modular_deformable_detr.py @@ -36,7 +36,7 @@ torch_compilable_check, ) from ...utils.generic import can_return_tuple, merge_with_config_defaults -from ...utils.import_utils import requires_backends +from ...utils.import_utils import requires, requires_backends from ...utils.output_capturing import OutputRecorder, capture_outputs from ..detr.image_processing_detr import DetrImageProcessor from ..detr.image_processing_pil_detr import DetrImageProcessorPil @@ -131,6 +131,7 @@ def post_process_panoptic_segmentation(self): class DeformableDetrImageProcessorPil(DetrImageProcessorPil): + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None, top_k: int = 100 ): diff --git a/src/transformers/models/detr/image_processing_pil_detr.py b/src/transformers/models/detr/image_processing_pil_detr.py index 0a145aaffbc9..d45a34a6cee3 100644 --- a/src/transformers/models/detr/image_processing_pil_detr.py +++ b/src/transformers/models/detr/image_processing_pil_detr.py @@ -50,6 +50,7 @@ is_vision_available, logging, ) +from ...utils.import_utils import requires from .image_processing_detr import ( DetrImageProcessorKwargs, compute_segments, @@ -253,6 +254,7 @@ def prepare_coco_panoptic_annotation( return new_target +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class DetrImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -667,6 +669,7 @@ def _preprocess( ] return encoded_inputs + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] | None = None ): @@ -725,6 +728,7 @@ def post_process_object_detection( return results + @requires(backends=("vision", "torch")) def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple[int, int]] | None = None): """ Converts the output of [`DetrForSegmentation`] into semantic segmentation maps. Only supports PyTorch. @@ -777,6 +781,7 @@ def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple[i return semantic_segmentation + @requires(backends=("vision", "torch")) def post_process_instance_segmentation( self, outputs, @@ -865,6 +870,7 @@ def post_process_instance_segmentation( results.append({"segmentation": segmentation, "segments_info": segments}) return results + @requires(backends=("vision", "torch")) def post_process_panoptic_segmentation( self, outputs, diff --git a/src/transformers/models/donut/image_processing_donut.py b/src/transformers/models/donut/image_processing_donut.py index dd1992878493..9e4cb28e2be9 100644 --- a/src/transformers/models/donut/image_processing_donut.py +++ b/src/transformers/models/donut/image_processing_donut.py @@ -13,6 +13,9 @@ # limitations under the License. """Image processor class for Donut.""" +import torch +from torchvision.transforms.v2 import functional as tvF + from ...image_processing_backends import TorchvisionBackend from ...image_processing_utils import BatchFeature from ...image_transforms import group_images_by_shape, reorder_images @@ -24,12 +27,7 @@ SizeDict, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - import torch - from torchvision.transforms.v2 import functional as tvF +from ...utils import TensorType, auto_docstring class DonutImageProcessorKwargs(ImagesKwargs, total=False): diff --git a/src/transformers/models/donut/image_processing_pil_donut.py b/src/transformers/models/donut/image_processing_pil_donut.py index f3fc4521405a..15cdf5ac0d46 100644 --- a/src/transformers/models/donut/image_processing_pil_donut.py +++ b/src/transformers/models/donut/image_processing_pil_donut.py @@ -26,14 +26,12 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_donut import DonutImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class DonutImageProcessorPil(PilBackend): """PIL backend for Donut with align_long_axis, thumbnail, and pad_image.""" @@ -132,7 +130,7 @@ def thumbnail( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, **kwargs, ) -> np.ndarray: """Resize the image to make a thumbnail.""" @@ -163,7 +161,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/dpt/image_processing_pil_dpt.py b/src/transformers/models/dpt/image_processing_pil_dpt.py index d977a2f3983c..d2d1afe92996 100644 --- a/src/transformers/models/dpt/image_processing_pil_dpt.py +++ b/src/transformers/models/dpt/image_processing_pil_dpt.py @@ -30,30 +30,23 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - logging, - requires_backends, -) +from ...utils import TensorType, auto_docstring, logging, requires_backends +from ...utils.import_utils import requires from .image_processing_dpt import DPTImageProcessorKwargs, get_resize_output_image_size if TYPE_CHECKING: from ...modeling_outputs import DepthEstimatorOutput -if is_torch_available(): - import torch +import torch +from torchvision.transforms.v2 import functional as tvF -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF logger = logging.get_logger(__name__) @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class DPTImageProcessorPil(PilBackend): """PIL backend for DPT with custom resize and pad.""" @@ -156,12 +149,7 @@ def resize( ) return super().resize(image, output_size, resample, **kwargs) - def pad_image( - self, - image: np.ndarray, - size_divisor: int = 1, - **kwargs, - ) -> np.ndarray: + def pad_image(self, image: np.ndarray, size_divisor: int = 1, **kwargs) -> np.ndarray: """Center pad image to be a multiple of size_divisor.""" def _get_pad(size, size_divisor): @@ -206,11 +194,7 @@ def _preprocess( image = self.reduce_label(image) if do_resize: image = self.resize( - image, - size, - resample, - ensure_multiple_of=ensure_multiple_of, - keep_aspect_ratio=keep_aspect_ratio, + image, size, resample, ensure_multiple_of=ensure_multiple_of, keep_aspect_ratio=keep_aspect_ratio ) if do_rescale: image = self.rescale(image, rescale_factor) @@ -245,9 +229,7 @@ def post_process_semantic_segmentation(self, outputs, target_sizes: list[tuple] return semantic_segmentation def post_process_depth_estimation( - self, - outputs: "DepthEstimatorOutput", - target_sizes: TensorType | list[tuple[int, int]] | None = None, + self, outputs: "DepthEstimatorOutput", target_sizes: TensorType | list[tuple[int, int]] | None = None ) -> list[dict[str, TensorType]]: """Converts the raw output of [`DepthEstimatorOutput`] into final depth predictions.""" requires_backends(self, "torch") diff --git a/src/transformers/models/efficientloftr/image_processing_efficientloftr.py b/src/transformers/models/efficientloftr/image_processing_efficientloftr.py index ea99957a95a6..80897ada4243 100644 --- a/src/transformers/models/efficientloftr/image_processing_efficientloftr.py +++ b/src/transformers/models/efficientloftr/image_processing_efficientloftr.py @@ -6,6 +6,7 @@ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨 import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import TorchvisionBackend from ...image_processing_utils import BatchFeature @@ -21,16 +22,13 @@ to_numpy_array, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available, is_vision_available +from ...utils import TensorType, auto_docstring, is_vision_available from .modeling_efficientloftr import EfficientLoFTRKeypointMatchingOutput if is_vision_available(): from PIL import Image, ImageDraw -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - class EfficientLoFTRImageProcessorKwargs(ImagesKwargs, total=False): r""" diff --git a/src/transformers/models/efficientloftr/image_processing_pil_efficientloftr.py b/src/transformers/models/efficientloftr/image_processing_pil_efficientloftr.py index dce9d9e5f411..b7c6da2e648c 100644 --- a/src/transformers/models/efficientloftr/image_processing_pil_efficientloftr.py +++ b/src/transformers/models/efficientloftr/image_processing_pil_efficientloftr.py @@ -13,7 +13,7 @@ from ...image_utils import ImageInput, PILImageResampling, SizeDict, to_numpy_array from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, is_vision_available -from ...utils.import_utils import requires_backends +from ...utils.import_utils import requires, requires_backends from .image_processing_efficientloftr import EfficientLoFTRImageProcessorKwargs, validate_and_format_image_pairs from .modeling_efficientloftr import EfficientLoFTRKeypointMatchingOutput @@ -27,17 +27,13 @@ from torchvision.transforms.v2 import functional as tvF -def is_grayscale( - image: np.ndarray, -): +def is_grayscale(image: np.ndarray): if image.shape[0] == 1: return True return np.all(image[0, ...] == image[1, ...]) and np.all(image[1, ...] == image[2, ...]) -def convert_to_grayscale( - image: ImageInput, -) -> ImageInput: +def convert_to_grayscale(image: ImageInput) -> ImageInput: """ Converts an image to grayscale format using the NTSC formula. Only support numpy and PIL Image. @@ -65,7 +61,7 @@ def convert_to_grayscale( return image -@auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class EfficientLoFTRImageProcessorPil(PilBackend): valid_kwargs = EfficientLoFTRImageProcessorKwargs resample = PILImageResampling.BILINEAR @@ -84,11 +80,7 @@ def __init__(self, **kwargs: Unpack[EfficientLoFTRImageProcessorKwargs]): def preprocess(self, images: ImageInput, **kwargs: Unpack[EfficientLoFTRImageProcessorKwargs]) -> BatchFeature: return super().preprocess(images, **kwargs) - def _prepare_images_structure( - self, - images: ImageInput, - **kwargs, - ) -> ImageInput: + def _prepare_images_structure(self, images: ImageInput, **kwargs) -> ImageInput: # we need to handle image pairs validation and flattening images = self.fetch_images(images) return validate_and_format_image_pairs(images) @@ -186,9 +178,7 @@ def post_process_keypoint_matching( return results def visualize_keypoint_matching( - self, - images: ImageInput, - keypoint_matching_output: list[dict[str, torch.Tensor]], + self, images: ImageInput, keypoint_matching_output: list[dict[str, torch.Tensor]] ) -> list["Image.Image"]: """ Plots the image pairs side by side with the detected keypoints as well as the matching between them. @@ -225,11 +215,7 @@ def visualize_keypoint_matching( keypoints0_x, keypoints0_y, keypoints1_x, keypoints1_y, pair_output["matching_scores"] ): color = self._get_color(matching_score) - draw.line( - (keypoint0_x, keypoint0_y, keypoint1_x + width0, keypoint1_y), - fill=color, - width=3, - ) + draw.line((keypoint0_x, keypoint0_y, keypoint1_x + width0, keypoint1_y), fill=color, width=3) draw.ellipse((keypoint0_x - 2, keypoint0_y - 2, keypoint0_x + 2, keypoint0_y + 2), fill="black") draw.ellipse( (keypoint1_x + width0 - 2, keypoint1_y - 2, keypoint1_x + width0 + 2, keypoint1_y + 2), diff --git a/src/transformers/models/efficientloftr/modular_efficientloftr.py b/src/transformers/models/efficientloftr/modular_efficientloftr.py index 106281549038..600620806d64 100644 --- a/src/transformers/models/efficientloftr/modular_efficientloftr.py +++ b/src/transformers/models/efficientloftr/modular_efficientloftr.py @@ -1,7 +1,7 @@ import torch from ...utils import TensorType -from ...utils.import_utils import requires_backends +from ...utils.import_utils import requires, requires_backends from ..superglue.image_processing_pil_superglue import SuperGlueImageProcessorPil from ..superglue.image_processing_superglue import SuperGlueImageProcessor from .modeling_efficientloftr import EfficientLoFTRKeypointMatchingOutput @@ -68,6 +68,7 @@ def post_process_keypoint_matching( return results +@requires(backends=("vision", "torch", "torchvision")) class EfficientLoFTRImageProcessorPil(SuperGlueImageProcessorPil): def post_process_keypoint_matching( self, diff --git a/src/transformers/models/efficientnet/image_processing_pil_efficientnet.py b/src/transformers/models/efficientnet/image_processing_pil_efficientnet.py index f553411af063..3b23a8ef6e3d 100644 --- a/src/transformers/models/efficientnet/image_processing_pil_efficientnet.py +++ b/src/transformers/models/efficientnet/image_processing_pil_efficientnet.py @@ -24,14 +24,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_efficientnet import EfficientNetImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class EfficientNetImageProcessorPil(PilBackend): """PIL backend for EfficientNet with rescale offset and include_top.""" @@ -71,7 +69,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/eomt/image_processing_pil_eomt.py b/src/transformers/models/eomt/image_processing_pil_eomt.py index 723fa949102e..e4bb98690527 100644 --- a/src/transformers/models/eomt/image_processing_pil_eomt.py +++ b/src/transformers/models/eomt/image_processing_pil_eomt.py @@ -16,6 +16,8 @@ import math import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -31,20 +33,8 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, -) - - -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_eomt import ( EomtImageProcessorKwargs, compute_segments, @@ -92,6 +82,7 @@ def convert_segmentation_map_to_binary_masks( @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class EomtImageProcessorPil(PilBackend): valid_kwargs = EomtImageProcessorKwargs resample = PILImageResampling.BILINEAR @@ -231,9 +222,7 @@ def _preprocess_image_like_inputs( instance_id = instance_id_to_semantic_id # Use instance2class_id mapping per image masks, classes = convert_segmentation_map_to_binary_masks( - segmentation_map, - instance_id, - ignore_index=ignore_index, + segmentation_map, instance_id, ignore_index=ignore_index ) mask_labels.append(torch.from_numpy(masks)) @@ -349,10 +338,7 @@ def merge_image_patches( for idx, (logit_sum, count) in enumerate(zip(aggregated_logits, patch_counts)): averaged_logits = logit_sum / count.clamp(min=1) resized_logits = torch.nn.functional.interpolate( - averaged_logits[None, ...], - size=target_sizes[idx], - mode="bilinear", - align_corners=False, + averaged_logits[None, ...], size=target_sizes[idx], mode="bilinear", align_corners=False )[0] reconstructed_logits.append(resized_logits) @@ -360,10 +346,7 @@ def merge_image_patches( return reconstructed_logits def unpad_image( - self, - segmentation_logits: torch.Tensor, - target_sizes: list[tuple[int, int]], - size: dict[str, int], + self, segmentation_logits: torch.Tensor, target_sizes: list[tuple[int, int]], size: dict[str, int] ) -> list[torch.Tensor]: """Restores panoptic segmentation logits to their original image resolutions.""" @@ -381,10 +364,7 @@ def unpad_image( return resized_logits def post_process_semantic_segmentation( - self, - outputs, - target_sizes: list[tuple[int, int]], - size: dict[str, int] | None = None, + self, outputs, target_sizes: list[tuple[int, int]], size: dict[str, int] | None = None ) -> np.ndarray: """Post-processes model outputs into final semantic segmentation prediction.""" @@ -395,11 +375,7 @@ def post_process_semantic_segmentation( patch_offsets = outputs.patch_offsets output_size = get_target_size(size) - masks_queries_logits = torch.nn.functional.interpolate( - masks_queries_logits, - size=output_size, - mode="bilinear", - ) + masks_queries_logits = torch.nn.functional.interpolate(masks_queries_logits, size=output_size, mode="bilinear") # Remove the null class `[..., :-1]` masks_classes = class_queries_logits.softmax(dim=-1)[..., :-1] @@ -445,11 +421,7 @@ def post_process_panoptic_segmentation( num_labels = class_queries_logits.shape[-1] - 1 output_size = get_target_size(size) - masks_queries_logits = torch.nn.functional.interpolate( - masks_queries_logits, - size=output_size, - mode="bilinear", - ) + masks_queries_logits = torch.nn.functional.interpolate(masks_queries_logits, size=output_size, mode="bilinear") mask_probs_batch = self.unpad_image(masks_queries_logits, target_sizes, size) pred_scores_batch, pred_labels_batch = class_queries_logits.softmax(dim=-1).max(-1) @@ -482,11 +454,7 @@ def post_process_panoptic_segmentation( return results def post_process_instance_segmentation( - self, - outputs, - target_sizes: list[tuple[int, int]], - threshold: float = 0.8, - size: dict[str, int] | None = None, + self, outputs, target_sizes: list[tuple[int, int]], threshold: float = 0.8, size: dict[str, int] | None = None ): """Post-processes model outputs into Instance Segmentation Predictions.""" @@ -496,11 +464,7 @@ def post_process_instance_segmentation( class_queries_logits = outputs.class_queries_logits output_size = get_target_size(size) - masks_queries_logits = torch.nn.functional.interpolate( - masks_queries_logits, - size=output_size, - mode="bilinear", - ) + masks_queries_logits = torch.nn.functional.interpolate(masks_queries_logits, size=output_size, mode="bilinear") mask_probs_batch = self.unpad_image(masks_queries_logits, target_sizes, size) diff --git a/src/transformers/models/ernie4_5_vl_moe/image_processing_pil_ernie4_5_vl_moe.py b/src/transformers/models/ernie4_5_vl_moe/image_processing_pil_ernie4_5_vl_moe.py index 1bbff5d029c9..e408d5e1be26 100644 --- a/src/transformers/models/ernie4_5_vl_moe/image_processing_pil_ernie4_5_vl_moe.py +++ b/src/transformers/models/ernie4_5_vl_moe/image_processing_pil_ernie4_5_vl_moe.py @@ -25,6 +25,7 @@ from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, ImageInput, PILImageResampling, SizeDict from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, logging +from ...utils.import_utils import requires from .image_processing_ernie4_5_vl_moe import Ernie4_5_VLMoeImageProcessorKwargs, smart_resize @@ -37,6 +38,7 @@ logger = logging.get_logger(__name__) +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Ernie4_5_VLMoeImageProcessorPil(PilBackend): do_resize = True diff --git a/src/transformers/models/flava/image_processing_pil_flava.py b/src/transformers/models/flava/image_processing_pil_flava.py index fb8ceb54d39d..1f55fa338e7e 100644 --- a/src/transformers/models/flava/image_processing_pil_flava.py +++ b/src/transformers/models/flava/image_processing_pil_flava.py @@ -31,13 +31,8 @@ from ...utils import ( TensorType, auto_docstring, - is_torchvision_available, ) - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils.import_utils import requires from .image_processing_flava import ( FLAVA_CODEBOOK_MEAN, FLAVA_CODEBOOK_STD, @@ -49,6 +44,7 @@ ) +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class FlavaImageProcessorPil(PilBackend): valid_kwargs = FlavaImageProcessorKwargs @@ -138,7 +134,7 @@ def _standardize_kwargs( codebook_crop_size: int | Iterable[int] | dict[str, int] | SizeDict | None = None, codebook_image_mean: float | list[float] | None = None, codebook_image_std: float | list[float] | None = None, - codebook_resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + codebook_resample: "PILImageResampling | int | None" = None, data_format: ChannelDimension | None = None, **kwargs, ) -> dict: @@ -178,7 +174,7 @@ def _preprocess_image( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, @@ -211,7 +207,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, @@ -231,7 +227,7 @@ def _preprocess( return_codebook_pixels: bool | None, codebook_do_resize: bool | None, codebook_size: SizeDict | None, - codebook_resample: "PILImageResampling | tvF.InterpolationMode | int | None", + codebook_resample: "PILImageResampling | int | None", codebook_do_center_crop: bool | None, codebook_crop_size: SizeDict | None, codebook_do_rescale: bool | None, diff --git a/src/transformers/models/fuyu/image_processing_pil_fuyu.py b/src/transformers/models/fuyu/image_processing_pil_fuyu.py index 3fcbe97d2ddb..4992f4073dfb 100644 --- a/src/transformers/models/fuyu/image_processing_pil_fuyu.py +++ b/src/transformers/models/fuyu/image_processing_pil_fuyu.py @@ -16,34 +16,20 @@ import math import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import get_size_dict -from ...image_utils import ( - ImageInput, - PILImageResampling, - SizeDict, - get_image_size, -) +from ...image_utils import ImageInput, PILImageResampling, SizeDict, get_image_size from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - requires_backends, -) +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires from .image_processing_fuyu import FuyuBatchFeature, FuyuImagesKwargs, make_list_of_list_of_images -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class FuyuImageProcessorPil(PilBackend): do_resize = True size = {"height": 1080, "width": 1920} @@ -69,11 +55,7 @@ class FuyuImageProcessorPil(PilBackend): def __init__(self, **kwargs: Unpack[FuyuImagesKwargs]): super().__init__(**kwargs) - def _prepare_images_structure( - self, - images: ImageInput, - expected_ndims: int = 3, - ) -> ImageInput: + def _prepare_images_structure(self, images: ImageInput, expected_ndims: int = 3) -> ImageInput: images = self.fetch_images(images) return make_list_of_list_of_images(images) @@ -428,11 +410,7 @@ def preprocess_with_tokenizer_info( } ) - def _standardize_kwargs( - self, - patch_size: dict[str, int] | SizeDict | None = None, - **kwargs, - ) -> dict: + def _standardize_kwargs(self, patch_size: dict[str, int] | SizeDict | None = None, **kwargs) -> dict: """ Process Fuyu-specific kwargs before validation. """ diff --git a/src/transformers/models/gemma3/image_processing_pil_gemma3.py b/src/transformers/models/gemma3/image_processing_pil_gemma3.py index fdd4315bedf3..54414cf12736 100644 --- a/src/transformers/models/gemma3/image_processing_pil_gemma3.py +++ b/src/transformers/models/gemma3/image_processing_pil_gemma3.py @@ -32,16 +32,12 @@ from ...utils import ( TensorType, auto_docstring, - is_torchvision_available, ) - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils.import_utils import requires from .image_processing_gemma3 import Gemma3ImageProcessorKwargs +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Gemma3ImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -162,7 +158,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/glm46v/image_processing_pil_glm46v.py b/src/transformers/models/glm46v/image_processing_pil_glm46v.py index 6242f1ba4e17..08ffe8abbfd2 100644 --- a/src/transformers/models/glm46v/image_processing_pil_glm46v.py +++ b/src/transformers/models/glm46v/image_processing_pil_glm46v.py @@ -25,14 +25,12 @@ from ...image_processing_utils import BatchFeature from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, ImageInput, PILImageResampling, SizeDict from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_glm46v import Glm46VImageProcessorKwargs, smart_resize -if is_torchvision_available(): - import torchvision.transforms.v2.functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Glm46VImageProcessorPil(PilBackend): do_resize = True @@ -78,7 +76,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/glm4v/image_processing_pil_glm4v.py b/src/transformers/models/glm4v/image_processing_pil_glm4v.py index 0d663c46353c..327a64c43746 100644 --- a/src/transformers/models/glm4v/image_processing_pil_glm4v.py +++ b/src/transformers/models/glm4v/image_processing_pil_glm4v.py @@ -25,14 +25,11 @@ SizeDict, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available, logging +from ...utils import TensorType, auto_docstring, logging +from ...utils.import_utils import requires from .image_processing_glm4v import smart_resize -if is_torchvision_available(): - import torchvision.transforms.v2.functional as tvF - - logger = logging.get_logger(__name__) @@ -51,6 +48,7 @@ class Glm4vImageProcessorKwargs(ImagesKwargs, total=False): merge_size: int +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Glm4vImageProcessorPil(PilBackend): do_resize = True @@ -96,7 +94,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/glm_image/image_processing_pil_glm_image.py b/src/transformers/models/glm_image/image_processing_pil_glm_image.py index 37edb41a94b6..68caf452a7a2 100644 --- a/src/transformers/models/glm_image/image_processing_pil_glm_image.py +++ b/src/transformers/models/glm_image/image_processing_pil_glm_image.py @@ -26,14 +26,12 @@ from ...image_processing_backends import PilBackend from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, ImageInput, PILImageResampling, SizeDict from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_glm_image import GlmImageImageProcessorKwargs, smart_resize -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class GlmImageImageProcessorPil(PilBackend): do_resize = True @@ -96,7 +94,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/glpn/image_processing_pil_glpn.py b/src/transformers/models/glpn/image_processing_pil_glpn.py index 104d46bc1e7e..a98af6587ac9 100644 --- a/src/transformers/models/glpn/image_processing_pil_glpn.py +++ b/src/transformers/models/glpn/image_processing_pil_glpn.py @@ -16,34 +16,18 @@ from typing import TYPE_CHECKING import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature -from ...image_utils import ( - ImageInput, - PILImageResampling, - SizeDict, -) +from ...image_utils import ImageInput, PILImageResampling, SizeDict from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - logging, - requires_backends, -) +from ...utils import TensorType, auto_docstring, logging, requires_backends +from ...utils.import_utils import requires from .image_processing_glpn import GLPNImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - -if is_torch_available(): - import torch - - if TYPE_CHECKING: from ...modeling_outputs import DepthEstimatorOutput @@ -51,6 +35,7 @@ @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class GLPNImageProcessorPil(PilBackend): """PIL backend for GLPN with size_divisor resize.""" @@ -120,9 +105,7 @@ def _preprocess( return BatchFeature(data={"pixel_values": processed_images}, tensor_type=return_tensors) def post_process_depth_estimation( - self, - outputs: "DepthEstimatorOutput", - target_sizes: TensorType | list[tuple[int, int]] | None = None, + self, outputs: "DepthEstimatorOutput", target_sizes: TensorType | list[tuple[int, int]] | None = None ) -> list[dict[str, TensorType]]: """ Convert raw model outputs to final depth predictions. diff --git a/src/transformers/models/got_ocr2/image_processing_pil_got_ocr2.py b/src/transformers/models/got_ocr2/image_processing_pil_got_ocr2.py index 0be901ec3ea8..2ffb5e199feb 100644 --- a/src/transformers/models/got_ocr2/image_processing_pil_got_ocr2.py +++ b/src/transformers/models/got_ocr2/image_processing_pil_got_ocr2.py @@ -31,15 +31,12 @@ from ...utils import ( TensorType, auto_docstring, - is_torchvision_available, ) +from ...utils.import_utils import requires from .image_processing_got_ocr2 import GotOcr2ImageProcessorKwargs, get_optimal_tiled_canvas -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class GotOcr2ImageProcessorPil(PilBackend): valid_kwargs = GotOcr2ImageProcessorKwargs @@ -65,7 +62,7 @@ def crop_image_to_patches( max_patches: int, use_thumbnail: bool = True, patch_size: SizeDict | None = None, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, ): """ Crop the image to patches and return a list of cropped images. @@ -84,7 +81,7 @@ def crop_image_to_patches( Whether to add a thumbnail image to the list of cropped patches. patch_size (`SizeDict`, *optional*): The size of the output patches. - resample (`PILImageResampling | tvF.InterpolationMode | int | None`, *optional*): + resample (`PILImageResampling | int | None`, *optional*): Resampling filter to use when resizing. """ # Ensure image is in CHW format for processing @@ -134,7 +131,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/grounding_dino/image_processing_pil_grounding_dino.py b/src/transformers/models/grounding_dino/image_processing_pil_grounding_dino.py index 515d7c8af97b..86133985b67b 100644 --- a/src/transformers/models/grounding_dino/image_processing_pil_grounding_dino.py +++ b/src/transformers/models/grounding_dino/image_processing_pil_grounding_dino.py @@ -61,6 +61,7 @@ is_vision_available, requires_backends, ) +from ...utils.import_utils import requires from .image_processing_grounding_dino import GroundingDinoImageProcessorKwargs @@ -289,6 +290,7 @@ def _scale_boxes(boxes, target_sizes): return boxes +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class GroundingDinoImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -703,6 +705,7 @@ def _preprocess( ] return encoded_inputs + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs: "GroundingDinoObjectDetectionOutput", diff --git a/src/transformers/models/grounding_dino/modular_grounding_dino.py b/src/transformers/models/grounding_dino/modular_grounding_dino.py index 0c16061243f1..d8ae692b0890 100644 --- a/src/transformers/models/grounding_dino/modular_grounding_dino.py +++ b/src/transformers/models/grounding_dino/modular_grounding_dino.py @@ -30,6 +30,7 @@ logging, requires_backends, ) +from ...utils.import_utils import requires if TYPE_CHECKING: @@ -132,6 +133,7 @@ def post_process_panoptic_segmentation(self): class GroundingDinoImageProcessorPil(DetrImageProcessorPil): + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs: "GroundingDinoObjectDetectionOutput", diff --git a/src/transformers/models/idefics/image_processing_pil_idefics.py b/src/transformers/models/idefics/image_processing_pil_idefics.py index 57905fd6d7d4..9d4cf14f85c0 100644 --- a/src/transformers/models/idefics/image_processing_pil_idefics.py +++ b/src/transformers/models/idefics/image_processing_pil_idefics.py @@ -17,9 +17,11 @@ from ...image_utils import ImageInput, PILImageResampling, make_flat_list_of_images from ...processing_utils import Unpack from ...utils import auto_docstring, is_torch_available +from ...utils.import_utils import requires from .image_processing_idefics import IDEFICS_STANDARD_MEAN, IDEFICS_STANDARD_STD, IdeficsImageProcessorKwargs +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class IdeficsImageProcessorPil(PilBackend): valid_kwargs = IdeficsImageProcessorKwargs diff --git a/src/transformers/models/idefics2/image_processing_pil_idefics2.py b/src/transformers/models/idefics2/image_processing_pil_idefics2.py index a2374e10ec5b..c04bd45cebce 100644 --- a/src/transformers/models/idefics2/image_processing_pil_idefics2.py +++ b/src/transformers/models/idefics2/image_processing_pil_idefics2.py @@ -27,7 +27,8 @@ make_nested_list_of_images, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_idefics2 import ( Idefics2ImageProcessorKwargs, convert_to_rgb, @@ -44,10 +45,7 @@ def _make_pixel_mask(image: np.ndarray, output_size: tuple[int, int]) -> np.ndar return mask -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Idefics2ImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -147,7 +145,7 @@ def _preprocess( images: list[list[np.ndarray]], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/idefics3/image_processing_pil_idefics3.py b/src/transformers/models/idefics3/image_processing_pil_idefics3.py index 50ec3b9a35b1..2fdb99e39e2f 100644 --- a/src/transformers/models/idefics3/image_processing_pil_idefics3.py +++ b/src/transformers/models/idefics3/image_processing_pil_idefics3.py @@ -29,7 +29,8 @@ make_nested_list_of_images, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_idefics3 import ( MAX_IMAGE_SIZE, Idefics3ImageProcessorKwargs, @@ -49,10 +50,7 @@ def _make_pixel_mask(image: np.ndarray, output_size: tuple[int, int]) -> np.ndar return mask -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Idefics3ImageProcessorPil(PilBackend): resample = PILImageResampling.LANCZOS @@ -189,7 +187,7 @@ def _preprocess( images: list[list[np.ndarray]], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/imagegpt/image_processing_pil_imagegpt.py b/src/transformers/models/imagegpt/image_processing_pil_imagegpt.py index 7b3b0adf24ff..772d1ba5d5cb 100644 --- a/src/transformers/models/imagegpt/image_processing_pil_imagegpt.py +++ b/src/transformers/models/imagegpt/image_processing_pil_imagegpt.py @@ -26,16 +26,13 @@ TensorType, auto_docstring, is_torch_available, - is_torchvision_available, ) +from ...utils.import_utils import requires if is_torch_available(): import torch -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - from .image_processing_imagegpt import ImageGPTImageProcessorKwargs @@ -54,6 +51,7 @@ def color_quantize(x, clusters): return np.argmin(d, axis=1) +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class ImageGPTImageProcessorPil(PilBackend): model_input_names = ["input_ids"] @@ -87,7 +85,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/janus/image_processing_pil_janus.py b/src/transformers/models/janus/image_processing_pil_janus.py index 5a67fb7e34c0..01bcb298f8bb 100644 --- a/src/transformers/models/janus/image_processing_pil_janus.py +++ b/src/transformers/models/janus/image_processing_pil_janus.py @@ -16,6 +16,7 @@ from collections.abc import Iterable import numpy as np +import PIL from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -36,15 +37,12 @@ from ...utils import ( TensorType, auto_docstring, - is_vision_available, ) +from ...utils.import_utils import requires from .image_processing_janus import JanusImageProcessorKwargs -if is_vision_available(): - import PIL - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class JanusImageProcessorPil(PilBackend): resample = PILImageResampling.BICUBIC diff --git a/src/transformers/models/kosmos2_5/image_processing_pil_kosmos2_5.py b/src/transformers/models/kosmos2_5/image_processing_pil_kosmos2_5.py index c3456b35a128..c47a0bc724a0 100644 --- a/src/transformers/models/kosmos2_5/image_processing_pil_kosmos2_5.py +++ b/src/transformers/models/kosmos2_5/image_processing_pil_kosmos2_5.py @@ -23,10 +23,12 @@ from ...image_utils import ChannelDimension, ImageInput, SizeDict, get_image_size from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires from .image_processing_kosmos2_5 import Kosmos2_5ImageProcessorKwargs, torch_extract_patches @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class Kosmos2_5ImageProcessorPil(PilBackend): do_normalize = True do_convert_rgb = True @@ -42,11 +44,7 @@ def __init__(self, **kwargs: Unpack[Kosmos2_5ImageProcessorKwargs]): def preprocess(self, images: ImageInput, **kwargs: Unpack[Kosmos2_5ImageProcessorKwargs]) -> BatchFeature: return super().preprocess(images, **kwargs) - def normalize( - self, - image: np.ndarray, - **kwargs, - ) -> np.ndarray: + def normalize(self, image: np.ndarray, **kwargs) -> np.ndarray: """ Normalize an image using per-image mean and standard deviation. @@ -68,10 +66,7 @@ def normalize( return (image - mean) / adjusted_stddev def extract_flattened_patches( - self, - image: np.ndarray, - max_patches: int, - patch_size: SizeDict, + self, image: np.ndarray, max_patches: int, patch_size: SizeDict ) -> tuple[np.ndarray, int, int, int, int]: """ Extract flattened patches from an image. Uses torch for patch extraction. @@ -108,11 +103,7 @@ def extract_flattened_patches( resized_width = max(num_feasible_cols * patch_width, 1) image_tensor = torch.nn.functional.interpolate( - image_tensor, - size=(resized_height, resized_width), - mode="bilinear", - align_corners=False, - antialias=True, + image_tensor, size=(resized_height, resized_width), mode="bilinear", align_corners=False, antialias=True ) # [1, rows, columns, patch_height * patch_width * image_channels] @@ -179,9 +170,7 @@ def _preprocess( image = self.normalize(image, **kwargs) patches, resized_width, resized_height, n_rows, n_columns = self.extract_flattened_patches( - image=image, - max_patches=max_patches, - patch_size=patch_size, + image=image, max_patches=max_patches, patch_size=patch_size ) flattened_patches.append(patches) width.append(resized_width) @@ -211,11 +200,7 @@ def _validate_preprocess_kwargs(self, **kwargs): """ pass - def _standardize_kwargs( - self, - patch_size: dict[str, int] | SizeDict | None = None, - **kwargs, - ) -> dict: + def _standardize_kwargs(self, patch_size: dict[str, int] | SizeDict | None = None, **kwargs) -> dict: """ Process Kosmos2_5-specific kwargs before validation. """ diff --git a/src/transformers/models/layoutlmv2/image_processing_pil_layoutlmv2.py b/src/transformers/models/layoutlmv2/image_processing_pil_layoutlmv2.py index d403bd9fc6eb..78a77eae63b2 100644 --- a/src/transformers/models/layoutlmv2/image_processing_pil_layoutlmv2.py +++ b/src/transformers/models/layoutlmv2/image_processing_pil_layoutlmv2.py @@ -25,14 +25,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available, requires_backends +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires from .image_processing_layoutlmv2 import LayoutLMv2ImageProcessorKwargs, apply_tesseract -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class LayoutLMv2ImageProcessorPil(PilBackend): valid_kwargs = LayoutLMv2ImageProcessorKwargs @@ -56,7 +54,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", return_tensors: str | TensorType | None, apply_ocr: bool = True, ocr_lang: str | None = None, diff --git a/src/transformers/models/layoutlmv3/image_processing_pil_layoutlmv3.py b/src/transformers/models/layoutlmv3/image_processing_pil_layoutlmv3.py index 3fc3a3c8e149..d03d62c722de 100644 --- a/src/transformers/models/layoutlmv3/image_processing_pil_layoutlmv3.py +++ b/src/transformers/models/layoutlmv3/image_processing_pil_layoutlmv3.py @@ -26,14 +26,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available, requires_backends +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires from .image_processing_layoutlmv3 import LayoutLMv3ImageProcessorKwargs, apply_tesseract -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class LayoutLMv3ImageProcessorPil(PilBackend): valid_kwargs = LayoutLMv3ImageProcessorKwargs @@ -60,7 +58,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/levit/image_processing_pil_levit.py b/src/transformers/models/levit/image_processing_pil_levit.py index 09a310202919..d793d805ed47 100644 --- a/src/transformers/models/levit/image_processing_pil_levit.py +++ b/src/transformers/models/levit/image_processing_pil_levit.py @@ -25,11 +25,7 @@ SizeDict, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF +from ...utils import auto_docstring @auto_docstring @@ -55,7 +51,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, **kwargs, ) -> np.ndarray: """Resize: shortest_edge is rescaled to int((256/224) * shortest_edge).""" diff --git a/src/transformers/models/lightglue/image_processing_lightglue.py b/src/transformers/models/lightglue/image_processing_lightglue.py index 1b8782366671..d55a0717ebdd 100644 --- a/src/transformers/models/lightglue/image_processing_lightglue.py +++ b/src/transformers/models/lightglue/image_processing_lightglue.py @@ -20,6 +20,7 @@ from typing import TYPE_CHECKING import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import TorchvisionBackend from ...image_processing_utils import BatchFeature @@ -35,7 +36,7 @@ to_numpy_array, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available, is_vision_available +from ...utils import TensorType, auto_docstring, is_vision_available if TYPE_CHECKING: @@ -44,9 +45,6 @@ if is_vision_available(): from PIL import Image, ImageDraw -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - class LightGlueImageProcessorKwargs(ImagesKwargs, total=False): r""" diff --git a/src/transformers/models/lightglue/image_processing_pil_lightglue.py b/src/transformers/models/lightglue/image_processing_pil_lightglue.py index 84074be55ce6..66c85ba46efc 100644 --- a/src/transformers/models/lightglue/image_processing_pil_lightglue.py +++ b/src/transformers/models/lightglue/image_processing_pil_lightglue.py @@ -34,6 +34,7 @@ is_vision_available, requires_backends, ) +from ...utils.import_utils import requires from .image_processing_lightglue import LightGlueImageProcessorKwargs, validate_and_format_image_pairs @@ -49,17 +50,13 @@ from torchvision.transforms.v2 import functional as tvF -def is_grayscale( - image: np.ndarray, -): +def is_grayscale(image: np.ndarray): if image.shape[0] == 1: return True return np.all(image[0, ...] == image[1, ...]) and np.all(image[1, ...] == image[2, ...]) -def convert_to_grayscale( - image: ImageInput, -) -> ImageInput: +def convert_to_grayscale(image: ImageInput) -> ImageInput: """ Converts an image to grayscale format using the NTSC formula. Only support numpy and PIL Image. @@ -87,7 +84,7 @@ def convert_to_grayscale( return image -@auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class LightGlueImageProcessorPil(PilBackend): valid_kwargs = LightGlueImageProcessorKwargs resample = PILImageResampling.BILINEAR @@ -106,11 +103,7 @@ def __init__(self, **kwargs: Unpack[LightGlueImageProcessorKwargs]): def preprocess(self, images: ImageInput, **kwargs: Unpack[LightGlueImageProcessorKwargs]) -> BatchFeature: return super().preprocess(images, **kwargs) - def _prepare_images_structure( - self, - images: ImageInput, - **kwargs, - ) -> ImageInput: + def _prepare_images_structure(self, images: ImageInput, **kwargs) -> ImageInput: # we need to handle image pairs validation and flattening images = self.fetch_images(images) return validate_and_format_image_pairs(images) @@ -217,9 +210,7 @@ def post_process_keypoint_matching( return results def visualize_keypoint_matching( - self, - images: ImageInput, - keypoint_matching_output: list[dict[str, torch.Tensor]], + self, images: ImageInput, keypoint_matching_output: list[dict[str, torch.Tensor]] ) -> list["Image.Image"]: """ Plots the image pairs side by side with the detected keypoints as well as the matching between them. @@ -256,11 +247,7 @@ def visualize_keypoint_matching( keypoints0_x, keypoints0_y, keypoints1_x, keypoints1_y, pair_output["matching_scores"] ): color = self._get_color(matching_score) - draw.line( - (keypoint0_x, keypoint0_y, keypoint1_x + width0, keypoint1_y), - fill=color, - width=3, - ) + draw.line((keypoint0_x, keypoint0_y, keypoint1_x + width0, keypoint1_y), fill=color, width=3) draw.ellipse((keypoint0_x - 2, keypoint0_y - 2, keypoint0_x + 2, keypoint0_y + 2), fill="black") draw.ellipse( (keypoint1_x + width0 - 2, keypoint1_y - 2, keypoint1_x + width0 + 2, keypoint1_y + 2), diff --git a/src/transformers/models/lightglue/modular_lightglue.py b/src/transformers/models/lightglue/modular_lightglue.py index f5780779188e..71255c8d3dd0 100644 --- a/src/transformers/models/lightglue/modular_lightglue.py +++ b/src/transformers/models/lightglue/modular_lightglue.py @@ -25,6 +25,7 @@ from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel from ...processing_utils import Unpack from ...utils import ModelOutput, TensorType, auto_docstring, can_return_tuple, logging, requires_backends +from ...utils.import_utils import requires from ..auto import CONFIG_MAPPING, AutoConfig from ..auto.modeling_auto import AutoModelForKeypointDetection from ..clip.modeling_clip import CLIPMLP @@ -178,6 +179,7 @@ def post_process_keypoint_matching( return super().post_process_keypoint_matching(outputs, target_sizes, threshold) +@requires(backends=("vision", "torch", "torchvision")) class LightGlueImageProcessorPil(SuperGlueImageProcessorPil): def post_process_keypoint_matching( self, diff --git a/src/transformers/models/llava/image_processing_pil_llava.py b/src/transformers/models/llava/image_processing_pil_llava.py index b4ffc3d3129c..3dccb4f3ac03 100644 --- a/src/transformers/models/llava/image_processing_pil_llava.py +++ b/src/transformers/models/llava/image_processing_pil_llava.py @@ -13,8 +13,6 @@ # limitations under the License. """Image processor class for LLaVa.""" -from typing import Union - import numpy as np from ...image_processing_backends import PilBackend @@ -26,11 +24,7 @@ SizeDict, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF +from ...utils import TensorType, auto_docstring @auto_docstring @@ -101,7 +95,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: Union["PILImageResampling", "tvF.InterpolationMode", int] | None, + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/llava_next/image_processing_pil_llava_next.py b/src/transformers/models/llava_next/image_processing_pil_llava_next.py index a1681ef0ef8c..5c520095bd6e 100644 --- a/src/transformers/models/llava_next/image_processing_pil_llava_next.py +++ b/src/transformers/models/llava_next/image_processing_pil_llava_next.py @@ -31,14 +31,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_llava_next import LlavaNextImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class LlavaNextImageProcessorPil(PilBackend): model_input_names = ["pixel_values", "image_sizes"] @@ -158,7 +156,7 @@ def _preprocess( do_resize: bool, size: SizeDict, image_grid_pinpoints: list[list[int]], - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/llava_onevision/image_processing_llava_onevision.py b/src/transformers/models/llava_onevision/image_processing_llava_onevision.py index 1164d218d748..8d745802fc00 100644 --- a/src/transformers/models/llava_onevision/image_processing_llava_onevision.py +++ b/src/transformers/models/llava_onevision/image_processing_llava_onevision.py @@ -172,7 +172,7 @@ def _preprocess( do_resize: bool, size: SizeDict, image_grid_pinpoints: list[list[int]], - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/llava_onevision/image_processing_pil_llava_onevision.py b/src/transformers/models/llava_onevision/image_processing_pil_llava_onevision.py index b83fd56f5ddc..c8e3fccd2eb4 100644 --- a/src/transformers/models/llava_onevision/image_processing_pil_llava_onevision.py +++ b/src/transformers/models/llava_onevision/image_processing_pil_llava_onevision.py @@ -33,14 +33,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_llava_onevision import LlavaOnevisionImageProcessorKwargs -if is_torchvision_available(): - import torchvision.transforms.v2.functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class LlavaOnevisionImageProcessorPil(PilBackend): model_input_names = ["pixel_values", "image_sizes", "batch_num_images"] @@ -167,7 +165,7 @@ def _preprocess( do_resize: bool, size: SizeDict, image_grid_pinpoints: list[list[int]], - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/llava_onevision/modular_llava_onevision.py b/src/transformers/models/llava_onevision/modular_llava_onevision.py index 671365facc06..602de8a4aaf4 100644 --- a/src/transformers/models/llava_onevision/modular_llava_onevision.py +++ b/src/transformers/models/llava_onevision/modular_llava_onevision.py @@ -137,7 +137,7 @@ def _preprocess( do_resize: bool, size: SizeDict, image_grid_pinpoints: list[list[int]], - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, @@ -298,7 +298,7 @@ def _preprocess( do_resize: bool, size: SizeDict, image_grid_pinpoints: list[list[int]], - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/mask2former/image_processing_pil_mask2former.py b/src/transformers/models/mask2former/image_processing_pil_mask2former.py index 5907b5b85433..ad926a52309f 100644 --- a/src/transformers/models/mask2former/image_processing_pil_mask2former.py +++ b/src/transformers/models/mask2former/image_processing_pil_mask2former.py @@ -48,6 +48,7 @@ logging, requires_backends, ) +from ...utils.import_utils import requires from .image_processing_mask2former import ( Mask2FormerImageProcessorKwargs, compute_segments, @@ -102,7 +103,7 @@ def convert_segmentation_map_to_binary_masks( return binary_masks.astype(np.float32), labels -@auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class Mask2FormerImageProcessorPil(PilBackend): valid_kwargs = Mask2FormerImageProcessorKwargs resample = PILImageResampling.BILINEAR @@ -178,11 +179,7 @@ def resize( if size.shortest_edge and size.longest_edge: # Get current image size height, width = get_image_size(image, channel_dim=ChannelDimension.FIRST) - new_size = get_size_with_aspect_ratio( - (height, width), - size.shortest_edge, - size.longest_edge, - ) + new_size = get_size_with_aspect_ratio((height, width), size.shortest_edge, size.longest_edge) elif size.max_height and size.max_width: height, width = get_image_size(image, channel_dim=ChannelDimension.FIRST) new_size = get_image_size_for_max_height_width((height, width), size.max_height, size.max_width) @@ -357,10 +354,7 @@ def _preprocess( seg_map = segmentation_maps[idx] if do_resize: seg_map = self.resize( - image=seg_map, - size=size, - size_divisor=size_divisor, - resample=PILImageResampling.NEAREST, + image=seg_map, size=size, size_divisor=size_divisor, resample=PILImageResampling.NEAREST ) resized_segmentation_maps.append(seg_map) @@ -385,10 +379,7 @@ def _preprocess( if segmentation_map.ndim == 3 and segmentation_map.shape[0] == 1: segmentation_map = segmentation_map.squeeze(0) masks, classes = convert_segmentation_map_to_binary_masks( - segmentation_map, - instance_id, - ignore_index=ignore_index, - do_reduce_labels=do_reduce_labels, + segmentation_map, instance_id, ignore_index=ignore_index, do_reduce_labels=do_reduce_labels ) mask_labels.append(masks) class_labels.append(classes) @@ -412,8 +403,7 @@ def _preprocess( ) encoded_inputs = BatchFeature( - data={"pixel_values": padded_images, "pixel_mask": pixel_masks}, - tensor_type=return_tensors, + data={"pixel_values": padded_images, "pixel_mask": pixel_masks}, tensor_type=return_tensors ) # we cannot batch them since they don't share a common class size if segmentation_maps is not None: diff --git a/src/transformers/models/mask2former/modular_mask2former.py b/src/transformers/models/mask2former/modular_mask2former.py index 90c82313886e..9fb3c0639554 100644 --- a/src/transformers/models/mask2former/modular_mask2former.py +++ b/src/transformers/models/mask2former/modular_mask2former.py @@ -20,6 +20,7 @@ logging, requires_backends, ) +from ...utils.import_utils import requires from ..maskformer.image_processing_maskformer import MaskFormerImageProcessor from ..maskformer.image_processing_pil_maskformer import MaskFormerImageProcessorPil from .image_processing_mask2former import ( @@ -305,6 +306,7 @@ def post_process_panoptic_segmentation( return results +@requires(backends=("vision", "torch", "torchvision")) class Mask2FormerImageProcessorPil(MaskFormerImageProcessorPil): def post_process_semantic_segmentation( self, outputs, target_sizes: list[tuple[int, int]] | None = None diff --git a/src/transformers/models/maskformer/image_processing_pil_maskformer.py b/src/transformers/models/maskformer/image_processing_pil_maskformer.py index 37de4dae5960..5ef4fc1d1f1c 100644 --- a/src/transformers/models/maskformer/image_processing_pil_maskformer.py +++ b/src/transformers/models/maskformer/image_processing_pil_maskformer.py @@ -17,6 +17,9 @@ from typing import Any import numpy as np +import torch +from torch import nn +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature, get_size_dict @@ -34,23 +37,8 @@ get_max_height_width, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - logging, - requires_backends, -) - - -if is_torch_available(): - import torch - from torch import nn - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils import TensorType, auto_docstring, logging, requires_backends +from ...utils.import_utils import requires from .image_processing_maskformer import ( MaskFormerImageProcessorKwargs, compute_segments, @@ -99,6 +87,7 @@ def convert_segmentation_map_to_binary_masks( @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class MaskFormerImageProcessorPil(PilBackend): valid_kwargs = MaskFormerImageProcessorKwargs resample = PILImageResampling.BILINEAR @@ -174,11 +163,7 @@ def resize( if size.shortest_edge and size.longest_edge: # Get current image size height, width = get_image_size(image, channel_dim=ChannelDimension.FIRST) - new_size = get_size_with_aspect_ratio( - (height, width), - size.shortest_edge, - size.longest_edge, - ) + new_size = get_size_with_aspect_ratio((height, width), size.shortest_edge, size.longest_edge) elif size.max_height and size.max_width: height, width = get_image_size(image, channel_dim=ChannelDimension.FIRST) new_size = get_image_size_for_max_height_width((height, width), size.max_height, size.max_width) @@ -353,10 +338,7 @@ def _preprocess( seg_map = segmentation_maps[idx] if do_resize: seg_map = self.resize( - image=seg_map, - size=size, - size_divisor=size_divisor, - resample=PILImageResampling.NEAREST, + image=seg_map, size=size, size_divisor=size_divisor, resample=PILImageResampling.NEAREST ) resized_segmentation_maps.append(seg_map) @@ -381,10 +363,7 @@ def _preprocess( if segmentation_map.ndim == 3 and segmentation_map.shape[0] == 1: segmentation_map = segmentation_map.squeeze(0) masks, classes = convert_segmentation_map_to_binary_masks( - segmentation_map, - instance_id, - ignore_index=ignore_index, - do_reduce_labels=do_reduce_labels, + segmentation_map, instance_id, ignore_index=ignore_index, do_reduce_labels=do_reduce_labels ) mask_labels.append(masks) class_labels.append(classes) @@ -408,8 +387,7 @@ def _preprocess( ) encoded_inputs = BatchFeature( - data={"pixel_values": padded_images, "pixel_mask": pixel_masks}, - tensor_type=return_tensors, + data={"pixel_values": padded_images, "pixel_mask": pixel_masks}, tensor_type=return_tensors ) # we cannot batch them since they don't share a common class size if segmentation_maps is not None: diff --git a/src/transformers/models/mllama/image_processing_pil_mllama.py b/src/transformers/models/mllama/image_processing_pil_mllama.py index 3697a2632415..a7ae5ce21a9a 100644 --- a/src/transformers/models/mllama/image_processing_pil_mllama.py +++ b/src/transformers/models/mllama/image_processing_pil_mllama.py @@ -30,6 +30,7 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_mllama import ( MllamaImageProcessorKwargs, _validate_mllama_preprocess_arguments, @@ -167,6 +168,7 @@ def convert_aspect_ratios_to_ids_np(aspect_ratios: list[list[tuple[int, int]]], return aspect_ratios_ids +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class MllamaImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR diff --git a/src/transformers/models/mobilenet_v2/image_processing_pil_mobilenet_v2.py b/src/transformers/models/mobilenet_v2/image_processing_pil_mobilenet_v2.py index 12450dc884eb..48d87af8a807 100644 --- a/src/transformers/models/mobilenet_v2/image_processing_pil_mobilenet_v2.py +++ b/src/transformers/models/mobilenet_v2/image_processing_pil_mobilenet_v2.py @@ -16,6 +16,8 @@ from typing import Union import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -28,18 +30,13 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available +from ...utils import TensorType, auto_docstring, is_torch_available +from ...utils.import_utils import requires from .image_processing_mobilenet_v2 import MobileNetV2ImageProcessorKwargs -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class MobileNetV2ImageProcessorPil(PilBackend): """PIL backend for MobileNetV2 with reduce_label support.""" diff --git a/src/transformers/models/mobilevit/image_processing_pil_mobilevit.py b/src/transformers/models/mobilevit/image_processing_pil_mobilevit.py index dd059127341b..714800919eca 100644 --- a/src/transformers/models/mobilevit/image_processing_pil_mobilevit.py +++ b/src/transformers/models/mobilevit/image_processing_pil_mobilevit.py @@ -16,6 +16,8 @@ from typing import Union import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -29,27 +31,16 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - logging, - requires_backends, -) +from ...utils import TensorType, auto_docstring, logging, requires_backends +from ...utils.import_utils import requires from .image_processing_mobilevit import MobileVitImageProcessorKwargs -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - logger = logging.get_logger(__name__) @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class MobileViTImageProcessorPil(PilBackend): """PIL backend for MobileViT with flip_channel_order and reduce_label support.""" diff --git a/src/transformers/models/nougat/image_processing_pil_nougat.py b/src/transformers/models/nougat/image_processing_pil_nougat.py index 3c9abd18d04d..5214dcd7a3e3 100644 --- a/src/transformers/models/nougat/image_processing_pil_nougat.py +++ b/src/transformers/models/nougat/image_processing_pil_nougat.py @@ -36,16 +36,12 @@ from ...utils import ( TensorType, auto_docstring, - is_torchvision_available, ) - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils.import_utils import requires from .image_processing_nougat import NougatImageProcessorKwargs +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class NougatImageProcessorPil(PilBackend): valid_kwargs = NougatImageProcessorKwargs @@ -211,7 +207,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, reducing_gap: int | None = None, **kwargs, ) -> np.ndarray: @@ -223,7 +219,7 @@ def resize( Image to resize. size (`SizeDict`): Size of the output image. - resample (`PILImageResampling | tvF.InterpolationMode | int`, *optional*): + resample (`PILImageResampling | int`, *optional*): Resampling filter to use when resizing the image. Returns: `np.ndarray`: The resized image. @@ -247,7 +243,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/oneformer/image_processing_pil_oneformer.py b/src/transformers/models/oneformer/image_processing_pil_oneformer.py index e9c8f3d262b5..2a14eb51bea8 100644 --- a/src/transformers/models/oneformer/image_processing_pil_oneformer.py +++ b/src/transformers/models/oneformer/image_processing_pil_oneformer.py @@ -14,6 +14,9 @@ """Image processor class for OneFormer.""" import numpy as np +import torch +from torch import nn +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -30,22 +33,8 @@ get_max_height_width, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - logging, -) - - -if is_torch_available(): - import torch - from torch import nn - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils import TensorType, auto_docstring, logging +from ...utils.import_utils import requires from .image_processing_oneformer import ( OneFormerImageProcessorKwargs, compute_segments, @@ -78,6 +67,7 @@ def make_pixel_mask(image: np.ndarray, output_size: tuple[int, int]) -> np.ndarr @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class OneFormerImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR image_mean = IMAGENET_DEFAULT_MEAN @@ -204,12 +194,7 @@ def _preprocess( return encoded_inputs - def _pad_image( - self, - image: np.ndarray, - output_size: tuple[int, int], - constant_values: float = 0, - ) -> np.ndarray: + def _pad_image(self, image: np.ndarray, output_size: tuple[int, int], constant_values: float = 0) -> np.ndarray: """ Pad an image with zeros to the given size using numpy operations. @@ -249,10 +234,7 @@ def _pad_image( return padded_image def pad( - self, - images: list[np.ndarray], - return_pixel_mask: bool = True, - return_tensors: str | TensorType | None = None, + self, images: list[np.ndarray], return_pixel_mask: bool = True, return_tensors: str | TensorType | None = None ) -> BatchFeature: """ Pad a batch of images to the same size using numpy operations. @@ -494,10 +476,7 @@ def encode_inputs( # Convert segmentation map to binary masks using numpy operations masks, classes = self.convert_segmentation_map_to_binary_masks( - segmentation_map, - instance_id, - ignore_index=ignore_index, - do_reduce_labels=do_reduce_labels, + segmentation_map, instance_id, ignore_index=ignore_index, do_reduce_labels=do_reduce_labels ) annotations.append({"masks": masks, "classes": classes}) diff --git a/src/transformers/models/ovis2/image_processing_pil_ovis2.py b/src/transformers/models/ovis2/image_processing_pil_ovis2.py index 9e3d131efdcc..5ecc453f7c6a 100644 --- a/src/transformers/models/ovis2/image_processing_pil_ovis2.py +++ b/src/transformers/models/ovis2/image_processing_pil_ovis2.py @@ -28,7 +28,8 @@ infer_channel_dimension_format, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_ovis2 import ( Ovis2ImageProcessorKwargs, get_min_tile_covering_grid, @@ -36,10 +37,7 @@ ) -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Ovis2ImageProcessorPil(PilBackend): resample = PILImageResampling.BICUBIC @@ -72,7 +70,7 @@ def crop_image_to_patches( use_covering_area_grid: bool = True, covering_threshold: float = 0.9, patch_size: SizeDict | None = None, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, ): """ Crop the image to patches and return a list of cropped images. @@ -131,7 +129,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/owlv2/image_processing_pil_owlv2.py b/src/transformers/models/owlv2/image_processing_pil_owlv2.py index f8220b8c6cbb..9fe163797f25 100644 --- a/src/transformers/models/owlv2/image_processing_pil_owlv2.py +++ b/src/transformers/models/owlv2/image_processing_pil_owlv2.py @@ -36,6 +36,7 @@ is_torchvision_available, requires_backends, ) +from ...utils.import_utils import requires from ..owlv2.image_processing_owlv2 import box_iou @@ -152,6 +153,7 @@ def _scale_boxes(boxes, target_sizes): @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class Owlv2ImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR image_mean = OPENAI_CLIP_MEAN @@ -178,6 +180,7 @@ def __init__(self, **kwargs: Unpack[ImagesKwargs]): super().__init__(**kwargs) + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs: "Owlv2ObjectDetectionOutput", @@ -232,6 +235,7 @@ def post_process_object_detection( return results + @requires(backends=("vision", "torch")) def post_process_image_guided_detection(self, outputs, threshold=0.0, nms_threshold=0.3, target_sizes=None): """ Converts the output of [`Owlv2ForObjectDetection.image_guided_detection`] into the format expected by the COCO diff --git a/src/transformers/models/owlv2/modular_owlv2.py b/src/transformers/models/owlv2/modular_owlv2.py index f57321249218..9d5d1d873ba6 100644 --- a/src/transformers/models/owlv2/modular_owlv2.py +++ b/src/transformers/models/owlv2/modular_owlv2.py @@ -37,21 +37,13 @@ TensorType, auto_docstring, is_scipy_available, - is_torch_available, - is_vision_available, requires_backends, ) +from ...utils.import_utils import requires from ..owlvit.image_processing_owlvit import OwlViTImageProcessor from ..owlvit.image_processing_pil_owlvit import OwlViTImageProcessorPil -if is_torch_available(): - import torch - - -if is_vision_available(): - pass - if is_scipy_available(): from scipy import ndimage as ndi @@ -320,6 +312,7 @@ def _preprocess( @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class Owlv2ImageProcessorPil(OwlViTImageProcessorPil): resample = PILImageResampling.BILINEAR image_mean = OPENAI_CLIP_MEAN diff --git a/src/transformers/models/owlvit/image_processing_pil_owlvit.py b/src/transformers/models/owlvit/image_processing_pil_owlvit.py index 1569de2558d2..2afdea5eb809 100644 --- a/src/transformers/models/owlvit/image_processing_pil_owlvit.py +++ b/src/transformers/models/owlvit/image_processing_pil_owlvit.py @@ -15,16 +15,17 @@ from typing import TYPE_CHECKING +import torch + from ...image_processing_backends import PilBackend from ...image_transforms import center_to_corners_format from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, PILImageResampling from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, logging, requires_backends +from ...utils import TensorType, auto_docstring, logging, requires_backends +from ...utils.import_utils import requires from ..owlvit.image_processing_owlvit import _scale_boxes, box_iou -if is_torch_available(): - import torch if TYPE_CHECKING: from .modeling_owlvit import OwlViTObjectDetectionOutput @@ -32,6 +33,7 @@ logger = logging.get_logger(__name__) +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class OwlViTImageProcessorPil(PilBackend): resample = PILImageResampling.BICUBIC @@ -57,6 +59,7 @@ def __init__(self, **kwargs: Unpack[ImagesKwargs]): super().__init__(**kwargs) + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs: "OwlViTObjectDetectionOutput", @@ -111,6 +114,7 @@ def post_process_object_detection( return results + @requires(backends=("vision", "torch")) def post_process_image_guided_detection(self, outputs, threshold=0.0, nms_threshold=0.3, target_sizes=None): """ Converts the output of [`OwlViTForObjectDetection.image_guided_detection`] into the format expected by the COCO diff --git a/src/transformers/models/paddleocr_vl/image_processing_pil_paddleocr_vl.py b/src/transformers/models/paddleocr_vl/image_processing_pil_paddleocr_vl.py index 20e0887400e1..50b403d270e6 100644 --- a/src/transformers/models/paddleocr_vl/image_processing_pil_paddleocr_vl.py +++ b/src/transformers/models/paddleocr_vl/image_processing_pil_paddleocr_vl.py @@ -32,6 +32,7 @@ from ...image_utils import OPENAI_CLIP_MEAN, OPENAI_CLIP_STD, ImageInput, PILImageResampling, SizeDict from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils.import_utils import requires from .image_processing_paddleocr_vl import PaddleOCRVLImageProcessorKwargs, smart_resize @@ -39,6 +40,7 @@ from torchvision.transforms.v2 import functional as tvF +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class PaddleOCRVLImageProcessorPil(PilBackend): do_resize = True diff --git a/src/transformers/models/perceiver/image_processing_pil_perceiver.py b/src/transformers/models/perceiver/image_processing_pil_perceiver.py index 9a87b1441d0b..0be7552b241f 100644 --- a/src/transformers/models/perceiver/image_processing_pil_perceiver.py +++ b/src/transformers/models/perceiver/image_processing_pil_perceiver.py @@ -24,11 +24,7 @@ SizeDict, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF +from ...utils import TensorType, auto_docstring @auto_docstring @@ -80,7 +76,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/pi0/modular_pi0.py b/src/transformers/models/pi0/modular_pi0.py index eb9db339ad31..f79ac3c2775a 100644 --- a/src/transformers/models/pi0/modular_pi0.py +++ b/src/transformers/models/pi0/modular_pi0.py @@ -34,6 +34,7 @@ from ...tokenization_utils_base import PreTokenizedInput, TextInput from ...utils import auto_docstring, can_return_tuple, logging from ...utils.generic import maybe_autocast +from ...utils.import_utils import requires from ..auto import CONFIG_MAPPING, AutoConfig, AutoModel from ..paligemma.processing_paligemma import PaligemmaProcessor from ..siglip.image_processing_siglip import SiglipImageProcessor @@ -61,6 +62,7 @@ class PI0ProcessorKwargs(ProcessingKwargs, total=False): @auto_docstring +@requires(backends=("vision", "torch")) class PI0Processor(PaligemmaProcessor): def __init__(self, image_processor=None, tokenizer=None, chat_template=None, **kwargs): self.height, self.width = image_processor.size["height"], image_processor.size["width"] diff --git a/src/transformers/models/pi0/processing_pi0.py b/src/transformers/models/pi0/processing_pi0.py index c33c9eec0e6e..6fe2d94ff08c 100644 --- a/src/transformers/models/pi0/processing_pi0.py +++ b/src/transformers/models/pi0/processing_pi0.py @@ -27,6 +27,7 @@ from ...processing_utils import MultiModalData, ProcessingKwargs, ProcessorMixin, Unpack from ...tokenization_utils_base import AddedToken, PreTokenizedInput, TextInput from ...utils import auto_docstring, logging +from ...utils.import_utils import requires logger = logging.get_logger(__name__) @@ -48,6 +49,7 @@ class PI0ProcessorKwargs(ProcessingKwargs, total=False): @auto_docstring +@requires(backends=("vision", "torch")) class PI0Processor(ProcessorMixin): def __init__(self, image_processor=None, tokenizer=None, chat_template=None, **kwargs): self.height, self.width = image_processor.size["height"], image_processor.size["width"] diff --git a/src/transformers/models/pix2struct/image_processing_pil_pix2struct.py b/src/transformers/models/pix2struct/image_processing_pil_pix2struct.py index e2e5ac133ff6..72fb9c9bbe7e 100644 --- a/src/transformers/models/pix2struct/image_processing_pil_pix2struct.py +++ b/src/transformers/models/pix2struct/image_processing_pil_pix2struct.py @@ -16,6 +16,7 @@ import math import numpy as np +import torch from PIL import Image from ...image_processing_backends import PilBackend @@ -23,19 +24,13 @@ from ...image_transforms import to_channel_dimension_format, to_pil_image from ...image_utils import ChannelDimension, ImageInput, SizeDict from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, requires_backends -from .image_processing_pix2struct import ( - Pix2StructImageProcessorKwargs, - render_text, - torch_extract_patches, -) - - -if is_torch_available(): - import torch +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires +from .image_processing_pix2struct import Pix2StructImageProcessorKwargs, render_text, torch_extract_patches @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class Pix2StructImageProcessorPil(PilBackend): rescale_factor = None do_normalize = True @@ -46,11 +41,7 @@ class Pix2StructImageProcessorPil(PilBackend): valid_kwargs = Pix2StructImageProcessorKwargs model_input_names = ["flattened_patches", "attention_mask"] - def _standardize_kwargs( - self, - patch_size: dict[str, int] | SizeDict | None = None, - **kwargs, - ) -> dict: + def _standardize_kwargs(self, patch_size: dict[str, int] | SizeDict | None = None, **kwargs) -> dict: """ Process custom Pix2Struct kwargs, specifically converting patch_size to SizeDict. """ @@ -71,11 +62,7 @@ def _validate_preprocess_kwargs(self, **kwargs): pass def render_header( - self, - image: np.ndarray, - header: str, - font_bytes: bytes | None = None, - font_path: str | None = None, + self, image: np.ndarray, header: str, font_bytes: bytes | None = None, font_path: str | None = None ) -> np.ndarray: """ Render header text on image using numpy arrays. @@ -138,12 +125,7 @@ def normalize(self, image: np.ndarray) -> np.ndarray: return (image - mean) / adjusted_stddev - def extract_flattened_patches( - self, - image: np.ndarray, - max_patches: int, - patch_size: SizeDict, - ) -> np.ndarray: + def extract_flattened_patches(self, image: np.ndarray, max_patches: int, patch_size: SizeDict) -> np.ndarray: """ Extract flattened patches from an image. Uses torch for patch extraction. @@ -233,9 +215,7 @@ def _preprocess_image_like_inputs( """ # Prepare images (converts to numpy arrays) images = self._prepare_image_like_inputs( - images=images, - do_convert_rgb=do_convert_rgb, - input_data_format=input_data_format, + images=images, do_convert_rgb=do_convert_rgb, input_data_format=input_data_format ) # Handle VQA mode with header rendering diff --git a/src/transformers/models/pixtral/image_processing_pil_pixtral.py b/src/transformers/models/pixtral/image_processing_pil_pixtral.py index e0872e8cf145..a0cc0cfa1364 100644 --- a/src/transformers/models/pixtral/image_processing_pil_pixtral.py +++ b/src/transformers/models/pixtral/image_processing_pil_pixtral.py @@ -26,15 +26,12 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_pixtral import PixtralImageProcessorKwargs, get_resize_output_image_size +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class PixtralImageProcessorPil(PilBackend): resample = PILImageResampling.BICUBIC @@ -63,7 +60,7 @@ def resize( image: np.ndarray, size: SizeDict, patch_size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, **kwargs, ) -> np.ndarray: """ @@ -115,7 +112,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/pixtral/processing_pixtral.py b/src/transformers/models/pixtral/processing_pixtral.py index 20dda57237f1..eef1dc674e7b 100644 --- a/src/transformers/models/pixtral/processing_pixtral.py +++ b/src/transformers/models/pixtral/processing_pixtral.py @@ -27,6 +27,7 @@ ) from ...tokenization_utils_base import PreTokenizedInput, TextInput from ...utils import auto_docstring, is_vision_available, logging +from ...utils.import_utils import requires if is_vision_available(): @@ -59,6 +60,7 @@ def is_image_or_image_url(elem): @auto_docstring +@requires(backends=("torchvision", "torch")) class PixtralProcessor(ProcessorMixin): def __init__( self, diff --git a/src/transformers/models/poolformer/image_processing_pil_poolformer.py b/src/transformers/models/poolformer/image_processing_pil_poolformer.py index 0b3155dc844a..635635306ff5 100644 --- a/src/transformers/models/poolformer/image_processing_pil_poolformer.py +++ b/src/transformers/models/poolformer/image_processing_pil_poolformer.py @@ -26,14 +26,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_poolformer import PoolFormerImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class PoolFormerImageProcessorPil(PilBackend): """PIL backend for PoolFormer with custom resize (crop_pct).""" @@ -60,7 +58,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, crop_pct: float | None = None, **kwargs, ) -> np.ndarray: @@ -92,7 +90,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/prompt_depth_anything/image_processing_pil_prompt_depth_anything.py b/src/transformers/models/prompt_depth_anything/image_processing_pil_prompt_depth_anything.py index a95e29e57c8e..522068abeba0 100644 --- a/src/transformers/models/prompt_depth_anything/image_processing_pil_prompt_depth_anything.py +++ b/src/transformers/models/prompt_depth_anything/image_processing_pil_prompt_depth_anything.py @@ -32,23 +32,15 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_torch_available, - is_torchvision_available, - requires_backends, -) +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires if TYPE_CHECKING: from ...modeling_outputs import DepthEstimatorOutput -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF +import torch +from torchvision.transforms.v2 import functional as tvF from .image_processing_prompt_depth_anything import PromptDepthAnythingImageProcessorKwargs @@ -67,10 +59,7 @@ def _constrain_to_multiple_of(val, multiple, min_val=0, max_val=None): def _get_resize_output_image_size( - input_image: np.ndarray, - output_size: tuple[int, int], - keep_aspect_ratio: bool, - multiple: int, + input_image: np.ndarray, output_size: tuple[int, int], keep_aspect_ratio: bool, multiple: int ) -> tuple[int, int]: """Get the output size for resizing an image.""" input_height, input_width = get_image_size(input_image, channel_dim=ChannelDimension.FIRST) @@ -96,6 +85,7 @@ def _get_resize_output_image_size( @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class PromptDepthAnythingImageProcessorPil(PilBackend): model_input_names = ["pixel_values", "prompt_depth"] @@ -152,17 +142,9 @@ def resize_with_aspect_ratio( ) # Standard resize method with calculated output size - return self.resize( - image=image, - size=SizeDict(height=output_size[0], width=output_size[1]), - resample=resample, - ) + return self.resize(image=image, size=SizeDict(height=output_size[0], width=output_size[1]), resample=resample) - def pad_image( - self, - image: np.ndarray, - size_divisor: int, - ) -> np.ndarray: + def pad_image(self, image: np.ndarray, size_divisor: int) -> np.ndarray: """ Center pad an image to be a multiple of size_divisor. """ @@ -295,9 +277,7 @@ def _preprocess( return processed_images def post_process_depth_estimation( - self, - outputs: "DepthEstimatorOutput", - target_sizes: TensorType | list[tuple[int, int]] | None | None = None, + self, outputs: "DepthEstimatorOutput", target_sizes: TensorType | list[tuple[int, int]] | None | None = None ) -> list[dict[str, TensorType]]: """ Converts the raw output of [`DepthEstimatorOutput`] into final depth predictions and depth PIL images. diff --git a/src/transformers/models/qwen2_vl/image_processing_pil_qwen2_vl.py b/src/transformers/models/qwen2_vl/image_processing_pil_qwen2_vl.py index f8cd4fdf3bca..e3707edf5467 100644 --- a/src/transformers/models/qwen2_vl/image_processing_pil_qwen2_vl.py +++ b/src/transformers/models/qwen2_vl/image_processing_pil_qwen2_vl.py @@ -27,14 +27,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_qwen2_vl import Qwen2VLImageProcessorKwargs, smart_resize -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Qwen2VLImageProcessorPil(PilBackend): do_resize = True @@ -97,7 +95,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/rt_detr/image_processing_pil_rt_detr.py b/src/transformers/models/rt_detr/image_processing_pil_rt_detr.py index 68b24352584f..848de988db74 100644 --- a/src/transformers/models/rt_detr/image_processing_pil_rt_detr.py +++ b/src/transformers/models/rt_detr/image_processing_pil_rt_detr.py @@ -48,6 +48,7 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, requires_backends +from ...utils.import_utils import requires from .image_processing_rt_detr import RTDetrImageProcessorKwargs @@ -114,7 +115,7 @@ def prepare_coco_detection_annotation_pil( return new_target -@auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class RTDetrImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR image_mean = IMAGENET_DEFAULT_MEAN @@ -492,6 +493,7 @@ def _preprocess( ] return encoded_inputs + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, diff --git a/src/transformers/models/rt_detr/modular_rt_detr.py b/src/transformers/models/rt_detr/modular_rt_detr.py index 150063bc1481..a299925a348d 100644 --- a/src/transformers/models/rt_detr/modular_rt_detr.py +++ b/src/transformers/models/rt_detr/modular_rt_detr.py @@ -52,6 +52,7 @@ torch_int, ) from ...utils.generic import can_return_tuple, merge_with_config_defaults +from ...utils.import_utils import requires from ...utils.output_capturing import capture_outputs from ..conditional_detr.modeling_conditional_detr import inverse_sigmoid from ..deformable_detr.modeling_deformable_detr import DeformableDetrMultiscaleDeformableAttention @@ -426,6 +427,7 @@ def post_process_panoptic_segmentation(self): raise NotImplementedError("Panoptic segmentation post-processing is not implemented for RT-DETR yet.") +@requires(backends=("vision", "torch", "torchvision")) class RTDetrImageProcessorPil(DetrImageProcessorPil): resample = PILImageResampling.BILINEAR image_mean = IMAGENET_DEFAULT_MEAN diff --git a/src/transformers/models/sam/image_processing_pil_sam.py b/src/transformers/models/sam/image_processing_pil_sam.py index 3f1d9a668cb5..ffc745e02ac3 100644 --- a/src/transformers/models/sam/image_processing_pil_sam.py +++ b/src/transformers/models/sam/image_processing_pil_sam.py @@ -20,6 +20,9 @@ from typing import Any, Optional, Union import numpy as np +import torch +import torch.nn.functional as F +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature, get_size_dict @@ -33,17 +36,11 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, is_vision_available +from ...utils import TensorType, auto_docstring, is_torch_available, is_vision_available +from ...utils.import_utils import requires from .image_processing_sam import SamImageProcessorKwargs -if is_torch_available(): - import torch - import torch.nn.functional as F - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - if is_vision_available(): import PIL @@ -66,6 +63,7 @@ def get_resize_output_image_size( @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class SamImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR image_mean = IMAGENET_DEFAULT_MEAN diff --git a/src/transformers/models/sam3/modeling_sam3.py b/src/transformers/models/sam3/modeling_sam3.py index 1250dde03325..5a9aa329daa0 100644 --- a/src/transformers/models/sam3/modeling_sam3.py +++ b/src/transformers/models/sam3/modeling_sam3.py @@ -20,9 +20,14 @@ import torch import torch.nn as nn import torch.nn.functional as F -import torchvision from torch import Tensor +from ...utils import is_torchvision_available + + +if is_torchvision_available(): + import torchvision + from transformers import CLIPTextModelWithProjection from ... import initialization as init @@ -43,6 +48,7 @@ is_flash_attention_requested, merge_with_config_defaults, ) +from ...utils.import_utils import requires from ...utils.output_capturing import capture_outputs from ..auto import AutoModel from .configuration_sam3 import ( @@ -761,6 +767,7 @@ def forward( @auto_docstring +@requires(backends=("torch", "torchvision")) class Sam3PreTrainedModel(PreTrainedModel): config_class = Sam3Config base_model_prefix = "sam3" diff --git a/src/transformers/models/sam3_video/processing_sam3_video.py b/src/transformers/models/sam3_video/processing_sam3_video.py index 1a93f3f322be..6f7b1c238cfe 100644 --- a/src/transformers/models/sam3_video/processing_sam3_video.py +++ b/src/transformers/models/sam3_video/processing_sam3_video.py @@ -14,7 +14,12 @@ from typing import Union import torch -from torchvision.ops import masks_to_boxes + +from ...utils import is_torchvision_available + + +if is_torchvision_available(): + from torchvision.ops import masks_to_boxes from ...image_utils import ImageInput from ...processing_utils import ProcessorMixin @@ -25,7 +30,7 @@ from .modeling_sam3_video import Sam3VideoInferenceSession -@requires(backends=("torch",)) +@requires(backends=("torch", "torchvision")) @auto_docstring class Sam3VideoProcessor(ProcessorMixin): def __init__( diff --git a/src/transformers/models/segformer/image_processing_pil_segformer.py b/src/transformers/models/segformer/image_processing_pil_segformer.py index 00c632c9fe6c..bd517cfb9c56 100644 --- a/src/transformers/models/segformer/image_processing_pil_segformer.py +++ b/src/transformers/models/segformer/image_processing_pil_segformer.py @@ -33,6 +33,7 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available +from ...utils.import_utils import requires from .image_processing_segformer import SegformerImageProcessorKwargs @@ -43,7 +44,7 @@ import torchvision.transforms.v2.functional as tvF -@auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class SegformerImageProcessorPil(PilBackend): """PIL backend for Segformer with reduce_label support.""" diff --git a/src/transformers/models/segformer/modular_segformer.py b/src/transformers/models/segformer/modular_segformer.py index 2075432d7f13..a8303bd9ec05 100644 --- a/src/transformers/models/segformer/modular_segformer.py +++ b/src/transformers/models/segformer/modular_segformer.py @@ -32,6 +32,7 @@ SizeDict, ) from ...utils import TensorType +from ...utils.import_utils import requires class SegformerImageProcessor(BeitImageProcessor): @@ -141,6 +142,7 @@ def _preprocess( return processed_images +@requires(backends=("vision", "torch", "torchvision")) class SegformerImageProcessorPil(BeitImageProcessorPil): resample = PILImageResampling.BILINEAR image_mean = IMAGENET_DEFAULT_MEAN diff --git a/src/transformers/models/seggpt/image_processing_pil_seggpt.py b/src/transformers/models/seggpt/image_processing_pil_seggpt.py index e60e4005194f..33039503d802 100644 --- a/src/transformers/models/seggpt/image_processing_pil_seggpt.py +++ b/src/transformers/models/seggpt/image_processing_pil_seggpt.py @@ -14,6 +14,8 @@ """Image processor class for SegGPT.""" import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -26,18 +28,13 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, requires_backends +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires from .image_processing_seggpt import SegGptImageProcessorKwargs, build_palette -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class SegGptImageProcessorPil(PilBackend): valid_kwargs = SegGptImageProcessorKwargs @@ -245,11 +242,7 @@ def post_process_semantic_segmentation( for idx, mask in enumerate(masks): if target_sizes is not None: - mask = torch.nn.functional.interpolate( - mask.unsqueeze(0), - size=target_sizes[idx], - mode="nearest", - )[0] + mask = torch.nn.functional.interpolate(mask.unsqueeze(0), size=target_sizes[idx], mode="nearest")[0] if num_labels is not None: channels, height, width = mask.shape diff --git a/src/transformers/models/siglip2/image_processing_pil_siglip2.py b/src/transformers/models/siglip2/image_processing_pil_siglip2.py index d4a77363aa62..efca87b53635 100644 --- a/src/transformers/models/siglip2/image_processing_pil_siglip2.py +++ b/src/transformers/models/siglip2/image_processing_pil_siglip2.py @@ -22,18 +22,14 @@ from ...utils import ( TensorType, auto_docstring, - is_torchvision_available, ) +from ...utils.import_utils import requires from .image_processing_siglip2 import ( Siglip2ImageProcessorKwargs, get_image_size_for_max_num_patches, ) -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - def convert_image_to_patches(image: np.ndarray, patch_size: int) -> np.ndarray: """ Convert 3D array image of shape (num_channels, image_height, image_width) into 2D array of patches of shape @@ -62,6 +58,7 @@ def pad_along_first_dim(array: np.ndarray, target_length: int, pad_value: int = return array, mask +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Siglip2ImageProcessorPil(PilBackend): valid_kwargs = Siglip2ImageProcessorKwargs @@ -93,7 +90,7 @@ def _preprocess( do_resize: bool, patch_size: int, max_num_patches: int, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/smolvlm/image_processing_pil_smolvlm.py b/src/transformers/models/smolvlm/image_processing_pil_smolvlm.py index b0789aa97ca3..0f0711dcee7d 100644 --- a/src/transformers/models/smolvlm/image_processing_pil_smolvlm.py +++ b/src/transformers/models/smolvlm/image_processing_pil_smolvlm.py @@ -36,7 +36,8 @@ make_nested_list_of_images, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_smolvlm import ( MAX_IMAGE_SIZE, SmolVLMImageProcessorKwargs, @@ -48,10 +49,6 @@ ) -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - def _make_pixel_mask(image: np.ndarray, output_size: tuple[int, int]) -> np.ndarray: """Make pixel mask: 1=valid, 0=padding. Images are CHW.""" h, w = image.shape[-2:] @@ -60,6 +57,7 @@ def _make_pixel_mask(image: np.ndarray, output_size: tuple[int, int]) -> np.ndar return mask +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class SmolVLMImageProcessorPil(PilBackend): resample = PILImageResampling.LANCZOS @@ -196,7 +194,7 @@ def _preprocess( images: list[list[np.ndarray]], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/superglue/image_processing_pil_superglue.py b/src/transformers/models/superglue/image_processing_pil_superglue.py index ef75e3ab557b..bb2837a33eea 100644 --- a/src/transformers/models/superglue/image_processing_pil_superglue.py +++ b/src/transformers/models/superglue/image_processing_pil_superglue.py @@ -19,14 +19,10 @@ from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature -from ...image_utils import ( - ImageInput, - PILImageResampling, - SizeDict, - to_numpy_array, -) +from ...image_utils import ImageInput, PILImageResampling, SizeDict, to_numpy_array from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, is_vision_available +from ...utils import TensorType, auto_docstring, is_vision_available +from ...utils.import_utils import requires from .image_processing_superglue import validate_and_format_image_pairs @@ -37,24 +33,17 @@ import PIL from PIL import Image, ImageDraw -if is_torch_available(): - import torch +import torch +from torchvision.transforms.v2 import functional as tvF -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - -def is_grayscale( - image: np.ndarray, -): +def is_grayscale(image: np.ndarray): if image.shape[0] == 1: return True return np.all(image[0, ...] == image[1, ...]) and np.all(image[1, ...] == image[2, ...]) -def convert_to_grayscale( - image: ImageInput, -) -> ImageInput: +def convert_to_grayscale(image: ImageInput) -> ImageInput: """ Converts an image to grayscale format using the NTSC formula. Only support numpy and PIL Image. @@ -92,6 +81,7 @@ class SuperGlueImageProcessorKwargs(ImagesKwargs, total=False): @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class SuperGlueImageProcessorPil(PilBackend): valid_kwargs = SuperGlueImageProcessorKwargs resample = PILImageResampling.BILINEAR @@ -110,11 +100,7 @@ def __init__(self, **kwargs: Unpack[SuperGlueImageProcessorKwargs]): def preprocess(self, images: ImageInput, **kwargs: Unpack[SuperGlueImageProcessorKwargs]) -> BatchFeature: return super().preprocess(images, **kwargs) - def _prepare_images_structure( - self, - images: ImageInput, - **kwargs, - ) -> ImageInput: + def _prepare_images_structure(self, images: ImageInput, **kwargs) -> ImageInput: # we need to handle image pairs validation and flattening images = self.fetch_images(images) return validate_and_format_image_pairs(images) @@ -220,9 +206,7 @@ def post_process_keypoint_matching( return results def visualize_keypoint_matching( - self, - images: ImageInput, - keypoint_matching_output: list[dict[str, torch.Tensor]], + self, images: ImageInput, keypoint_matching_output: list[dict[str, torch.Tensor]] ) -> list["Image.Image"]: """ Plots the image pairs side by side with the detected keypoints as well as the matching between them. @@ -259,11 +243,7 @@ def visualize_keypoint_matching( keypoints0_x, keypoints0_y, keypoints1_x, keypoints1_y, pair_output["matching_scores"] ): color = self._get_color(matching_score) - draw.line( - (keypoint0_x, keypoint0_y, keypoint1_x + width0, keypoint1_y), - fill=color, - width=3, - ) + draw.line((keypoint0_x, keypoint0_y, keypoint1_x + width0, keypoint1_y), fill=color, width=3) draw.ellipse((keypoint0_x - 2, keypoint0_y - 2, keypoint0_x + 2, keypoint0_y + 2), fill="black") draw.ellipse( (keypoint1_x + width0 - 2, keypoint1_y - 2, keypoint1_x + width0 + 2, keypoint1_y + 2), diff --git a/src/transformers/models/superpoint/image_processing_pil_superpoint.py b/src/transformers/models/superpoint/image_processing_pil_superpoint.py index 2fff5dd91041..c428241b5840 100644 --- a/src/transformers/models/superpoint/image_processing_pil_superpoint.py +++ b/src/transformers/models/superpoint/image_processing_pil_superpoint.py @@ -21,18 +21,16 @@ from ...image_processing_utils import BatchFeature from ...image_utils import PILImageResampling, SizeDict from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, requires_backends +from ...utils import TensorType, auto_docstring, requires_backends +from ...utils.import_utils import requires from .image_processing_superpoint import SuperPointImageProcessorKwargs if TYPE_CHECKING: from .modeling_superpoint import SuperPointKeypointDescriptionOutput -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF +import torch +from torchvision.transforms.v2 import functional as tvF def is_grayscale(image: np.ndarray) -> bool: @@ -63,6 +61,7 @@ def convert_to_grayscale(image: np.ndarray) -> np.ndarray: @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class SuperPointImageProcessorPil(PilBackend): valid_kwargs = SuperPointImageProcessorKwargs resample = PILImageResampling.BILINEAR diff --git a/src/transformers/models/swin2sr/image_processing_pil_swin2sr.py b/src/transformers/models/swin2sr/image_processing_pil_swin2sr.py index 359ec5007c2e..8a8e4058af70 100644 --- a/src/transformers/models/swin2sr/image_processing_pil_swin2sr.py +++ b/src/transformers/models/swin2sr/image_processing_pil_swin2sr.py @@ -25,14 +25,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_swin2sr import Swin2SRImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class Swin2SRImageProcessorPil(PilBackend): """PIL backend for Swin2SR with custom pad.""" @@ -83,7 +81,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/textnet/image_processing_pil_textnet.py b/src/transformers/models/textnet/image_processing_pil_textnet.py index 9b2ab9f1ed75..394693c417a2 100644 --- a/src/transformers/models/textnet/image_processing_pil_textnet.py +++ b/src/transformers/models/textnet/image_processing_pil_textnet.py @@ -28,14 +28,12 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils import TensorType, auto_docstring +from ...utils.import_utils import requires from .image_processing_textnet import TextNetImageProcessorKwargs -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - - +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class TextNetImageProcessorPil(PilBackend): """PIL backend for TextNet with size_divisor resize.""" @@ -66,7 +64,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", size_divisor: int = 32, **kwargs, ) -> np.ndarray: @@ -97,7 +95,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/tvp/image_processing_pil_tvp.py b/src/transformers/models/tvp/image_processing_pil_tvp.py index 48796df9b4ae..7a15222ba975 100644 --- a/src/transformers/models/tvp/image_processing_pil_tvp.py +++ b/src/transformers/models/tvp/image_processing_pil_tvp.py @@ -31,6 +31,7 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils.import_utils import requires from .image_processing_tvp import TvpImageProcessorKwargs @@ -58,6 +59,7 @@ def get_resize_output_image_size( @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class TvpImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR image_mean = IMAGENET_STANDARD_MEAN diff --git a/src/transformers/models/video_llama_3/image_processing_pil_video_llama_3.py b/src/transformers/models/video_llama_3/image_processing_pil_video_llama_3.py index 90fbf0efbe86..53c3e3c03d26 100644 --- a/src/transformers/models/video_llama_3/image_processing_pil_video_llama_3.py +++ b/src/transformers/models/video_llama_3/image_processing_pil_video_llama_3.py @@ -26,6 +26,7 @@ from ...image_utils import IMAGENET_STANDARD_MEAN, IMAGENET_STANDARD_STD, ImageInput, PILImageResampling, SizeDict from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torchvision_available +from ...utils.import_utils import requires from .image_processing_video_llama_3 import VideoLlama3ImageProcessorKwargs, smart_resize @@ -33,6 +34,7 @@ from torchvision.transforms.v2 import functional as tvF +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class VideoLlama3ImageProcessorPil(PilBackend): do_resize = True diff --git a/src/transformers/models/videomae/image_processing_pil_videomae.py b/src/transformers/models/videomae/image_processing_pil_videomae.py index d0bdf700d93f..b268c3aefa91 100644 --- a/src/transformers/models/videomae/image_processing_pil_videomae.py +++ b/src/transformers/models/videomae/image_processing_pil_videomae.py @@ -26,11 +26,7 @@ make_nested_list_of_images, ) from ...processing_utils import ImagesKwargs, Unpack -from ...utils import TensorType, auto_docstring, is_torchvision_available - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF +from ...utils import TensorType, auto_docstring @auto_docstring @@ -67,7 +63,7 @@ def _preprocess( images: list[list[np.ndarray]], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_center_crop: bool, crop_size: SizeDict, do_rescale: bool, diff --git a/src/transformers/models/vilt/image_processing_pil_vilt.py b/src/transformers/models/vilt/image_processing_pil_vilt.py index 8ca27a0d0e74..a5c4ecd9de51 100644 --- a/src/transformers/models/vilt/image_processing_pil_vilt.py +++ b/src/transformers/models/vilt/image_processing_pil_vilt.py @@ -33,13 +33,8 @@ from ...utils import ( TensorType, auto_docstring, - is_torchvision_available, ) - - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - +from ...utils.import_utils import requires from .image_processing_vilt import ViltImageProcessorKwargs @@ -104,6 +99,7 @@ def get_resize_output_image_size( return new_height, new_width +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class ViltImageProcessorPil(PilBackend): valid_kwargs = ViltImageProcessorKwargs @@ -123,7 +119,7 @@ def resize( self, image: np.ndarray, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None" = None, + resample: "PILImageResampling | int | None" = None, size_divisor: int | None = None, ) -> np.ndarray: """ @@ -132,7 +128,7 @@ def resize( Args: image (`np.ndarray`): Image to resize. size (`SizeDict`): Size dictionary with shortest_edge key. - resample (`PILImageResampling | tvF.InterpolationMode | int`, *optional*): Interpolation method to use. + resample (`PILImageResampling | int`, *optional*): Interpolation method to use. size_divisor (`int`, *optional*): Value to ensure height/width are divisible by. Returns: @@ -205,7 +201,7 @@ def _preprocess( images: list[np.ndarray], do_resize: bool, size: SizeDict, - resample: "PILImageResampling | tvF.InterpolationMode | int | None", + resample: "PILImageResampling | int | None", do_rescale: bool, rescale_factor: float, do_normalize: bool, diff --git a/src/transformers/models/vitmatte/image_processing_pil_vitmatte.py b/src/transformers/models/vitmatte/image_processing_pil_vitmatte.py index b83a773b5ac5..7438d2aa9168 100644 --- a/src/transformers/models/vitmatte/image_processing_pil_vitmatte.py +++ b/src/transformers/models/vitmatte/image_processing_pil_vitmatte.py @@ -30,6 +30,7 @@ ) from ...processing_utils import Unpack from ...utils import TensorType, auto_docstring, is_torch_available +from ...utils.import_utils import requires from .image_processing_vitmatte import VitMatteImageProcessorKwargs @@ -37,6 +38,7 @@ import torch +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class VitMatteImageProcessorPil(PilBackend): do_rescale = True diff --git a/src/transformers/models/vitpose/image_processing_pil_vitpose.py b/src/transformers/models/vitpose/image_processing_pil_vitpose.py index c7000d5ac184..fb246f8dcc3d 100644 --- a/src/transformers/models/vitpose/image_processing_pil_vitpose.py +++ b/src/transformers/models/vitpose/image_processing_pil_vitpose.py @@ -17,6 +17,8 @@ from typing import TYPE_CHECKING, Union import numpy as np +import torch +from torchvision.transforms.v2 import functional as tvF from ...image_processing_backends import PilBackend from ...image_processing_utils import BatchFeature @@ -29,15 +31,8 @@ SizeDict, ) from ...processing_utils import Unpack -from ...utils import ( - TensorType, - auto_docstring, - is_scipy_available, - is_torch_available, - is_torchvision_available, - logging, - requires_backends, -) +from ...utils import TensorType, auto_docstring, is_scipy_available, logging, requires_backends +from ...utils.import_utils import requires from .image_processing_vitpose import ( VitPoseImageProcessorKwargs, box_to_center_and_scale, @@ -50,12 +45,6 @@ ) -if is_torch_available(): - import torch - -if is_torchvision_available(): - from torchvision.transforms.v2 import functional as tvF - if is_scipy_available(): pass @@ -66,6 +55,7 @@ @auto_docstring +@requires(backends=("torch", "torchvision")) class VitPoseImageProcessorPil(PilBackend): """PIL backend for VitPose with affine transform.""" @@ -115,12 +105,7 @@ def _preprocess_image_like_inputs( return self._preprocess(images, **kwargs) def affine_transform( - self, - image: np.ndarray, - center: tuple[float], - scale: tuple[float], - rotation: float, - size: SizeDict, + self, image: np.ndarray, center: tuple[float], scale: tuple[float], rotation: float, size: SizeDict ) -> np.ndarray: """Apply an affine transformation to an image.""" size_tuple = (size.width, size.height) @@ -161,10 +146,7 @@ def _preprocess( for image, image_boxes in zip(images, boxes): for box in image_boxes: center, scale = box_to_center_and_scale( - box, - image_width=size.width, - image_height=size.height, - normalize_factor=normalize_factor, + box, image_width=size.width, image_height=size.height, normalize_factor=normalize_factor ) transformed_image = self.affine_transform(image, center, scale, rotation=0, size=size) transformed_images.append(transformed_image) @@ -179,13 +161,7 @@ def _preprocess( processed_images.append(image) return BatchFeature(data={"pixel_values": processed_images}, tensor_type=return_tensors) - def keypoints_from_heatmaps( - self, - heatmaps: np.ndarray, - center: np.ndarray, - scale: np.ndarray, - kernel: int = 11, - ): + def keypoints_from_heatmaps(self, heatmaps: np.ndarray, center: np.ndarray, scale: np.ndarray, kernel: int = 11): """Get final keypoint predictions from heatmaps and transform them back to the image.""" batch_size, _, height, width = heatmaps.shape coords, scores = get_keypoint_predictions(heatmaps) diff --git a/src/transformers/models/yolos/image_processing_pil_yolos.py b/src/transformers/models/yolos/image_processing_pil_yolos.py index 52181802837e..943aee1cf6be 100644 --- a/src/transformers/models/yolos/image_processing_pil_yolos.py +++ b/src/transformers/models/yolos/image_processing_pil_yolos.py @@ -41,6 +41,7 @@ is_vision_available, requires_backends, ) +from ...utils.import_utils import requires from .image_processing_yolos import YolosImageProcessorKwargs @@ -279,6 +280,7 @@ def get_size_with_aspect_ratio_yolos( return (oh, ow) +@requires(backends=("vision", "torch", "torchvision")) @auto_docstring class YolosImageProcessorPil(PilBackend): resample = PILImageResampling.BILINEAR @@ -693,6 +695,7 @@ def _preprocess( ] return encoded_inputs + @requires(backends=("vision", "torch")) def post_process_object_detection( self, outputs, threshold: float = 0.5, target_sizes: TensorType | list[tuple] = None ): diff --git a/src/transformers/models/zoedepth/image_processing_pil_zoedepth.py b/src/transformers/models/zoedepth/image_processing_pil_zoedepth.py index c6da1e98b56f..3c446bbfdbbd 100644 --- a/src/transformers/models/zoedepth/image_processing_pil_zoedepth.py +++ b/src/transformers/models/zoedepth/image_processing_pil_zoedepth.py @@ -31,22 +31,24 @@ get_image_size, ) from ...processing_utils import Unpack -from ...utils import TensorType, auto_docstring, is_torch_available, is_torchvision_available, requires_backends +from ...utils import TensorType, auto_docstring, is_torchvision_available, requires_backends +from ...utils.import_utils import requires from .image_processing_zoedepth import ZoeDepthImageProcessorKwargs, get_resize_output_image_size if TYPE_CHECKING: from .modeling_zoedepth import ZoeDepthDepthEstimatorOutput -if is_torch_available(): - import torch - from torch import nn +import torch +from torch import nn + if is_torchvision_available(): import torchvision.transforms.v2.functional as tvF @auto_docstring +@requires(backends=("vision", "torch", "torchvision")) class ZoeDepthImageProcessorPil(PilBackend): valid_kwargs = ZoeDepthImageProcessorKwargs do_pad = True diff --git a/src/transformers/tokenization_mistral_common.py b/src/transformers/tokenization_mistral_common.py index 44947575cb15..1f218fe40873 100644 --- a/src/transformers/tokenization_mistral_common.py +++ b/src/transformers/tokenization_mistral_common.py @@ -1246,7 +1246,7 @@ def _maybe_adapt_message(message: dict[str, Any]) -> None: def _get_image_sizes_for_tensor( self, images: list[np.ndarray], return_tensors: str | TensorType | None - ) -> list[list[int]] | np.ndarray | torch.Tensor: + ) -> "list[list[int]] | np.ndarray | torch.Tensor": """ Convert image sizes to the appropriate format based on return_tensors. diff --git a/src/transformers/trainer_utils.py b/src/transformers/trainer_utils.py index 0a00c4d60283..400268de8180 100644 --- a/src/transformers/trainer_utils.py +++ b/src/transformers/trainer_utils.py @@ -62,7 +62,7 @@ import torch from safetensors.torch import load_file as safe_load_file -if is_peft_available(): +if is_peft_available() and is_torch_available(): from peft import PeftMixedModel, PeftModel diff --git a/src/transformers/utils/auto_docstring.py b/src/transformers/utils/auto_docstring.py index b314a9055e57..6a9370b4fcf3 100644 --- a/src/transformers/utils/auto_docstring.py +++ b/src/transformers/utils/auto_docstring.py @@ -4249,6 +4249,9 @@ def auto_class_docstring(cls, custom_intro=None, custom_args=None, checkpoint=No )[model_name_lowercase] except KeyError: pass + except ImportError: + # In some environments, certain model classes might not be available. In that case, we can skip this part. + pass if model_name_lowercase and model_name_lowercase not in getattr( getattr(auto_module, PLACEHOLDER_TO_AUTO_MODULE["config_class"][0]), diff --git a/src/transformers/utils/import_utils.py b/src/transformers/utils/import_utils.py index b31e97225ca3..e7a3068fe403 100644 --- a/src/transformers/utils/import_utils.py +++ b/src/transformers/utils/import_utils.py @@ -644,6 +644,8 @@ def is_libcst_available() -> bool: @lru_cache def is_accelerate_available(min_version: str = ACCELERATE_MIN_VERSION) -> bool: + if not is_torch_available(): + return False is_available, accelerate_version = _is_package_available("accelerate", return_version=True) return is_available and version.parse(accelerate_version) >= version.parse(min_version) @@ -672,7 +674,7 @@ def is_pygments_available() -> bool: @lru_cache def is_torchvision_available() -> bool: - return _is_package_available("torchvision")[0] + return is_vision_available() and is_torch_available() and _is_package_available("torchvision")[0] @lru_cache @@ -1126,12 +1128,17 @@ def is_tokenizers_available() -> bool: @lru_cache def is_vision_available() -> bool: - return _is_package_available("PIL")[0] + try: + import PIL.Image # noqa: F401 + + return True + except ImportError: + return False @lru_cache def is_pytesseract_available() -> bool: - return _is_package_available("pytesseract")[0] + return _is_package_available("pytesseract")[0] and is_vision_available() @lru_cache @@ -1166,7 +1173,7 @@ def is_soundfile_available() -> bool: @lru_cache def is_timm_available() -> bool: - return _is_package_available("timm")[0] + return is_vision_available() and is_torch_available() and _is_package_available("timm")[0] @lru_cache @@ -1191,11 +1198,13 @@ def is_numba_available() -> bool: @lru_cache def is_torchaudio_available() -> bool: - return _is_package_available("torchaudio")[0] + return is_torch_available() and _is_package_available("torchaudio")[0] @lru_cache def is_torchao_available(min_version: str = TORCHAO_MIN_VERSION) -> bool: + if not is_torch_available(): + return False is_available, torchao_version = _is_package_available("torchao", return_version=True) return is_available and version.parse(torchao_version) >= version.parse(min_version) @@ -1287,7 +1296,7 @@ def is_matplotlib_available() -> bool: @lru_cache def is_mistral_common_available() -> bool: - return _is_package_available("mistral_common")[0] + return is_vision_available() and _is_package_available("mistral_common")[0] @lru_cache @@ -2495,8 +2504,9 @@ def requires(*, backends=()): - The '@requires' string is used to dynamically import objects """ - if not isinstance(backends, tuple): - raise TypeError("Backends should be a tuple.") + if not isinstance(backends, (tuple, list)): + raise TypeError("Backends should be a tuple or list.") + backends = tuple(backends) applied_backends = [] for backend in backends: @@ -2517,19 +2527,14 @@ def inner_fn(fun): BASE_FILE_REQUIREMENTS = { lambda name, content: "modeling_" in name: ("torch",), - lambda name, content: name.startswith("tokenization_") and name.endswith("_fast"): ("tokenizers",), - lambda name, content: name.startswith("image_processing_") and name.endswith("_fast"): ( + lambda name, content: "tokenization_" in name and name.endswith("_fast"): ("tokenizers",), + lambda name, content: "image_processing_" in name and "TorchvisionBackend" in content: ( "vision", "torch", "torchvision", ), - lambda name, content: name.startswith("image_processing_") and "TorchvisionBackend" in content: ( - "vision", - "torch", - "torchvision", - ), - lambda name, content: name.startswith("image_processing_"): ("vision",), - lambda name, content: name.startswith("video_processing_"): ("vision", "torch", "torchvision"), + lambda name, content: "image_processing_" in name: ("vision",), + lambda name, content: "video_processing_" in name: ("vision", "torch", "torchvision"), } @@ -2686,20 +2691,25 @@ def create_import_structure_from_path(module_path): continue # Skipping line enables putting whatever we want between the - # export() call and the actual class/method definition. + # requires() call and the actual class/method definition. # This is what enables having # Copied from statements, docs, etc. skip_line = False if "@requires" in previous_line: skip_line = False - # Backends are defined on the same line as export + # Backends are defined on the same line as requires if "backends" in previous_line: - backends_string = previous_line.split("backends=")[1].split("(")[1].split(")")[0] + try: + backends_string = previous_line.split("backends=")[1].split("(")[1].split(")")[0] + except IndexError: + raise ValueError( + f"Couldn't parse backends for @requires decorator in file {module_name}:{previous_line}" + ) backends = tuple(sorted([b.strip("'\",") for b in backends_string.split(", ") if b])) - # Backends are defined in the lines following export, for example such as: - # @export( + # Backends are defined in the lines following requires, for example such as: + # @requires( # backends=( # "sentencepiece", # "torch", @@ -2708,7 +2718,7 @@ def create_import_structure_from_path(module_path): # # or # - # @export( + # @requires( # backends=( # "sentencepiece", # ) @@ -2729,7 +2739,7 @@ def create_import_structure_from_path(module_path): break backends = tuple(backends) - # No backends are registered for export + # No backends are registered for requires else: backends = ()