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