• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 Huawei Technologies Co., Ltd
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 at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# 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 and
13# limitations under the License.
14# ==============================================================================
15"""
16The module vision.py_transforms is mainly implemented based on Python PIL, which
17provides many kinds of image augmentation methods and conversion methods between
18PIL image and numpy.ndarray. For users who prefer using Python PIL in computer vision
19tasks, this module is a good choice to process images. Users can also self-define
20their own augmentation methods with Python PIL.
21"""
22import numbers
23import random
24
25import numpy as np
26from PIL import Image
27
28import mindspore.dataset.transforms.py_transforms as py_transforms
29from . import py_transforms_util as util
30from .c_transforms import parse_padding
31from .validators import check_prob, check_center_crop, check_five_crop, check_resize_interpolation, check_random_resize_crop, \
32    check_normalize_py, check_normalizepad_py, check_random_crop, check_random_color_adjust, check_random_rotation, \
33    check_ten_crop, check_num_channels, check_pad, check_rgb_to_hsv, check_hsv_to_rgb, \
34    check_random_perspective, check_random_erasing, check_cutout, check_linear_transform, check_random_affine, \
35    check_mix_up, check_positive_degrees, check_uniform_augment_py, check_auto_contrast, check_rgb_to_bgr, \
36    check_adjust_gamma
37from .utils import Inter, Border
38from .py_transforms_util import is_pil
39
40DE_PY_INTER_MODE = {Inter.NEAREST: Image.NEAREST,
41                    Inter.ANTIALIAS: Image.ANTIALIAS,
42                    Inter.LINEAR: Image.LINEAR,
43                    Inter.CUBIC: Image.CUBIC}
44
45DE_PY_BORDER_TYPE = {Border.CONSTANT: 'constant',
46                     Border.EDGE: 'edge',
47                     Border.REFLECT: 'reflect',
48                     Border.SYMMETRIC: 'symmetric'}
49
50
51def not_random(function):
52    """
53    Specify the function as "not random", i.e., it produces deterministic result.
54    A Python function can only be cached after it is specified as "not random".
55    """
56    function.random = False
57    return function
58
59
60class ToTensor(py_transforms.PyTensorOperation):
61    """
62    Convert the input PIL Image or numpy.ndarray of shape (H, W, C) in the range [0, 255] to numpy.ndarray of
63    shape (C, H, W) in the range [0.0, 1.0] with the desired dtype.
64
65    Note:
66        The values in the input image will be rescaled from [0, 255] to [0.0, 1.0].
67        The dtype will be cast to `output_type`.
68        The number of channels remains the same.
69
70    Args:
71        output_type (numpy.dtype, optional): The dtype of the numpy.ndarray output (default=np.float32).
72
73    Raises:
74        TypeError: If the input is not PIL Image or numpy.ndarray.
75        TypeError: If the dimension of input is not 2 or 3.
76
77    Examples:
78        >>> from mindspore.dataset.transforms.py_transforms import Compose
79        >>> # create a list of transformations to be applied to the "image" column of each data row
80        >>> transforms_list = Compose([py_vision.Decode(),
81        ...                            py_vision.RandomHorizontalFlip(0.5),
82        ...                            py_vision.ToTensor()])
83        >>> # apply the transform to dataset through map function
84        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
85        ...                                                 input_columns="image")
86    """
87
88    def __init__(self, output_type=np.float32):
89        self.output_type = output_type
90        self.random = False
91
92    def __call__(self, img):
93        """
94        Call method.
95
96        Args:
97            img (Union[PIL Image, numpy.ndarray]): PIL Image or numpy.ndarray to be type converted.
98
99        Returns:
100            numpy.ndarray, converted numpy.ndarray with desired type.
101        """
102        return util.to_tensor(img, self.output_type)
103
104
105class ToType(py_transforms.PyTensorOperation):
106    """
107    Convert the input numpy.ndarray image to the desired dtype.
108
109    Args:
110        output_type (numpy.dtype): The dtype of the numpy.ndarray output, e.g. numpy.float32.
111
112    Raises:
113        TypeError: If the input is not numpy.ndarray.
114
115    Examples:
116        >>> from mindspore.dataset.transforms.py_transforms import Compose
117        >>> import numpy as np
118        >>> transforms_list =Compose([py_vision.Decode(),
119        ...                           py_vision.RandomHorizontalFlip(0.5),
120        ...                           py_vision.ToTensor(),
121        ...                           py_vision.ToType(np.float32)])
122        >>> # apply the transform to dataset through map function
123        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
124        ...                                                 input_columns="image")
125    """
126
127    def __init__(self, output_type):
128        self.output_type = output_type
129        self.random = False
130
131    def __call__(self, img):
132        """
133        Call method.
134
135        Args:
136            img (numpy.ndarray): numpy.ndarray to be dtype converted.
137
138        Returns:
139            numpy.ndarray, converted numpy.ndarray with desired dtype.
140        """
141        return util.to_type(img, self.output_type)
142
143
144class HWC2CHW(py_transforms.PyTensorOperation):
145    """
146    Transpose the input numpy.ndarray image of shape (H, W, C) to (C, H, W).
147
148    Raises:
149        TypeError: If the input is not numpy.ndarray.
150        TypeError: If the dimension of input is not 3.
151
152    Examples:
153        >>> from mindspore.dataset.transforms.py_transforms import Compose
154        >>> transforms_list = Compose([py_vision.Decode(),
155        ...                            py_vision.HWC2CHW()])
156        >>> # apply the transform to dataset through map function
157        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
158        ...                                                 input_columns="image")
159    """
160
161    def __init__(self):
162        self.random = False
163
164    def __call__(self, img):
165        """
166        Call method.
167
168        Args:
169            img (numpy.ndarray): numpy.ndarray of shape (H, W, C) to be transposed.
170
171        Returns:
172            numpy.ndarray, transposed numpy.ndarray of shape (C, H, W).
173        """
174        return util.hwc_to_chw(img)
175
176
177class ToPIL(py_transforms.PyTensorOperation):
178    """
179    Convert the input decoded numpy.ndarray image to PIL Image.
180
181    Note:
182        The conversion mode will be determined from type according to `PIL.Image.fromarray`.
183
184    Raises:
185        TypeError: If the input is not numpy.ndarray or PIL Image.
186
187    Examples:
188        >>> # data is already decoded, but not in PIL Image format
189        >>> from mindspore.dataset.transforms.py_transforms import Compose
190        >>> transforms_list = Compose([py_vision.ToPIL(),
191        ...                            py_vision.RandomHorizontalFlip(0.5),
192        ...                            py_vision.ToTensor()])
193        >>> # apply the transform to dataset through map function
194        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
195        ...                                                 input_columns="image")
196    """
197
198    def __init__(self):
199        self.random = False
200
201    def __call__(self, img):
202        """
203        Call method.
204
205        Args:
206            img (numpy.ndarray): Decoded numpy.ndarray image to be converted to PIL Image.
207
208        Returns:
209            PIL Image, converted PIL Image.
210        """
211        return util.to_pil(img)
212
213
214class Decode(py_transforms.PyTensorOperation):
215    """
216    Decode the input raw image to PIL Image format in RGB mode.
217
218    Raises:
219        ValueError: If the input is not raw data.
220        ValueError: If the input image is already decoded.
221
222    Examples:
223        >>> from mindspore.dataset.transforms.py_transforms import Compose
224        >>> transforms_list = Compose([py_vision.Decode(),
225        ...                            py_vision.RandomHorizontalFlip(0.5),
226        ...                            py_vision.ToTensor()])
227        >>> # apply the transform to dataset through map function
228        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
229        ...                                                 input_columns="image")
230    """
231
232    def __init__(self):
233        self.random = False
234
235    def __call__(self, img):
236        """
237        Call method.
238
239        Args:
240            img (Bytes-like Object): Raw image data to be decoded.
241
242        Returns:
243            PIL Image, decoded PIL Image in RGB mode.
244        """
245        return util.decode(img)
246
247
248class Normalize(py_transforms.PyTensorOperation):
249    r"""
250    Normalize the input numpy.ndarray image of shape (C, H, W) with the specified mean and standard deviation.
251
252    .. math::
253
254        output_{c} = \frac{input_{c} - mean_{c}}{std_{c}}
255
256    Note:
257        The values of the input image need to be in the range [0.0, 1.0]. If not so, call `ToTensor` first.
258
259    Args:
260        mean (Union[float, sequence]): list or tuple of mean values for each channel, arranged in channel order. The
261            values must be in the range [0.0, 1.0].
262            If a single float is provided, it will be filled to the same length as the channel.
263        std (Union[float, sequence]): list or tuple of standard deviation values for each channel, arranged in channel
264            order. The values must be in the range (0.0, 1.0].
265            If a single float is provided, it will be filled to the same length as the channel.
266
267    Raises:
268        TypeError: If the input is not numpy.ndarray.
269        TypeError: If the dimension of input is not 3.
270        NotImplementedError: If the dtype of input is a subdtype of np.integer.
271        ValueError: If the lengths of the mean and std are not equal.
272        ValueError: If the length of the mean or std is neither equal to the channel length nor 1.
273
274    Examples:
275        >>> from mindspore.dataset.transforms.py_transforms import Compose
276        >>> transforms_list = Compose([py_vision.Decode(),
277        ...                            py_vision.RandomHorizontalFlip(0.5),
278        ...                            py_vision.ToTensor(),
279        ...                            py_vision.Normalize((0.491, 0.482, 0.447), (0.247, 0.243, 0.262))])
280        >>> # apply the transform to dataset through map function
281        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
282        ...                                                 input_columns="image")
283    """
284
285    @check_normalize_py
286    def __init__(self, mean, std):
287        self.mean = mean
288        self.std = std
289        self.random = False
290
291    def __call__(self, img):
292        """
293        Call method.
294
295        Args:
296            img (numpy.ndarray): numpy.ndarray to be normalized.
297
298        Returns:
299            numpy.ndarray, normalized numpy.ndarray.
300        """
301        return util.normalize(img, self.mean, self.std)
302
303
304class NormalizePad(py_transforms.PyTensorOperation):
305    r"""
306    Normalize the input numpy.ndarray image of shape (C, H, W) with the specified mean and standard deviation,
307    then pad an extra channel filled with zeros.
308
309    .. math::
310        output_{c} = \begin{cases}
311        \frac{input_{c} - mean_{c}}{std_{c}}, & \text{if} \quad 0 \le c < 3 \text{;}\\
312        0, & \text{if} \quad c = 3 \text{.}
313        \end{cases}
314
315    Note:
316        The values of the input image need to be in the range [0.0, 1.0]. If not so, call `ToTensor` first.
317
318    Args:
319        mean (Union[float, sequence]): list or tuple of mean values for each channel, arranged in channel order. The
320            values must be in the range [0.0, 1.0].
321            If a single float is provided, it will be filled to the same length as the channel.
322        std (Union[float, sequence]): list or tuple of standard deviation values for each channel, arranged in channel
323            order. The values must be in the range (0.0, 1.0].
324            If a single float is provided, it will be filled to the same length as the channel.
325        dtype (str): The dtype of the numpy.ndarray output when `pad_channel` is set True. Only "float32" and "float16"
326            are supported (default="float32").
327
328    Raises:
329        TypeError: If the input is not numpy.ndarray.
330        TypeError: If the dimension of input is not 3.
331        NotImplementedError: If the dtype of input is a subdtype of np.integer.
332        ValueError: If the length of the mean and std are not equal.
333        ValueError: If the length of the mean or std is neither equal to the channel length nor 1.
334
335    Examples:
336        >>> from mindspore.dataset.transforms.py_transforms import Compose
337        >>> transforms_list = Compose([py_vision.Decode(),
338        ...                            py_vision.RandomHorizontalFlip(0.5),
339        ...                            py_vision.ToTensor(),
340        ...                            py_vision.NormalizePad((0.491, 0.482, 0.447), (0.247, 0.243, 0.262), "float32")])
341        >>> # apply the transform to dataset through map function
342        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
343        ...                                                 input_columns="image")
344    """
345
346    @check_normalizepad_py
347    def __init__(self, mean, std, dtype="float32"):
348        self.mean = mean
349        self.std = std
350        self.dtype = dtype
351        self.random = False
352
353    def __call__(self, img):
354        """
355        Call method.
356
357        Args:
358            img (numpy.ndarray): numpy.ndarray to be normalized and padded.
359
360        Returns:
361            numpy.ndarray, normalized and padded numpy.ndarray.
362        """
363        return util.normalize(img, self.mean, self.std, pad_channel=True, dtype=self.dtype)
364
365
366class RandomCrop(py_transforms.PyTensorOperation):
367    """
368    Crop the input PIL Image at a random location with the specified size.
369
370    Args:
371        size (Union[int, sequence]): The output size of the cropped image.
372            If size is an integer, a square of size (size, size) is returned.
373            If size is a sequence of length 2, it should be in shape of (height, width).
374        padding (Union[int, sequence], optional): Padding on each border of the image (default=None).
375            If padding is not None, pad the image before cropping.
376            If a single number is provided, pad all borders with this value.
377            If a sequence of length 2 is provided, pad the left/top border
378            with the first value and right/bottom border with the second value.
379            If a sequence of length 4 is provided, pad the left, top, right and bottom borders respectively.
380        pad_if_needed (bool, optional): Pad the image if either side is smaller than
381            the given output size (default=False).
382        fill_value (Union[int, tuple], optional): Pixel fill value to pad the borders when padding_mode is
383            Border.CONSTANT (default=0). If a tuple of length 3 is provided, it is used to fill R, G, B
384            channels respectively.
385        padding_mode (Border, optional): The method of padding (default=Border.CONSTANT). It can be any of
386            [Border.CONSTANT, Border.EDGE, Border.REFLECT, Border.SYMMETRIC].
387
388            - Border.CONSTANT, means to pad with given constant values.
389
390            - Border.EDGE, means to pad with the last value at the edge.
391
392            - Border.REFLECT, means to pad with reflection of image omitting the last value at the edge.
393
394            - Border.SYMMETRIC, means to pad with reflection of image repeating the last value at the edge.
395
396    Examples:
397        >>> from mindspore.dataset.transforms.py_transforms import Compose
398        >>> transforms_list = Compose([py_vision.Decode(),
399        ...                            py_vision.RandomCrop(224),
400        ...                            py_vision.ToTensor()])
401        >>> # apply the transform to dataset through map function
402        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
403        ...                                                 input_columns="image")
404    """
405
406    @check_random_crop
407    def __init__(self, size, padding=None, pad_if_needed=False, fill_value=0, padding_mode=Border.CONSTANT):
408        if padding is None:
409            padding = (0, 0, 0, 0)
410        else:
411            padding = parse_padding(padding)
412        self.size = size
413        self.padding = padding
414        self.pad_if_needed = pad_if_needed
415        self.fill_value = fill_value
416        self.padding_mode = DE_PY_BORDER_TYPE[padding_mode]
417
418    def __call__(self, img):
419        """
420        Call method.
421
422        Args:
423            img (PIL Image): Image to be randomly cropped.
424
425        Returns:
426            PIL Image, cropped image.
427        """
428        return util.random_crop(img, self.size, self.padding, self.pad_if_needed,
429                                self.fill_value, self.padding_mode)
430
431
432class RandomHorizontalFlip(py_transforms.PyTensorOperation):
433    """
434    Randomly flip the input image horizontally with a given probability.
435
436    Args:
437        prob (float, optional): Probability of the image to be horizontally flipped (default=0.5).
438
439    Examples:
440        >>> from mindspore.dataset.transforms.py_transforms import Compose
441        >>> transforms_list = Compose([py_vision.Decode(),
442        ...                            py_vision.RandomHorizontalFlip(0.5),
443        ...                            py_vision.ToTensor()])
444        >>> # apply the transform to dataset through map function
445        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
446        ...                                                 input_columns="image")
447    """
448
449    @check_prob
450    def __init__(self, prob=0.5):
451        self.prob = prob
452
453    def __call__(self, img):
454        """
455        Call method.
456
457        Args:
458            img (PIL Image): Image to be horizontally flipped.
459
460        Returns:
461            PIL Image, randomly horizontally flipped image.
462        """
463        return util.random_horizontal_flip(img, self.prob)
464
465
466class RandomVerticalFlip(py_transforms.PyTensorOperation):
467    """
468    Randomly flip the input image vertically with a given probability.
469
470    Args:
471        prob (float, optional): Probability of the image to be vertically flipped (default=0.5).
472
473    Examples:
474        >>> from mindspore.dataset.transforms.py_transforms import Compose
475        >>> transforms_list = Compose([py_vision.Decode(),
476        ...                            py_vision.RandomVerticalFlip(0.5),
477        ...                            py_vision.ToTensor()])
478        >>> # apply the transform to dataset through map function
479        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
480        ...                                                 input_columns="image")
481    """
482
483    @check_prob
484    def __init__(self, prob=0.5):
485        self.prob = prob
486
487    def __call__(self, img):
488        """
489        Call method.
490
491        Args:
492            img (PIL Image): Image to be vertically flipped.
493
494        Returns:
495            PIL Image, randomly vertically flipped image.
496        """
497        return util.random_vertical_flip(img, self.prob)
498
499
500class Resize(py_transforms.PyTensorOperation):
501    """
502    Resize the input PIL Image to the given size.
503
504    Args:
505        size (Union[int, sequence]): The output size of the image.
506            If size is an integer, the smaller edge of the image will be resized to this
507            value, keeping the image aspect ratio the same.
508            If size is a sequence of length 2, it should be in shape of (height, width).
509        interpolation (Inter, optional): Image interpolation mode (default=Inter.BILINEAR).
510            It can be any of [Inter.NEAREST, Inter.ANTIALIAS, Inter.BILINEAR, Inter.BICUBIC].
511
512            - Inter.NEAREST, nearest-neighbor interpolation.
513
514            - Inter.ANTIALIAS, antialias interpolation.
515
516            - Inter.BILINEAR, bilinear interpolation.
517
518            - Inter.BICUBIC, bicubic interpolation.
519
520    Examples:
521        >>> from mindspore.dataset.transforms.py_transforms import Compose
522        >>> transforms_list = Compose([py_vision.Decode(),
523        ...                            py_vision.Resize(256),
524        ...                            py_vision.ToTensor()])
525        >>> # apply the transform to dataset through map function
526        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
527        ...                                                 input_columns="image")
528    """
529
530    @check_resize_interpolation
531    def __init__(self, size, interpolation=Inter.BILINEAR):
532        self.size = size
533        self.interpolation = DE_PY_INTER_MODE[interpolation]
534        self.random = False
535
536    def __call__(self, img):
537        """
538        Call method.
539
540        Args:
541            img (PIL Image): Image to be resized.
542
543        Returns:
544            PIL Image, resized image.
545        """
546        return util.resize(img, self.size, self.interpolation)
547
548
549class RandomResizedCrop(py_transforms.PyTensorOperation):
550    """
551    Randomly crop the image and resize it to a given size.
552
553    Args:
554        size (Union[int, sequence]): The size of the output image.
555            If size is an integer, a square of size (size, size) is returned.
556            If size is a sequence of length 2, it should be in shape of (height, width).
557        scale (Union[list, tuple], optional): Respective size range of the original image to be cropped
558            in shape of (min, max) (default=(0.08, 1.0)).
559        ratio (Union[list, tuple], optional): Aspect ratio range to be cropped
560            in shape of (min, max) (default=(3./4., 4./3.)).
561        interpolation (Inter, optional): Image interpolation mode (default=Inter.BILINEAR).
562            It can be any of [Inter.NEAREST, Inter.ANTIALIAS, Inter.BILINEAR, Inter.BICUBIC].
563
564            - Inter.NEAREST, nearest-neighbor interpolation.
565
566            - Inter.ANTIALIAS, antialias interpolation.
567
568            - Inter.BILINEAR, bilinear interpolation.
569
570            - Inter.BICUBIC, bicubic interpolation.
571
572        max_attempts (int, optional): The maximum number of attempts to propose a valid
573            crop area (default=10). If exceeded, fall back to use center crop instead.
574
575    Examples:
576        >>> from mindspore.dataset.transforms.py_transforms import Compose
577        >>> transforms_list = Compose([py_vision.Decode(),
578        ...                            py_vision.RandomResizedCrop(224),
579        ...                            py_vision.ToTensor()])
580        >>> # apply the transform to dataset through map function
581        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
582        ...                                                 input_columns="image")
583    """
584
585    @check_random_resize_crop
586    def __init__(self, size, scale=(0.08, 1.0), ratio=(3. / 4., 4. / 3.),
587                 interpolation=Inter.BILINEAR, max_attempts=10):
588        self.size = size
589        self.scale = scale
590        self.ratio = ratio
591        self.interpolation = DE_PY_INTER_MODE[interpolation]
592        self.max_attempts = max_attempts
593
594    def __call__(self, img):
595        """
596        Call method.
597
598        Args:
599            img (PIL Image): Image to be randomly cropped and resized.
600
601        Returns:
602            PIL Image, randomly cropped and resized image.
603        """
604        return util.random_resize_crop(img, self.size, self.scale, self.ratio,
605                                       self.interpolation, self.max_attempts)
606
607
608class CenterCrop(py_transforms.PyTensorOperation):
609    """
610    Crop the central region of the input PIL Image with the given size.
611
612    Args:
613        size (Union[int, sequence]): The output size of the cropped image.
614            If size is an integer, a square of size (size, size) is returned.
615            If size is a sequence of length 2, it should be in shape of (height, width).
616
617    Examples:
618        >>> from mindspore.dataset.transforms.py_transforms import Compose
619        >>> transforms_list = Compose([py_vision.Decode(),
620        ...                            py_vision.CenterCrop(64),
621        ...                            py_vision.ToTensor()])
622        >>> # apply the transform to dataset through map function
623        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
624        ...                                                 input_columns="image")
625    """
626
627    @check_center_crop
628    def __init__(self, size):
629        self.size = size
630        self.random = False
631
632    def __call__(self, img):
633        """
634        Call method.
635
636        Args:
637            img (PIL Image): Image to be center cropped.
638
639        Returns:
640            PIL Image, cropped image.
641        """
642        return util.center_crop(img, self.size)
643
644
645class RandomColorAdjust(py_transforms.PyTensorOperation):
646    """
647    Randomly adjust the brightness, contrast, saturation, and hue of the input PIL Image.
648
649    Args:
650        brightness (Union[float, tuple], optional): Brightness adjustment factor,
651            which must be non negative (default=(1, 1)).
652            If brightness is a float, the factor is uniformly chosen in range of [max(0, 1-brightness), 1+brightness].
653            If brightness is a sequence of length 2, it should be in shape of [min, max].
654        contrast (Union[float, tuple], optional): Contrast adjustment factor,
655            which must be non negative (default=(1, 1)).
656            If contrast is a float, the factor is uniformly chosen in range of [max(0, 1-contrast), 1+contrast].
657            If contrast is a sequence of length 2, it should be in shape of [min, max].
658        saturation (Union[float, tuple], optional): Saturation adjustment factor,
659            which must be non negative(default=(1, 1)).
660            If saturation is a float, the factor is uniformly chosen in range of [max(0, 1-saturation), 1+saturation].
661            If saturation is a sequence of length 2, it should be in shape of [min, max].
662        hue (Union[float, tuple], optional): Hue adjustment factor (default=(0, 0)).
663            If hue is a float, the range will be [-hue, hue], where 0 <= hue <= 0.5.
664            If hue is a sequence of length 2, it should be in shape of [min, max], where -0.5 <= min <= max <= 0.5.
665
666    Examples:
667        >>> from mindspore.dataset.transforms.py_transforms import Compose
668        >>> transforms_list = Compose([py_vision.Decode(),
669        ...                            py_vision.RandomColorAdjust(0.4, 0.4, 0.4, 0.1),
670        ...                            py_vision.ToTensor()])
671        >>> # apply the transform to dataset through map function
672        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
673        ...                                                 input_columns="image")
674    """
675
676    @check_random_color_adjust
677    def __init__(self, brightness=(1, 1), contrast=(1, 1), saturation=(1, 1), hue=(0, 0)):
678        self.brightness = brightness
679        self.contrast = contrast
680        self.saturation = saturation
681        self.hue = hue
682
683    def __call__(self, img):
684        """
685        Call method.
686
687        Args:
688            img (PIL image): Image to be randomly color adjusted.
689
690        Returns:
691            PIL Image, randomly color adjusted image.
692        """
693        return util.random_color_adjust(img, self.brightness, self.contrast, self.saturation, self.hue)
694
695
696class RandomRotation(py_transforms.PyTensorOperation):
697    """
698    Rotate the input PIL Image by a random angle.
699
700    Note:
701        See https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.rotate.
702
703    Args:
704        degrees (Union[int, float, sequence]): Range of random rotation degrees.
705            If `degrees` is a number, the range will be converted to (-degrees, degrees).
706            If `degrees` is a sequence of length 2, it should be in shape of (min, max).
707        resample (Inter, optional): An optional resampling filter (default=Inter.NEAREST).
708            If the image is in mode of "1" or "P", it is set to Inter.NEAREST by default.
709            It can be any of [Inter.NEAREST, Inter.ANTIALIAS, Inter.BILINEAR, Inter.BICUBIC].
710
711            - Inter.NEAREST, nearest-neighbor interpolation.
712
713            - Inter.ANTIALIAS, antialias interpolation.
714
715            - Inter.BILINEAR, bilinear interpolation.
716
717            - Inter.BICUBIC, bicubic interpolation.
718
719        expand (bool, optional): Optional expansion flag (default=False).
720            If set to True, expand the output image to make it large enough to hold the entire rotated image.
721            If set to False, keep the output image the same size as the input.
722            Note that the expand flag assumes rotation around the center and no translation.
723        center (tuple, optional): Optional center of rotation, which must be a tuple of length 2 (default=None).
724            Origin is the top left corner. Default None means to set the center of the image.
725        fill_value (int or tuple, optional): Pixel fill value for the area outside the rotated image (default=0).
726            If fill_value is a tuple of length 3, it is used to fill R, G, B channels respectively.
727            If fill_value is an integer, it is used to fill all RGB channels.
728
729    Examples:
730        >>> from mindspore.dataset.transforms.py_transforms import Compose
731        >>> transforms_list = Compose([py_vision.Decode(),
732        ...                            py_vision.RandomRotation(30),
733        ...                            py_vision.ToTensor()])
734        >>> # apply the transform to dataset through map function
735        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
736        ...                                                 input_columns="image")
737    """
738
739    @check_random_rotation
740    def __init__(self, degrees, resample=Inter.NEAREST, expand=False, center=None, fill_value=0):
741        self.degrees = degrees
742        self.resample = DE_PY_INTER_MODE[resample]
743        self.expand = expand
744        self.center = center
745        self.fill_value = fill_value
746
747    def __call__(self, img):
748        """
749        Call method.
750
751        Args:
752            img (PIL Image): Image to be randomly rotated.
753
754        Returns:
755            PIL Image, randomly rotated image.
756        """
757        return util.random_rotation(img, self.degrees, self.resample, self.expand, self.center, self.fill_value)
758
759
760class FiveCrop(py_transforms.PyTensorOperation):
761    """
762    Crop the given image into one central crop and four corners.
763
764    Args:
765        size (Union[int, sequence]): The output size of the cropped images.
766            If size is an integer, a square of size (size, size) is returned.
767            If size is a sequence of length 2, it should be in shape of (height, width).
768
769    Examples:
770        >>> from mindspore.dataset.transforms.py_transforms import Compose
771        >>> transforms_list = Compose([py_vision.Decode(),
772        ...                            py_vision.FiveCrop(size=200),
773        ...                            # 4D stack of 5 images
774        ...                            lambda *images: numpy.stack([py_vision.ToTensor()(image) for image in images])])
775        >>> # apply the transform to dataset through map function
776        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
777        ...                                                 input_columns="image")
778    """
779
780    @check_five_crop
781    def __init__(self, size):
782        self.size = size
783        self.random = False
784
785    def __call__(self, img):
786        """
787        Call method.
788
789        Args:
790            img (PIL Image): Image to be cropped.
791
792        Returns:
793            tuple, a tuple of five PIL Image in order of top_left, top_right, bottom_left, bottom_right, center.
794        """
795        return util.five_crop(img, self.size)
796
797
798class TenCrop(py_transforms.PyTensorOperation):
799    """
800    Crop the given image into one central crop and four corners plus the flipped version of these.
801
802    Args:
803        size (Union[int, sequence]): The output size of the cropped images.
804            If size is an integer, a square of size (size, size) is returned.
805            If size is a sequence of length 2, it should be in shape of (height, width).
806        use_vertical_flip (bool, optional): Whether to flip the image vertically,
807            otherwise horizontally (default=False).
808
809    Examples:
810        >>> import numpy
811        >>> from mindspore.dataset.transforms.py_transforms import Compose
812        >>> transforms_list = Compose([py_vision.Decode(),
813        ...                            py_vision.TenCrop(size=200),
814        ...                            # 4D stack of 10 images
815        ...                            lambda *images: numpy.stack([py_vision.ToTensor()(image) for image in images])])
816        >>> # apply the transform to dataset through map function
817        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
818        ...                                                 input_columns="image")
819    """
820
821    @check_ten_crop
822    def __init__(self, size, use_vertical_flip=False):
823        if isinstance(size, int):
824            size = (size, size)
825        self.size = size
826        self.use_vertical_flip = use_vertical_flip
827        self.random = False
828
829    def __call__(self, img):
830        """
831        Call method.
832
833        Args:
834            img (PIL Image): Image to be cropped.
835
836        Returns:
837            tuple, a tuple of 10 PIL Image, in order of top_left, top_right, bottom_left, bottom_right, center
838                of the original image and top_left, top_right, bottom_left, bottom_right, center of the flipped image.
839        """
840        return util.ten_crop(img, self.size, self.use_vertical_flip)
841
842
843class Grayscale(py_transforms.PyTensorOperation):
844    """
845    Convert the input PIL Image to grayscale.
846
847    Args:
848        num_output_channels (int): Number of channels of the output grayscale image, which can be 1 or 3 (default=1).
849            If num_output_channels is 3, the returned image will have 3 identical RGB channels.
850
851    Examples:
852        >>> from mindspore.dataset.transforms.py_transforms import Compose
853        >>> transforms_list = Compose([py_vision.Decode(),
854        ...                            py_vision.Grayscale(3),
855        ...                            py_vision.ToTensor()])
856        >>> # apply the transform to dataset through map function
857        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
858        ...                                                 input_columns="image")
859    """
860
861    @check_num_channels
862    def __init__(self, num_output_channels=1):
863        self.num_output_channels = num_output_channels
864        self.random = False
865
866    def __call__(self, img):
867        """
868        Call method.
869
870        Args:
871            img (PIL Image): Image to be converted to grayscale.
872
873        Returns:
874            PIL Image, converted grayscale image.
875        """
876        return util.grayscale(img, num_output_channels=self.num_output_channels)
877
878
879class RandomGrayscale(py_transforms.PyTensorOperation):
880    """
881    Randomly convert the input image into grayscale with a given probability.
882
883    Args:
884        prob (float, optional): Probability of the image being converted to grayscale (default=0.1).
885
886    Examples:
887        >>> from mindspore.dataset.transforms.py_transforms import Compose
888        >>> transforms_list = Compose([py_vision.Decode(),
889        ...                            py_vision.RandomGrayscale(0.3),
890        ...                            py_vision.ToTensor()])
891        >>> # apply the transform to dataset through map function
892        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
893        ...                                                 input_columns="image")
894    """
895
896    @check_prob
897    def __init__(self, prob=0.1):
898        self.prob = prob
899
900    def __call__(self, img):
901        """
902        Call method.
903
904        Args:
905            img (PIL Image): Image to be randomly converted to grayscale.
906
907        Returns:
908            PIL Image, randomly converted grayscale image, which has the same number of channels as the input image.
909                If input image has 1 channel, the output grayscale image will have 1 channel.
910                If input image has 3 channels, the output grayscale image will have 3 identical channels.
911        """
912        if img.mode == 'L':
913            num_output_channels = 1
914        else:
915            num_output_channels = 3
916
917        if self.prob > random.random():
918            return util.grayscale(img, num_output_channels=num_output_channels)
919        return img
920
921
922class Pad(py_transforms.PyTensorOperation):
923    """
924    Pad the input image on all sides with the given padding parameters.
925
926    Args:
927        padding (Union[int, sequence]): The number of pixels padded on the image borders.
928            If a single number is provided, pad all borders with this value.
929            If a sequence of length 2 is provided, pad the left and top with the
930            first value and the right and bottom with the second value.
931            If a sequence of length 4 is provided, pad the left, top, right and bottom respectively.
932        fill_value (Union[int, tuple], optional): Pixel fill value to pad the borders,
933            only valid when padding_mode is Border.CONSTANT (default=0).
934            If fill_value is an integer, it is used for all RGB channels.
935            If fill_value is a tuple of length 3, it is used to fill R, G, B channels respectively.
936        padding_mode (Border, optional): The method of padding (default=Border.CONSTANT).
937            It can be any of [Border.CONSTANT, Border.EDGE, Border.REFLECT, Border.SYMMETRIC].
938
939            - Border.CONSTANT, pads with a constant value.
940
941            - Border.EDGE, pads with the last value at the edge of the image.
942
943            - Border.REFLECT, pads with reflection of the image omitting the last value on the edge.
944
945            - Border.SYMMETRIC, pads with reflection of the image repeating the last value on the edge.
946
947    Examples:
948        >>> from mindspore.dataset.transforms.py_transforms import Compose
949        >>> transforms_list = Compose([py_vision.Decode(),
950        ...                            # adds 10 pixels (default black) to each border of the image
951        ...                            py_vision.Pad(padding=10),
952        ...                            py_vision.ToTensor()])
953        >>> # apply the transform to dataset through map function
954        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
955        ...                                                 input_columns="image")
956    """
957
958    @check_pad
959    def __init__(self, padding, fill_value=0, padding_mode=Border.CONSTANT):
960        parse_padding(padding)
961
962        self.padding = padding
963        self.fill_value = fill_value
964        self.padding_mode = DE_PY_BORDER_TYPE[padding_mode]
965        self.random = False
966
967    def __call__(self, img):
968        """
969        Call method.
970
971        Args:
972            img (PIL Image): Image to be padded.
973
974        Returns:
975            PIL Image, padded image.
976        """
977        return util.pad(img, self.padding, self.fill_value, self.padding_mode)
978
979
980class RandomPerspective(py_transforms.PyTensorOperation):
981    """
982    Randomly apply perspective transformation to the input PIL Image with a given probability.
983
984    Args:
985        distortion_scale (float, optional): The scale of distortion, in range of [0, 1] (default=0.5).
986        prob (float, optional): Probability of the image being applied perspective transformation (default=0.5).
987        interpolation (Inter, optional): Image interpolation mode (default=Inter.BICUBIC).
988            It can be any of [Inter.BILINEAR, Inter.NEAREST, Inter.BICUBIC].
989
990            - Inter.BILINEAR, bilinear interpolation.
991
992            - Inter.NEAREST, nearest-neighbor interpolation.
993
994            - Inter.BICUBIC, bicubic interpolation.
995
996    Examples:
997        >>> from mindspore.dataset.transforms.py_transforms import Compose
998        >>> transforms_list = Compose([py_vision.Decode(),
999        ...                            py_vision.RandomPerspective(prob=0.1),
1000        ...                            py_vision.ToTensor()])
1001        >>> # apply the transform to dataset through map function
1002        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1003        ...                                                 input_columns="image")
1004    """
1005
1006    @check_random_perspective
1007    def __init__(self, distortion_scale=0.5, prob=0.5, interpolation=Inter.BICUBIC):
1008        self.distortion_scale = distortion_scale
1009        self.prob = prob
1010        self.interpolation = DE_PY_INTER_MODE[interpolation]
1011
1012    def __call__(self, img):
1013        """
1014        Call method.
1015
1016        Args:
1017            img (PIL Image): Image to be applied randomly perspective transformation.
1018
1019        Returns:
1020            PIL Image, image applied randomly perspective transformation.
1021        """
1022        if not is_pil(img):
1023            raise ValueError("Input image should be a Pillow image.")
1024        if self.prob > random.random():
1025            start_points, end_points = util.get_perspective_params(
1026                img, self.distortion_scale)
1027            return util.perspective(img, start_points, end_points, self.interpolation)
1028        return img
1029
1030
1031class RandomErasing(py_transforms.PyTensorOperation):
1032    """
1033    Randomly erase the pixels within a random selected rectangle region with a given probability.
1034
1035    See Zhun Zhong et al. 'Random Erasing Data Augmentation' 2017 on https://arxiv.org/pdf/1708.04896.pdf
1036
1037    Args:
1038        prob (float, optional): Probability of the image being randomly erased (default=0.5).
1039        scale (sequence of floats, optional): Range of the relative erase area to the
1040            original image (default=(0.02, 0.33)).
1041        ratio (sequence, optional): Range of aspect ratio of the erased area (default=(0.3, 3.3)).
1042        value (Union[int, sequence, str]): Erasing value (default=0).
1043            If value is a single integer, it is used to erase all pixels.
1044            If value is a sequence of length 3, it is used to erase R, G, B channels respectively.
1045            If value is a string of 'random', each pixel will be erased with a random value obtained
1046            from a standard normal distribution.
1047        inplace (bool, optional): Whether to apply this transformation inplace (default=False).
1048        max_attempts (int, optional): The maximum number of attempts to propose a valid
1049            area to be erased (default=10). If exceeded, return the original image.
1050
1051    Examples:
1052        >>> from mindspore.dataset.transforms.py_transforms import Compose
1053        >>> transforms_list = Compose([py_vision.Decode(),
1054        ...                            py_vision.ToTensor(),
1055        ...                            py_vision.RandomErasing(value='random')])
1056        >>> # apply the transform to dataset through map function
1057        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1058        ...                                                 input_columns="image")
1059    """
1060
1061    @check_random_erasing
1062    def __init__(self, prob=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False, max_attempts=10):
1063        self.prob = prob
1064        self.scale = scale
1065        self.ratio = ratio
1066        self.value = value
1067        self.inplace = inplace
1068        self.max_attempts = max_attempts
1069
1070    def __call__(self, np_img):
1071        """
1072        Call method.
1073
1074        Args:
1075            np_img (numpy.ndarray): image in shape of (C, H, W) to be randomly erased.
1076
1077        Returns:
1078            numpy.ndarray, erased image.
1079        """
1080        bounded = True
1081        if self.prob > random.random():
1082            i, j, erase_h, erase_w, erase_value = util.get_erase_params(np_img, self.scale, self.ratio,
1083                                                                        self.value, bounded, self.max_attempts)
1084            return util.erase(np_img, i, j, erase_h, erase_w, erase_value, self.inplace)
1085        return np_img
1086
1087
1088class Cutout(py_transforms.PyTensorOperation):
1089    """
1090    Randomly apply a given number of square patches of zeros to a location within the input
1091    numpy.ndarray image of shape (C, H, W).
1092
1093    See Terrance DeVries and Graham W. Taylor 'Improved Regularization of Convolutional Neural Networks with Cutout'
1094    2017 on https://arxiv.org/pdf/1708.04552.pdf
1095
1096    Args:
1097        length (int): The side length of each square patch.
1098        num_patches (int, optional): Number of patches to be applied to the image (default=1).
1099
1100    Examples:
1101        >>> from mindspore.dataset.transforms.py_transforms import Compose
1102        >>> transforms_list = Compose([py_vision.Decode(),
1103        ...                            py_vision.ToTensor(),
1104        ...                            py_vision.Cutout(80)])
1105        >>> # apply the transform to dataset through map function
1106        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1107        ...                                                 input_columns="image")
1108    """
1109
1110    @check_cutout
1111    def __init__(self, length, num_patches=1):
1112        self.length = length
1113        self.num_patches = num_patches
1114        self.random = False
1115
1116    def __call__(self, np_img):
1117        """
1118        Call method.
1119
1120        Args:
1121            np_img (numpy.ndarray): Image in shape of (C, H, W) to be cut out.
1122
1123        Returns:
1124            numpy.ndarray, image cut out.
1125        """
1126        if not isinstance(np_img, np.ndarray):
1127            raise TypeError(
1128                "img should be NumPy array. Got {}.".format(type(np_img)))
1129        if np_img.ndim != 3:
1130            raise TypeError(
1131                'img dimension should be 3. Got {}.'.format(np_img.ndim))
1132
1133        _, image_h, image_w = np_img.shape
1134        scale = (self.length * self.length) / (image_h * image_w)
1135        bounded = False
1136
1137        for _ in range(self.num_patches):
1138            i, j, erase_h, erase_w, erase_value = util.get_erase_params(np_img, (scale, scale), (1, 1), 0, bounded,
1139                                                                        1)
1140            np_img = util.erase(np_img, i, j, erase_h, erase_w, erase_value)
1141        return np_img
1142
1143
1144class LinearTransformation(py_transforms.PyTensorOperation):
1145    r"""
1146    Transform the input numpy.ndarray image with a given square transformation matrix and a mean vector.
1147    It will first flatten the input image and subtract the mean vector from it, then compute the dot
1148    product with the transformation matrix, finally reshape it back to its original shape.
1149
1150    Args:
1151        transformation_matrix (numpy.ndarray): A square transformation matrix in shape of (D, D), where
1152            :math:`D = C \times H \times W`.
1153        mean_vector (numpy.ndarray): A mean vector in shape of (D,), where :math:`D = C \times H \times W`.
1154
1155    Examples:
1156        >>> from mindspore.dataset.transforms.py_transforms import Compose
1157        >>> import numpy as np
1158        >>> height, width = 32, 32
1159        >>> dim = 3 * height * width
1160        >>> transformation_matrix = np.ones([dim, dim])
1161        >>> mean_vector = np.zeros(dim)
1162        >>> transforms_list = Compose([py_vision.Decode(),
1163        ...                            py_vision.Resize((height,width)),
1164        ...                            py_vision.ToTensor(),
1165        ...                            py_vision.LinearTransformation(transformation_matrix, mean_vector)])
1166        >>> # apply the transform to dataset through map function
1167        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1168        ...                                                 input_columns="image")
1169    """
1170
1171    @check_linear_transform
1172    def __init__(self, transformation_matrix, mean_vector):
1173        self.transformation_matrix = transformation_matrix
1174        self.mean_vector = mean_vector
1175        self.random = False
1176
1177    def __call__(self, np_img):
1178        """
1179        Call method.
1180
1181        Args:
1182            np_img (numpy.ndarray): Image in shape of (C, H, W) to be linearly transformed.
1183
1184        Returns:
1185            numpy.ndarray, linearly transformed image.
1186        """
1187        return util.linear_transform(np_img, self.transformation_matrix, self.mean_vector)
1188
1189
1190class RandomAffine(py_transforms.PyTensorOperation):
1191    """
1192    Apply random affine transformation to the input PIL Image.
1193
1194    Args:
1195        degrees (Union[int, float, sequence]): Range of degrees to select from.
1196            If `degrees` is a number, the range will be (-degrees, degrees).
1197            If `degrees` is a sequence, it should be in shape of (min, max).
1198        translate (sequence, optional): Maximum absolute fraction sequence in shape of (tx, ty)
1199            for horizontal and vertical translations. The horizontal and vertical shifts are randomly
1200            selected in the range (-tx * width, tx * width) and (-ty * height, ty * height) respectively.
1201            (default=None, no translation will be applied).
1202        scale (sequence, optional): Scaling factor interval (default=None, keep original scale).
1203        shear (Union[int, float, sequence], optional): Range of shear factor to select from.
1204            If shear is an integer, a shear parallel to the X axis in the range (-shear, shear) will be applied.
1205            If shear is a sequence of length 2, a shear parallel to the X axis in the range (shear[0], shear[1])
1206            will be applied.
1207            If shear is a sequence of length 4, a shear parallel to the X axis in the range (shear[0], shear[1])
1208            and a shear parallel to the Y axis in the range (shear[2], shear[3]) will be applied.
1209            (default=None, no shear will be applied).
1210        resample (Inter, optional): An optional resampling filter (default=Inter.NEAREST).
1211            If the PIL Image is in mode of "1" or "P", it is set to Inter.NEAREST by default.
1212            It can be any of [Inter.BILINEAR, Inter.NEAREST, Inter.BICUBIC].
1213
1214            - Inter.BILINEAR, bilinear interpolation.
1215
1216            - Inter.NEAREST, nearest-neighbor interpolation.
1217
1218            - Inter.BICUBIC, bicubic interpolation.
1219
1220        fill_value (Union[int, tuple], optional): Pixel fill value for the area outside the
1221            transformed image (default=0).
1222            If fill_value is an integer, it is used for all RGB channels.
1223            If fill_value is a tuple of length 3, it is used to fill R, G, B channels respectively.
1224            Only supported with Pillow version > 5.0.0.
1225
1226    Raises:
1227        ValueError: If `degrees` is negative.
1228        ValueError: If translation is not between 0 and 1.
1229        ValueError: If scale is not positive.
1230        ValueError: If shear is a non positive number.
1231        TypeError: If `degrees` is not a number or a sequence of length 2.
1232        TypeError: If translate is defined but not a sequence of length 2.
1233        TypeError: If scale is not a sequence of length 2.
1234        TypeError: If shear is not a sequence of length 2 or 4.
1235        TypeError: If fill_value is not an integer or a tuple of length 3.
1236
1237    Examples:
1238        >>> from mindspore.dataset.transforms.py_transforms import Compose
1239        >>> transforms_list = Compose([py_vision.Decode(),
1240        ...                            py_vision.RandomAffine(degrees=15, translate=(0.1, 0.1), scale=(0.9, 1.1)),
1241        ...                            py_vision.ToTensor()])
1242        >>> # apply the transform to dataset through map function
1243        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1244        ...                                                 input_columns="image")
1245    """
1246
1247    @check_random_affine
1248    def __init__(self, degrees, translate=None, scale=None, shear=None, resample=Inter.NEAREST, fill_value=0):
1249        if shear is not None:
1250            if isinstance(shear, numbers.Number):
1251                shear = (-1 * shear, shear)
1252            else:
1253                if len(shear) == 2:
1254                    shear = [shear[0], shear[1], 0., 0.]
1255                elif len(shear) == 4:
1256                    shear = [s for s in shear]
1257
1258        if isinstance(degrees, numbers.Number):
1259            degrees = (-degrees, degrees)
1260
1261        self.degrees = degrees
1262        self.translate = translate
1263        self.scale_ranges = scale
1264        self.shear = shear
1265        self.resample = DE_PY_INTER_MODE[resample]
1266        self.fill_value = fill_value
1267
1268    def __call__(self, img):
1269        """
1270        Call method.
1271
1272        Args:
1273            img (PIL Image): Image to be randomly affine transformed.
1274
1275        Returns:
1276            PIL Image, randomly affine transformed image.
1277        """
1278
1279        return util.random_affine(img,
1280                                  self.degrees,
1281                                  self.translate,
1282                                  self.scale_ranges,
1283                                  self.shear,
1284                                  self.resample,
1285                                  self.fill_value)
1286
1287
1288class MixUp(py_transforms.PyTensorOperation):
1289    """
1290    Randomly mix up a batch of images together with its labels. Each image will be multiplied by a random
1291    weight lambda generated from the beta distribution and then added to another image multiplied by 1 - lambda.
1292    The same transformation will be applied to their labels with the same value of lambda. Make sure that the
1293    labels are one hot encoded in advance.
1294
1295    Args:
1296        batch_size (int): The number of images in a batch.
1297        alpha (float): The alpha and beta parameter in the beta distribution.
1298        is_single (bool, optional): If True, it will randomly mix up [img(0), ..., img(n-1), img(n)] with
1299            [img1, ..., img(n), img0] in each batch. Otherwise, it will randomly mix up images with the
1300            output of mixing of previous batch of images (Default=True).
1301
1302
1303    Examples:
1304        >>> # Setup multi-batch mixup transformation
1305        >>> transform = [py_vision.MixUp(batch_size=16, alpha=0.2, is_single=False)]
1306        >>> # Apply the transform to the dataset through dataset.map()
1307        >>> image_folder_dataset = image_folder_dataset.map(input_columns="image",
1308        ...                                                 operations=transform)
1309    """
1310
1311    @check_mix_up
1312    def __init__(self, batch_size, alpha, is_single=True):
1313        self.image = 0
1314        self.label = 0
1315        self.is_first = True
1316        self.batch_size = batch_size
1317        self.alpha = alpha
1318        self.is_single = is_single
1319        self.random = False
1320
1321    def __call__(self, image, label):
1322        """
1323        Call method.
1324
1325        Args:
1326            image (numpy.ndarray): Images to be mixed up.
1327            label (numpy.ndarray): Labels to be mixed up.
1328
1329        Returns:
1330            numpy.ndarray, images after mixing up.
1331            numpy.ndarray, labels after mixing up.
1332        """
1333        if self.is_single:
1334            return util.mix_up_single(self.batch_size, image, label, self.alpha)
1335        return util.mix_up_muti(self, self.batch_size, image, label, self.alpha)
1336
1337
1338class RgbToBgr(py_transforms.PyTensorOperation):
1339    """
1340    Convert one or more numpy.ndarray images from RGB to BGR.
1341
1342    Args:
1343        is_hwc (bool): Whether the image is in shape of (H, W, C) or (N, H, W, C), otherwise
1344            in shape of (C, H, W) or (N, C, H, W) (default=False).
1345
1346    Examples:
1347        >>> from mindspore.dataset.transforms.py_transforms import Compose
1348        >>> transforms_list = Compose([py_vision.Decode(),
1349        ...                            py_vision.CenterCrop(20),
1350        ...                            py_vision.ToTensor(),
1351        ...                            py_vision.RgbToBgr()])
1352        >>> # apply the transform to dataset through map function
1353        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1354        ...                                                 input_columns="image")
1355    """
1356
1357    @check_rgb_to_bgr
1358    def __init__(self, is_hwc=False):
1359        self.is_hwc = is_hwc
1360        self.random = False
1361
1362    def __call__(self, rgb_imgs):
1363        """
1364        Call method.
1365
1366        Args:
1367            rgb_imgs (numpy.ndarray): RGB images to be converted.
1368
1369        Returns:
1370            numpy.ndarray, converted BGR images.
1371        """
1372        return util.rgb_to_bgrs(rgb_imgs, self.is_hwc)
1373
1374
1375class RgbToHsv(py_transforms.PyTensorOperation):
1376    """
1377    Convert one or more numpy.ndarray images from RGB to HSV.
1378
1379    Args:
1380        is_hwc (bool): Whether the image is in shape of (H, W, C) or (N, H, W, C), otherwise
1381            in shape of (C, H, W) or (N, C, H, W) (default=False).
1382
1383    Examples:
1384        >>> from mindspore.dataset.transforms.py_transforms import Compose
1385        >>> transforms_list = Compose([py_vision.Decode(),
1386        ...                            py_vision.CenterCrop(20),
1387        ...                            py_vision.ToTensor(),
1388        ...                            py_vision.RgbToHsv()])
1389        >>> # apply the transform to dataset through map function
1390        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1391        ...                                                 input_columns="image")
1392    """
1393
1394    @check_rgb_to_hsv
1395    def __init__(self, is_hwc=False):
1396        self.is_hwc = is_hwc
1397        self.random = False
1398
1399    def __call__(self, rgb_imgs):
1400        """
1401        Call method.
1402
1403        Args:
1404            rgb_imgs (numpy.ndarray): RGB images to be converted.
1405
1406        Returns:
1407            numpy.ndarray, converted HSV images.
1408        """
1409        return util.rgb_to_hsvs(rgb_imgs, self.is_hwc)
1410
1411
1412class HsvToRgb(py_transforms.PyTensorOperation):
1413    """
1414    Convert one or more numpy.ndarray images from HSV to RGB.
1415
1416    Args:
1417        is_hwc (bool): Whether the image is in shape of (H, W, C) or (N, H, W, C), otherwise
1418            in shape of (C, H, W) or (N, C, H, W) (default=False).
1419
1420    Examples:
1421        >>> from mindspore.dataset.transforms.py_transforms import Compose
1422        >>> transforms_list = Compose([py_vision.Decode(),
1423        ...                            py_vision.CenterCrop(20),
1424        ...                            py_vision.ToTensor(),
1425        ...                            py_vision.HsvToRgb()])
1426        >>> # apply the transform to dataset through map function
1427        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1428        ...                                                 input_columns="image")
1429    """
1430
1431    @check_hsv_to_rgb
1432    def __init__(self, is_hwc=False):
1433        self.is_hwc = is_hwc
1434        self.random = False
1435
1436    def __call__(self, hsv_imgs):
1437        """
1438        Call method.
1439
1440        Args:
1441            hsv_imgs (numpy.ndarray): HSV images to be converted.
1442
1443        Returns:
1444            numpy.ndarray, converted RGB images.
1445        """
1446        return util.hsv_to_rgbs(hsv_imgs, self.is_hwc)
1447
1448
1449class RandomColor(py_transforms.PyTensorOperation):
1450    """
1451    Adjust the color balance of the input PIL Image by a random degree.
1452
1453    Args:
1454        degrees (sequence): Range of color adjustment degree to be randomly chosen from,
1455            which should be in shape of (min, max) (default=(0.1,1.9)).
1456
1457    Examples:
1458        >>> from mindspore.dataset.transforms.py_transforms import Compose
1459        >>> transforms_list = Compose([py_vision.Decode(),
1460        ...                            py_vision.RandomColor((0.5, 2.0)),
1461        ...                            py_vision.ToTensor()])
1462        >>> # apply the transform to dataset through map function
1463        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1464        ...                                                 input_columns="image")
1465    """
1466
1467    @check_positive_degrees
1468    def __init__(self, degrees=(0.1, 1.9)):
1469        self.degrees = degrees
1470
1471    def __call__(self, img):
1472        """
1473        Call method.
1474
1475        Args:
1476            img (PIL Image): Image to be color adjusted.
1477
1478        Returns:
1479            PIL Image, color adjusted image.
1480        """
1481
1482        return util.random_color(img, self.degrees)
1483
1484
1485class RandomSharpness(py_transforms.PyTensorOperation):
1486    """
1487    Adjust the sharpness of the input PIL Image by a random degree.
1488
1489    Args:
1490        degrees (sequence): Range of sharpness adjustment degree to be randomly chosen from, which
1491            should be in shape of (min, max) (default=(0.1,1.9)).
1492            Degree of 0.0 gives a blurred image, degree of 1.0 gives the original image,
1493            and degree of 2.0 increases the sharpness by a factor of 2.
1494
1495    Examples:
1496        >>> from mindspore.dataset.transforms.py_transforms import Compose
1497        >>> transforms_list = Compose([py_vision.Decode(),
1498        ...                            py_vision.RandomSharpness((0.5, 1.5)),
1499        ...                            py_vision.ToTensor()])
1500        >>> # apply the transform to dataset through map function
1501        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1502        ...                                                 input_columns="image")
1503    """
1504
1505    @check_positive_degrees
1506    def __init__(self, degrees=(0.1, 1.9)):
1507        self.degrees = degrees
1508
1509    def __call__(self, img):
1510        """
1511        Call method.
1512
1513        Args:
1514            img (PIL Image): Image to be sharpness adjusted.
1515
1516        Returns:
1517            PIL Image, sharpness adjusted image.
1518        """
1519
1520        return util.random_sharpness(img, self.degrees)
1521
1522
1523class AdjustGamma(py_transforms.PyTensorOperation):
1524    """
1525    Perform gamma correction on the input PIL Image.
1526
1527    Args:
1528        gamma (float): Gamma parameter in the correction equation, which must be non negative.
1529        gain (float, optional): The constant multiplier (default=1.0).
1530
1531    Examples:
1532        >>> from mindspore.dataset.transforms.py_transforms import Compose
1533        >>> transforms_list = Compose([py_vision.Decode(),
1534        ...                            py_vision.AdjustGamma(gamma=10.0),
1535        ...                            py_vision.ToTensor()])
1536        >>> # apply the transform to dataset through map function
1537        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1538        ...                                                 input_columns="image")
1539    """
1540
1541    @check_adjust_gamma
1542    def __init__(self, gamma, gain=1.0):
1543        self.gamma = gamma
1544        self.gain = gain
1545        self.random = False
1546
1547    def __call__(self, img):
1548        """
1549        Call method.
1550
1551        Args:
1552            img (PIL Image): Image to be gamma adjusted.
1553
1554        Returns:
1555            PIL Image, gamma adjusted image.
1556        """
1557
1558        return util.adjust_gamma(img, self.gamma, self.gain)
1559
1560
1561class AutoContrast(py_transforms.PyTensorOperation):
1562    """
1563    Automatically maximize the contrast of the input PIL Image.
1564
1565    Args:
1566        cutoff (float, optional): Percent of pixels to be cut off from the histogram,
1567            which must be in range of [0.0, 50.0) (default=0.0).
1568        ignore (Union[int, sequence], optional): Pixel values to be ignored (default=None).
1569
1570    Examples:
1571        >>> from mindspore.dataset.transforms.py_transforms import Compose
1572        >>> transforms_list = Compose([py_vision.Decode(),
1573        ...                            py_vision.AutoContrast(),
1574        ...                            py_vision.ToTensor()])
1575        >>> # apply the transform to dataset through map function
1576        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1577        ...                                                 input_columns="image")
1578    """
1579
1580    @check_auto_contrast
1581    def __init__(self, cutoff=0.0, ignore=None):
1582        self.cutoff = cutoff
1583        self.ignore = ignore
1584        self.random = False
1585
1586    def __call__(self, img):
1587        """
1588        Call method.
1589
1590        Args:
1591            img (PIL Image): Image to be automatically contrasted.
1592
1593        Returns:
1594            PIL Image, automatically contrasted image.
1595        """
1596
1597        return util.auto_contrast(img, self.cutoff, self.ignore)
1598
1599
1600class Invert(py_transforms.PyTensorOperation):
1601    """
1602    Invert the colors of the input PIL Image.
1603
1604    Examples:
1605        >>> from mindspore.dataset.transforms.py_transforms import Compose
1606        >>> transforms_list = Compose([py_vision.Decode(),
1607        ...                            py_vision.Invert(),
1608        ...                            py_vision.ToTensor()])
1609        >>> # apply the transform to dataset through map function
1610        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1611        ...                                                 input_columns="image")
1612    """
1613
1614    def __init__(self):
1615        self.random = False
1616
1617    def __call__(self, img):
1618        """
1619        Call method.
1620
1621        Args:
1622            img (PIL Image): Image to be color inverted.
1623
1624        Returns:
1625            PIL Image, color inverted image.
1626        """
1627
1628        return util.invert_color(img)
1629
1630
1631class Equalize(py_transforms.PyTensorOperation):
1632    """
1633    Apply histogram equalization on the input PIL Image.
1634
1635    Examples:
1636        >>> from mindspore.dataset.transforms.py_transforms import Compose
1637        >>> transforms_list = Compose([py_vision.Decode(),
1638        ...                            py_vision.Equalize(),
1639        ...                            py_vision.ToTensor()])
1640        >>> # apply the transform to dataset through map function
1641        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1642        ...                                                 input_columns="image")
1643
1644    """
1645
1646    def __init__(self):
1647        self.random = False
1648
1649    def __call__(self, img):
1650        """
1651        Call method.
1652
1653        Args:
1654            img (PIL Image): Image to be equalized.
1655
1656        Returns:
1657            PIL Image, equalized image.
1658        """
1659
1660        return util.equalize(img)
1661
1662
1663class UniformAugment(py_transforms.PyTensorOperation):
1664    """
1665    Uniformly select a number of transformations from a sequence and apply them
1666    sequentially and randomly, which means that there is a chance that a chosen
1667    transformation will not be applied.
1668
1669    All transformations in the sequence require the output type to be the same as
1670    the input. Thus, the latter one can deal with the output of the previous one.
1671
1672    Args:
1673         transforms (sequence): Sequence of transformations to be chosen from.
1674         num_ops (int, optional): Number of transformations to be sequentially and randomly applied (default=2).
1675
1676    Examples:
1677        >>> from mindspore.dataset.transforms.py_transforms import Compose
1678        >>> transforms = [py_vision.CenterCrop(64),
1679        ...               py_vision.RandomColor(),
1680        ...               py_vision.RandomSharpness(),
1681        ...               py_vision.RandomRotation(30)]
1682        >>> transforms_list = Compose([py_vision.Decode(),
1683        ...                            py_vision.UniformAugment(transforms),
1684        ...                            py_vision.ToTensor()])
1685        >>> # apply the transform to dataset through map function
1686        >>> image_folder_dataset = image_folder_dataset.map(operations=transforms_list,
1687        ...                                                 input_columns="image")
1688    """
1689
1690    @check_uniform_augment_py
1691    def __init__(self, transforms, num_ops=2):
1692        self.transforms = transforms
1693        self.num_ops = num_ops
1694        self.random = False
1695
1696    def __call__(self, img):
1697        """
1698        Call method.
1699
1700        Args:
1701            img (PIL Image): Image to be transformed.
1702
1703        Returns:
1704            PIL Image, transformed image.
1705        """
1706        return util.uniform_augment(img, self.transforms.copy(), self.num_ops)
1707