CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
image_processing_base.py544 linesDownload Raw Back to transformers
1# Copyright 2020 The HuggingFace Inc. team.2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#     http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14 15 16import copy17import json18import os19import warnings20from typing import Any, Optional, TypeVar, Union21 22import numpy as np23 24from .dynamic_module_utils import custom_object_save25from .feature_extraction_utils import BatchFeature as BaseBatchFeature26from .image_utils import is_valid_image, load_image27from .utils import (28    IMAGE_PROCESSOR_NAME,29    PROCESSOR_NAME,30    PushToHubMixin,31    copy_func,32    download_url,33    is_offline_mode,34    is_remote_url,35    logging,36)37from .utils.hub import cached_file38 39 40ImageProcessorType = TypeVar("ImageProcessorType", bound="ImageProcessingMixin")41 42 43logger = logging.get_logger(__name__)44 45 46# TODO: Move BatchFeature to be imported by both image_processing_utils and image_processing_utils_fast47# We override the class string here, but logic is the same.48class BatchFeature(BaseBatchFeature):49    r"""50    Holds the output of the image processor specific `__call__` methods.51 52    This class is derived from a python dictionary and can be used as a dictionary.53 54    Args:55        data (`dict`):56            Dictionary of lists/arrays/tensors returned by the __call__ method ('pixel_values', etc.).57        tensor_type (`Union[None, str, TensorType]`, *optional*):58            You can give a tensor_type here to convert the lists of integers in PyTorch/TensorFlow/Numpy Tensors at59            initialization.60    """61 62 63# TODO: (Amy) - factor out the common parts of this and the feature extractor64class ImageProcessingMixin(PushToHubMixin):65    """66    This is an image processor mixin used to provide saving/loading functionality for sequential and image feature67    extractors.68    """69 70    _auto_class = None71 72    def __init__(self, **kwargs):73        """Set elements of `kwargs` as attributes."""74        # This key was saved while we still used `XXXFeatureExtractor` for image processing. Now we use75        # `XXXImageProcessor`, this attribute and its value are misleading.76        kwargs.pop("feature_extractor_type", None)77        # Pop "processor_class" as it should be saved as private attribute78        self._processor_class = kwargs.pop("processor_class", None)79        # Additional attributes without default values80        for key, value in kwargs.items():81            try:82                setattr(self, key, value)83            except AttributeError as err:84                logger.error(f"Can't set {key} with value {value} for {self}")85                raise err86 87    def _set_processor_class(self, processor_class: str):88        """Sets processor class as an attribute."""89        self._processor_class = processor_class90 91    @classmethod92    def from_pretrained(93        cls: type[ImageProcessorType],94        pretrained_model_name_or_path: Union[str, os.PathLike],95        cache_dir: Optional[Union[str, os.PathLike]] = None,96        force_download: bool = False,97        local_files_only: bool = False,98        token: Optional[Union[str, bool]] = None,99        revision: str = "main",100        **kwargs,101    ) -> ImageProcessorType:102        r"""103        Instantiate a type of [`~image_processing_utils.ImageProcessingMixin`] from an image processor.104 105        Args:106            pretrained_model_name_or_path (`str` or `os.PathLike`):107                This can be either:108 109                - a string, the *model id* of a pretrained image_processor hosted inside a model repo on110                  huggingface.co.111                - a path to a *directory* containing a image processor file saved using the112                  [`~image_processing_utils.ImageProcessingMixin.save_pretrained`] method, e.g.,113                  `./my_model_directory/`.114                - a path or url to a saved image processor JSON *file*, e.g.,115                  `./my_model_directory/preprocessor_config.json`.116            cache_dir (`str` or `os.PathLike`, *optional*):117                Path to a directory in which a downloaded pretrained model image processor should be cached if the118                standard cache should not be used.119            force_download (`bool`, *optional*, defaults to `False`):120                Whether or not to force to (re-)download the image processor files and override the cached versions if121                they exist.122            resume_download:123                Deprecated and ignored. All downloads are now resumed by default when possible.124                Will be removed in v5 of Transformers.125            proxies (`dict[str, str]`, *optional*):126                A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',127                'http://hostname': 'foo.bar:4012'}.` The proxies are used on each request.128            token (`str` or `bool`, *optional*):129                The token to use as HTTP bearer authorization for remote files. If `True`, or not specified, will use130                the token generated when running `hf auth login` (stored in `~/.huggingface`).131            revision (`str`, *optional*, defaults to `"main"`):132                The specific model version to use. It can be a branch name, a tag name, or a commit id, since we use a133                git-based system for storing models and other artifacts on huggingface.co, so `revision` can be any134                identifier allowed by git.135 136 137                <Tip>138 139                To test a pull request you made on the Hub, you can pass `revision="refs/pr/<pr_number>"`.140 141                </Tip>142 143            return_unused_kwargs (`bool`, *optional*, defaults to `False`):144                If `False`, then this function returns just the final image processor object. If `True`, then this145                functions returns a `Tuple(image_processor, unused_kwargs)` where *unused_kwargs* is a dictionary146                consisting of the key/value pairs whose keys are not image processor attributes: i.e., the part of147                `kwargs` which has not been used to update `image_processor` and is otherwise ignored.148            subfolder (`str`, *optional*, defaults to `""`):149                In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can150                specify the folder name here.151            kwargs (`dict[str, Any]`, *optional*):152                The values in kwargs of any keys which are image processor attributes will be used to override the153                loaded values. Behavior concerning key/value pairs whose keys are *not* image processor attributes is154                controlled by the `return_unused_kwargs` keyword parameter.155 156        Returns:157            A image processor of type [`~image_processing_utils.ImageProcessingMixin`].158 159        Examples:160 161        ```python162        # We can't instantiate directly the base class *ImageProcessingMixin* so let's show the examples on a163        # derived class: *CLIPImageProcessor*164        image_processor = CLIPImageProcessor.from_pretrained(165            "openai/clip-vit-base-patch32"166        )  # Download image_processing_config from huggingface.co and cache.167        image_processor = CLIPImageProcessor.from_pretrained(168            "./test/saved_model/"169        )  # E.g. image processor (or model) was saved using *save_pretrained('./test/saved_model/')*170        image_processor = CLIPImageProcessor.from_pretrained("./test/saved_model/preprocessor_config.json")171        image_processor = CLIPImageProcessor.from_pretrained(172            "openai/clip-vit-base-patch32", do_normalize=False, foo=False173        )174        assert image_processor.do_normalize is False175        image_processor, unused_kwargs = CLIPImageProcessor.from_pretrained(176            "openai/clip-vit-base-patch32", do_normalize=False, foo=False, return_unused_kwargs=True177        )178        assert image_processor.do_normalize is False179        assert unused_kwargs == {"foo": False}180        ```"""181        kwargs["cache_dir"] = cache_dir182        kwargs["force_download"] = force_download183        kwargs["local_files_only"] = local_files_only184        kwargs["revision"] = revision185 186        use_auth_token = kwargs.pop("use_auth_token", None)187        if use_auth_token is not None:188            warnings.warn(189                "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",190                FutureWarning,191            )192            if token is not None:193                raise ValueError(194                    "`token` and `use_auth_token` are both specified. Please set only the argument `token`."195                )196            token = use_auth_token197 198        if token is not None:199            kwargs["token"] = token200 201        image_processor_dict, kwargs = cls.get_image_processor_dict(pretrained_model_name_or_path, **kwargs)202 203        return cls.from_dict(image_processor_dict, **kwargs)204 205    def save_pretrained(self, save_directory: Union[str, os.PathLike], push_to_hub: bool = False, **kwargs):206        """207        Save an image processor object to the directory `save_directory`, so that it can be re-loaded using the208        [`~image_processing_utils.ImageProcessingMixin.from_pretrained`] class method.209 210        Args:211            save_directory (`str` or `os.PathLike`):212                Directory where the image processor JSON file will be saved (will be created if it does not exist).213            push_to_hub (`bool`, *optional*, defaults to `False`):214                Whether or not to push your model to the Hugging Face model hub after saving it. You can specify the215                repository you want to push to with `repo_id` (will default to the name of `save_directory` in your216                namespace).217            kwargs (`dict[str, Any]`, *optional*):218                Additional key word arguments passed along to the [`~utils.PushToHubMixin.push_to_hub`] method.219        """220        use_auth_token = kwargs.pop("use_auth_token", None)221 222        if use_auth_token is not None:223            warnings.warn(224                "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",225                FutureWarning,226            )227            if kwargs.get("token") is not None:228                raise ValueError(229                    "`token` and `use_auth_token` are both specified. Please set only the argument `token`."230                )231            kwargs["token"] = use_auth_token232 233        if os.path.isfile(save_directory):234            raise AssertionError(f"Provided path ({save_directory}) should be a directory, not a file")235 236        os.makedirs(save_directory, exist_ok=True)237 238        if push_to_hub:239            commit_message = kwargs.pop("commit_message", None)240            repo_id = kwargs.pop("repo_id", save_directory.split(os.path.sep)[-1])241            repo_id = self._create_repo(repo_id, **kwargs)242            files_timestamps = self._get_files_timestamps(save_directory)243 244        # If we have a custom config, we copy the file defining it in the folder and set the attributes so it can be245        # loaded from the Hub.246        if self._auto_class is not None:247            custom_object_save(self, save_directory, config=self)248 249        # If we save using the predefined names, we can load using `from_pretrained`250        output_image_processor_file = os.path.join(save_directory, IMAGE_PROCESSOR_NAME)251 252        self.to_json_file(output_image_processor_file)253        logger.info(f"Image processor saved in {output_image_processor_file}")254 255        if push_to_hub:256            self._upload_modified_files(257                save_directory,258                repo_id,259                files_timestamps,260                commit_message=commit_message,261                token=kwargs.get("token"),262            )263 264        return [output_image_processor_file]265 266    @classmethod267    def get_image_processor_dict(268        cls, pretrained_model_name_or_path: Union[str, os.PathLike], **kwargs269    ) -> tuple[dict[str, Any], dict[str, Any]]:270        """271        From a `pretrained_model_name_or_path`, resolve to a dictionary of parameters, to be used for instantiating a272        image processor of type [`~image_processor_utils.ImageProcessingMixin`] using `from_dict`.273 274        Parameters:275            pretrained_model_name_or_path (`str` or `os.PathLike`):276                The identifier of the pre-trained checkpoint from which we want the dictionary of parameters.277            subfolder (`str`, *optional*, defaults to `""`):278                In case the relevant files are located inside a subfolder of the model repo on huggingface.co, you can279                specify the folder name here.280            image_processor_filename (`str`, *optional*, defaults to `"config.json"`):281                The name of the file in the model directory to use for the image processor config.282 283        Returns:284            `tuple[Dict, Dict]`: The dictionary(ies) that will be used to instantiate the image processor object.285        """286        cache_dir = kwargs.pop("cache_dir", None)287        force_download = kwargs.pop("force_download", False)288        resume_download = kwargs.pop("resume_download", None)289        proxies = kwargs.pop("proxies", None)290        token = kwargs.pop("token", None)291        use_auth_token = kwargs.pop("use_auth_token", None)292        local_files_only = kwargs.pop("local_files_only", False)293        revision = kwargs.pop("revision", None)294        subfolder = kwargs.pop("subfolder", "")295        image_processor_filename = kwargs.pop("image_processor_filename", IMAGE_PROCESSOR_NAME)296 297        from_pipeline = kwargs.pop("_from_pipeline", None)298        from_auto_class = kwargs.pop("_from_auto", False)299 300        if use_auth_token is not None:301            warnings.warn(302                "The `use_auth_token` argument is deprecated and will be removed in v5 of Transformers. Please use `token` instead.",303                FutureWarning,304            )305            if token is not None:306                raise ValueError(307                    "`token` and `use_auth_token` are both specified. Please set only the argument `token`."308                )309            token = use_auth_token310 311        user_agent = {"file_type": "image processor", "from_auto_class": from_auto_class}312        if from_pipeline is not None:313            user_agent["using_pipeline"] = from_pipeline314 315        if is_offline_mode() and not local_files_only:316            logger.info("Offline mode: forcing local_files_only=True")317            local_files_only = True318 319        pretrained_model_name_or_path = str(pretrained_model_name_or_path)320        is_local = os.path.isdir(pretrained_model_name_or_path)321        if os.path.isdir(pretrained_model_name_or_path):322            image_processor_file = os.path.join(pretrained_model_name_or_path, image_processor_filename)323        if os.path.isfile(pretrained_model_name_or_path):324            resolved_image_processor_file = pretrained_model_name_or_path325            is_local = True326        elif is_remote_url(pretrained_model_name_or_path):327            image_processor_file = pretrained_model_name_or_path328            resolved_image_processor_file = download_url(pretrained_model_name_or_path)329        else:330            image_processor_file = image_processor_filename331            try:332                # Load from local folder or from cache or download from model Hub and cache333                resolved_image_processor_files = [334                    resolved_file335                    for filename in [image_processor_file, PROCESSOR_NAME]336                    if (337                        resolved_file := cached_file(338                            pretrained_model_name_or_path,339                            filename=filename,340                            cache_dir=cache_dir,341                            force_download=force_download,342                            proxies=proxies,343                            resume_download=resume_download,344                            local_files_only=local_files_only,345                            token=token,346                            user_agent=user_agent,347                            revision=revision,348                            subfolder=subfolder,349                            _raise_exceptions_for_missing_entries=False,350                        )351                    )352                    is not None353                ]354                resolved_image_processor_file = resolved_image_processor_files[0]355            except OSError:356                # Raise any environment error raise by `cached_file`. It will have a helpful error message adapted to357                # the original exception.358                raise359            except Exception:360                # For any other exception, we throw a generic error.361                raise OSError(362                    f"Can't load image processor for '{pretrained_model_name_or_path}'. If you were trying to load"363                    " it from 'https://huggingface.co/models', make sure you don't have a local directory with the"364                    f" same name. Otherwise, make sure '{pretrained_model_name_or_path}' is the correct path to a"365                    f" directory containing a {image_processor_filename} file"366                )367 368        try:369            # Load image_processor dict370            with open(resolved_image_processor_file, encoding="utf-8") as reader:371                text = reader.read()372            image_processor_dict = json.loads(text)373            image_processor_dict = image_processor_dict.get("image_processor", image_processor_dict)374 375        except json.JSONDecodeError:376            raise OSError(377                f"It looks like the config file at '{resolved_image_processor_file}' is not a valid JSON file."378            )379 380        if is_local:381            logger.info(f"loading configuration file {resolved_image_processor_file}")382        else:383            logger.info(384                f"loading configuration file {image_processor_file} from cache at {resolved_image_processor_file}"385            )386 387        return image_processor_dict, kwargs388 389    @classmethod390    def from_dict(cls, image_processor_dict: dict[str, Any], **kwargs):391        """392        Instantiates a type of [`~image_processing_utils.ImageProcessingMixin`] from a Python dictionary of parameters.393 394        Args:395            image_processor_dict (`dict[str, Any]`):396                Dictionary that will be used to instantiate the image processor object. Such a dictionary can be397                retrieved from a pretrained checkpoint by leveraging the398                [`~image_processing_utils.ImageProcessingMixin.to_dict`] method.399            kwargs (`dict[str, Any]`):400                Additional parameters from which to initialize the image processor object.401 402        Returns:403            [`~image_processing_utils.ImageProcessingMixin`]: The image processor object instantiated from those404            parameters.405        """406        image_processor_dict = image_processor_dict.copy()407        return_unused_kwargs = kwargs.pop("return_unused_kwargs", False)408 409        # The `size` parameter is a dict and was previously an int or tuple in feature extractors.410        # We set `size` here directly to the `image_processor_dict` so that it is converted to the appropriate411        # dict within the image processor and isn't overwritten if `size` is passed in as a kwarg.412        if "size" in kwargs and "size" in image_processor_dict:413            image_processor_dict["size"] = kwargs.pop("size")414        if "crop_size" in kwargs and "crop_size" in image_processor_dict:415            image_processor_dict["crop_size"] = kwargs.pop("crop_size")416 417        image_processor = cls(**image_processor_dict)418 419        # Update image_processor with kwargs if needed420        to_remove = []421        for key, value in kwargs.items():422            if hasattr(image_processor, key):423                setattr(image_processor, key, value)424                to_remove.append(key)425        for key in to_remove:426            kwargs.pop(key, None)427 428        logger.info(f"Image processor {image_processor}")429        if return_unused_kwargs:430            return image_processor, kwargs431        else:432            return image_processor433 434    def to_dict(self) -> dict[str, Any]:435        """436        Serializes this instance to a Python dictionary.437 438        Returns:439            `dict[str, Any]`: Dictionary of all the attributes that make up this image processor instance.440        """441        output = copy.deepcopy(self.__dict__)442        output["image_processor_type"] = self.__class__.__name__443 444        return output445 446    @classmethod447    def from_json_file(cls, json_file: Union[str, os.PathLike]):448        """449        Instantiates a image processor of type [`~image_processing_utils.ImageProcessingMixin`] from the path to a JSON450        file of parameters.451 452        Args:453            json_file (`str` or `os.PathLike`):454                Path to the JSON file containing the parameters.455 456        Returns:457            A image processor of type [`~image_processing_utils.ImageProcessingMixin`]: The image_processor object458            instantiated from that JSON file.459        """460        with open(json_file, encoding="utf-8") as reader:461            text = reader.read()462        image_processor_dict = json.loads(text)463        return cls(**image_processor_dict)464 465    def to_json_string(self) -> str:466        """467        Serializes this instance to a JSON string.468 469        Returns:470            `str`: String containing all the attributes that make up this feature_extractor instance in JSON format.471        """472        dictionary = self.to_dict()473 474        for key, value in dictionary.items():475            if isinstance(value, np.ndarray):476                dictionary[key] = value.tolist()477 478        # make sure private name "_processor_class" is correctly479        # saved as "processor_class"480        _processor_class = dictionary.pop("_processor_class", None)481        if _processor_class is not None:482            dictionary["processor_class"] = _processor_class483 484        return json.dumps(dictionary, indent=2, sort_keys=True) + "\n"485 486    def to_json_file(self, json_file_path: Union[str, os.PathLike]):487        """488        Save this instance to a JSON file.489 490        Args:491            json_file_path (`str` or `os.PathLike`):492                Path to the JSON file in which this image_processor instance's parameters will be saved.493        """494        with open(json_file_path, "w", encoding="utf-8") as writer:495            writer.write(self.to_json_string())496 497    def __repr__(self):498        return f"{self.__class__.__name__} {self.to_json_string()}"499 500    @classmethod501    def register_for_auto_class(cls, auto_class="AutoImageProcessor"):502        """503        Register this class with a given auto class. This should only be used for custom image processors as the ones504        in the library are already mapped with `AutoImageProcessor `.505 506 507 508        Args:509            auto_class (`str` or `type`, *optional*, defaults to `"AutoImageProcessor "`):510                The auto class to register this new image processor with.511        """512        if not isinstance(auto_class, str):513            auto_class = auto_class.__name__514 515        import transformers.models.auto as auto_module516 517        if not hasattr(auto_module, auto_class):518            raise ValueError(f"{auto_class} is not a valid auto class.")519 520        cls._auto_class = auto_class521 522    def fetch_images(self, image_url_or_urls: Union[str, list[str], list[list[str]]]):523        """524        Convert a single or a list of urls into the corresponding `PIL.Image` objects.525 526        If a single url is passed, the return value will be a single object. If a list is passed a list of objects is527        returned.528        """529        if isinstance(image_url_or_urls, list):530            return [self.fetch_images(x) for x in image_url_or_urls]531        elif isinstance(image_url_or_urls, str):532            return load_image(image_url_or_urls)533        elif is_valid_image(image_url_or_urls):534            return image_url_or_urls535        else:536            raise TypeError(f"only a single or a list of entries is supported but got type={type(image_url_or_urls)}")537 538 539ImageProcessingMixin.push_to_hub = copy_func(ImageProcessingMixin.push_to_hub)540if ImageProcessingMixin.push_to_hub.__doc__ is not None:541    ImageProcessingMixin.push_to_hub.__doc__ = ImageProcessingMixin.push_to_hub.__doc__.format(542        object="image processor", object_class="AutoImageProcessor", object_files="image processor file"543    )544 
Aluode/PerceptionLabPortable · CoolFace