Aluode/PerceptionLabPortable
0
1# coding=utf-82# Copyright 2022 The HuggingFace Inc. team. All rights reserved.3#4# Licensed under the Apache License, Version 2.0 (the "License");5# you may not use this file except in compliance with the License.6# You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing, software11# distributed under the License is distributed on an "AS IS" BASIS,12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13# See the License for the specific language governing permissions and14# limitations under the License.15"""Image processor class for ConvNeXT."""16 17from typing import Optional, Union18 19import numpy as np20 21from ...image_processing_utils import BaseImageProcessor, BatchFeature, get_size_dict22from ...image_transforms import (23 center_crop,24 get_resize_output_image_size,25 resize,26 to_channel_dimension_format,27)28from ...image_utils import (29 IMAGENET_STANDARD_MEAN,30 IMAGENET_STANDARD_STD,31 ChannelDimension,32 ImageInput,33 PILImageResampling,34 infer_channel_dimension_format,35 is_scaled_image,36 make_flat_list_of_images,37 to_numpy_array,38 valid_images,39 validate_preprocess_arguments,40)41from ...utils import TensorType, filter_out_non_signature_kwargs, is_vision_available, logging42from ...utils.import_utils import requires43 44 45if is_vision_available():46 import PIL47 48 49logger = logging.get_logger(__name__)50 51 52@requires(backends=("vision",))53class ConvNextImageProcessor(BaseImageProcessor):54 r"""55 Constructs a ConvNeXT image processor.56 57 Args:58 do_resize (`bool`, *optional*, defaults to `True`):59 Controls whether to resize the image's (height, width) dimensions to the specified `size`. Can be overridden60 by `do_resize` in the `preprocess` method.61 size (`dict[str, int]` *optional*, defaults to `{"shortest_edge": 384}`):62 Resolution of the output image after `resize` is applied. If `size["shortest_edge"]` >= 384, the image is63 resized to `(size["shortest_edge"], size["shortest_edge"])`. Otherwise, the smaller edge of the image will64 be matched to `int(size["shortest_edge"]/crop_pct)`, after which the image is cropped to65 `(size["shortest_edge"], size["shortest_edge"])`. Only has an effect if `do_resize` is set to `True`. Can66 be overridden by `size` in the `preprocess` method.67 crop_pct (`float` *optional*, defaults to 224 / 256):68 Percentage of the image to crop. Only has an effect if `do_resize` is `True` and size < 384. Can be69 overridden by `crop_pct` in the `preprocess` method.70 resample (`PILImageResampling`, *optional*, defaults to `Resampling.BILINEAR`):71 Resampling filter to use if resizing the image. Can be overridden by `resample` in the `preprocess` method.72 do_rescale (`bool`, *optional*, defaults to `True`):73 Whether to rescale the image by the specified scale `rescale_factor`. Can be overridden by `do_rescale` in74 the `preprocess` method.75 rescale_factor (`int` or `float`, *optional*, defaults to `1/255`):76 Scale factor to use if rescaling the image. Can be overridden by `rescale_factor` in the `preprocess`77 method.78 do_normalize (`bool`, *optional*, defaults to `True`):79 Whether to normalize the image. Can be overridden by the `do_normalize` parameter in the `preprocess`80 method.81 image_mean (`float` or `list[float]`, *optional*, defaults to `IMAGENET_STANDARD_MEAN`):82 Mean to use if normalizing the image. This is a float or list of floats the length of the number of83 channels in the image. Can be overridden by the `image_mean` parameter in the `preprocess` method.84 image_std (`float` or `list[float]`, *optional*, defaults to `IMAGENET_STANDARD_STD`):85 Standard deviation to use if normalizing the image. This is a float or list of floats the length of the86 number of channels in the image. Can be overridden by the `image_std` parameter in the `preprocess` method.87 """88 89 model_input_names = ["pixel_values"]90 91 def __init__(92 self,93 do_resize: bool = True,94 size: Optional[dict[str, int]] = None,95 crop_pct: Optional[float] = None,96 resample: PILImageResampling = PILImageResampling.BILINEAR,97 do_rescale: bool = True,98 rescale_factor: Union[int, float] = 1 / 255,99 do_normalize: bool = True,100 image_mean: Optional[Union[float, list[float]]] = None,101 image_std: Optional[Union[float, list[float]]] = None,102 **kwargs,103 ) -> None:104 super().__init__(**kwargs)105 size = size if size is not None else {"shortest_edge": 384}106 size = get_size_dict(size, default_to_square=False)107 108 self.do_resize = do_resize109 self.size = size110 # Default value set here for backwards compatibility where the value in config is None111 self.crop_pct = crop_pct if crop_pct is not None else 224 / 256112 self.resample = resample113 self.do_rescale = do_rescale114 self.rescale_factor = rescale_factor115 self.do_normalize = do_normalize116 self.image_mean = image_mean if image_mean is not None else IMAGENET_STANDARD_MEAN117 self.image_std = image_std if image_std is not None else IMAGENET_STANDARD_STD118 119 def resize(120 self,121 image: np.ndarray,122 size: dict[str, int],123 crop_pct: float,124 resample: PILImageResampling = PILImageResampling.BICUBIC,125 data_format: Optional[Union[str, ChannelDimension]] = None,126 input_data_format: Optional[Union[str, ChannelDimension]] = None,127 **kwargs,128 ) -> np.ndarray:129 """130 Resize an image.131 132 Args:133 image (`np.ndarray`):134 Image to resize.135 size (`dict[str, int]`):136 Dictionary of the form `{"shortest_edge": int}`, specifying the size of the output image. If137 `size["shortest_edge"]` >= 384 image is resized to `(size["shortest_edge"], size["shortest_edge"])`.138 Otherwise, the smaller edge of the image will be matched to `int(size["shortest_edge"] / crop_pct)`,139 after which the image is cropped to `(size["shortest_edge"], size["shortest_edge"])`.140 crop_pct (`float`):141 Percentage of the image to crop. Only has an effect if size < 384.142 resample (`PILImageResampling`, *optional*, defaults to `PILImageResampling.BICUBIC`):143 Resampling filter to use when resizing the image.144 data_format (`str` or `ChannelDimension`, *optional*):145 The channel dimension format of the image. If not provided, it will be the same as the input image.146 input_data_format (`ChannelDimension` or `str`, *optional*):147 The channel dimension format of the input image. If not provided, it will be inferred from the input148 image.149 """150 size = get_size_dict(size, default_to_square=False)151 if "shortest_edge" not in size:152 raise ValueError(f"Size dictionary must contain 'shortest_edge' key. Got {size.keys()}")153 shortest_edge = size["shortest_edge"]154 155 if shortest_edge < 384:156 # maintain same ratio, resizing shortest edge to shortest_edge/crop_pct157 resize_shortest_edge = int(shortest_edge / crop_pct)158 resize_size = get_resize_output_image_size(159 image, size=resize_shortest_edge, default_to_square=False, input_data_format=input_data_format160 )161 image = resize(162 image=image,163 size=resize_size,164 resample=resample,165 data_format=data_format,166 input_data_format=input_data_format,167 **kwargs,168 )169 # then crop to (shortest_edge, shortest_edge)170 return center_crop(171 image=image,172 size=(shortest_edge, shortest_edge),173 data_format=data_format,174 input_data_format=input_data_format,175 **kwargs,176 )177 else:178 # warping (no cropping) when evaluated at 384 or larger179 return resize(180 image,181 size=(shortest_edge, shortest_edge),182 resample=resample,183 data_format=data_format,184 input_data_format=input_data_format,185 **kwargs,186 )187 188 @filter_out_non_signature_kwargs()189 def preprocess(190 self,191 images: ImageInput,192 do_resize: Optional[bool] = None,193 size: Optional[dict[str, int]] = None,194 crop_pct: Optional[float] = None,195 resample: Optional[PILImageResampling] = None,196 do_rescale: Optional[bool] = None,197 rescale_factor: Optional[float] = None,198 do_normalize: Optional[bool] = None,199 image_mean: Optional[Union[float, list[float]]] = None,200 image_std: Optional[Union[float, list[float]]] = None,201 return_tensors: Optional[Union[str, TensorType]] = None,202 data_format: ChannelDimension = ChannelDimension.FIRST,203 input_data_format: Optional[Union[str, ChannelDimension]] = None,204 ) -> PIL.Image.Image:205 """206 Preprocess an image or batch of images.207 208 Args:209 images (`ImageInput`):210 Image to preprocess. Expects a single or batch of images with pixel values ranging from 0 to 255. If211 passing in images with pixel values between 0 and 1, set `do_rescale=False`.212 do_resize (`bool`, *optional*, defaults to `self.do_resize`):213 Whether to resize the image.214 size (`dict[str, int]`, *optional*, defaults to `self.size`):215 Size of the output image after `resize` has been applied. If `size["shortest_edge"]` >= 384, the image216 is resized to `(size["shortest_edge"], size["shortest_edge"])`. Otherwise, the smaller edge of the217 image will be matched to `int(size["shortest_edge"]/ crop_pct)`, after which the image is cropped to218 `(size["shortest_edge"], size["shortest_edge"])`. Only has an effect if `do_resize` is set to `True`.219 crop_pct (`float`, *optional*, defaults to `self.crop_pct`):220 Percentage of the image to crop if size < 384.221 resample (`int`, *optional*, defaults to `self.resample`):222 Resampling filter to use if resizing the image. This can be one of `PILImageResampling`, filters. Only223 has an effect if `do_resize` is set to `True`.224 do_rescale (`bool`, *optional*, defaults to `self.do_rescale`):225 Whether to rescale the image values between [0 - 1].226 rescale_factor (`float`, *optional*, defaults to `self.rescale_factor`):227 Rescale factor to rescale the image by if `do_rescale` is set to `True`.228 do_normalize (`bool`, *optional*, defaults to `self.do_normalize`):229 Whether to normalize the image.230 image_mean (`float` or `list[float]`, *optional*, defaults to `self.image_mean`):231 Image mean.232 image_std (`float` or `list[float]`, *optional*, defaults to `self.image_std`):233 Image standard deviation.234 return_tensors (`str` or `TensorType`, *optional*):235 The type of tensors to return. Can be one of:236 - Unset: Return a list of `np.ndarray`.237 - `TensorType.TENSORFLOW` or `'tf'`: Return a batch of type `tf.Tensor`.238 - `TensorType.PYTORCH` or `'pt'`: Return a batch of type `torch.Tensor`.239 - `TensorType.NUMPY` or `'np'`: Return a batch of type `np.ndarray`.240 - `TensorType.JAX` or `'jax'`: Return a batch of type `jax.numpy.ndarray`.241 data_format (`ChannelDimension` or `str`, *optional*, defaults to `ChannelDimension.FIRST`):242 The channel dimension format for the output image. Can be one of:243 - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.244 - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.245 - Unset: Use the channel dimension format of the input image.246 input_data_format (`ChannelDimension` or `str`, *optional*):247 The channel dimension format for the input image. If unset, the channel dimension format is inferred248 from the input image. Can be one of:249 - `"channels_first"` or `ChannelDimension.FIRST`: image in (num_channels, height, width) format.250 - `"channels_last"` or `ChannelDimension.LAST`: image in (height, width, num_channels) format.251 - `"none"` or `ChannelDimension.NONE`: image in (height, width) format.252 """253 do_resize = do_resize if do_resize is not None else self.do_resize254 crop_pct = crop_pct if crop_pct is not None else self.crop_pct255 resample = resample if resample is not None else self.resample256 do_rescale = do_rescale if do_rescale is not None else self.do_rescale257 rescale_factor = rescale_factor if rescale_factor is not None else self.rescale_factor258 do_normalize = do_normalize if do_normalize is not None else self.do_normalize259 image_mean = image_mean if image_mean is not None else self.image_mean260 image_std = image_std if image_std is not None else self.image_std261 262 size = size if size is not None else self.size263 size = get_size_dict(size, default_to_square=False)264 265 images = make_flat_list_of_images(images)266 267 if not valid_images(images):268 raise ValueError(269 "Invalid image type. Must be of type PIL.Image.Image, numpy.ndarray, "270 "torch.Tensor, tf.Tensor or jax.ndarray."271 )272 273 validate_preprocess_arguments(274 do_rescale=do_rescale,275 rescale_factor=rescale_factor,276 do_normalize=do_normalize,277 image_mean=image_mean,278 image_std=image_std,279 do_resize=do_resize,280 size=size,281 resample=resample,282 )283 284 # All transformations expect numpy arrays.285 images = [to_numpy_array(image) for image in images]286 287 if do_rescale and is_scaled_image(images[0]):288 logger.warning_once(289 "It looks like you are trying to rescale already rescaled images. If the input"290 " images have pixel values between 0 and 1, set `do_rescale=False` to avoid rescaling them again."291 )292 293 if input_data_format is None:294 # We assume that all images have the same channel dimension format.295 input_data_format = infer_channel_dimension_format(images[0])296 297 if do_resize:298 images = [299 self.resize(300 image=image, size=size, crop_pct=crop_pct, resample=resample, input_data_format=input_data_format301 )302 for image in images303 ]304 305 if do_rescale:306 images = [307 self.rescale(image=image, scale=rescale_factor, input_data_format=input_data_format)308 for image in images309 ]310 311 if do_normalize:312 images = [313 self.normalize(image=image, mean=image_mean, std=image_std, input_data_format=input_data_format)314 for image in images315 ]316 317 images = [318 to_channel_dimension_format(image, data_format, input_channel_dim=input_data_format) for image in images319 ]320 321 data = {"pixel_values": images}322 return BatchFeature(data=data, tensor_type=return_tensors)323 324 325__all__ = ["ConvNextImageProcessor"]326 