1- import torch
2- from torch import Tensor
31import math
2+ import numbers
3+ import warnings
4+ from collections .abc import Iterable
5+
6+ import numpy as np
7+ from numpy import sin , cos , tan
48from PIL import Image , ImageOps , ImageEnhance , __version__ as PILLOW_VERSION
9+
10+ import torch
11+ from torch import Tensor
12+ from torch .jit .annotations import List
13+
514try :
615 import accimage
716except ImportError :
817 accimage = None
9- import numpy as np
10- from numpy import sin , cos , tan
11- import numbers
12- from collections .abc import Sequence , Iterable
13- import warnings
1418
1519from . import functional_pil as F_pil
1620from . import functional_tensor as F_t
@@ -342,20 +346,24 @@ def scale(*args, **kwargs):
342346 return resize (* args , ** kwargs )
343347
344348
345- def pad (img , padding , fill = 0 , padding_mode = 'constant' ):
346- r"""Pad the given PIL Image on all sides with specified padding mode and fill value.
349+ def pad (img : Tensor , padding : List [int ], fill : int = 0 , padding_mode : str = "constant" ) -> Tensor :
350+ r"""Pad the given image on all sides with the given "pad" value.
351+ The image can be a PIL Image or a torch Tensor, in which case it is expected
352+ to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions
347353
348354 Args:
349- img (PIL Image): Image to be padded.
350- padding (int or tuple): Padding on each border. If a single int is provided this
355+ img (PIL Image or Tensor ): Image to be padded.
356+ padding (int or tuple or list ): Padding on each border. If a single int is provided this
351357 is used to pad all borders. If tuple of length 2 is provided this is the padding
352358 on left/right and top/bottom respectively. If a tuple of length 4 is provided
353- this is the padding for the left, top, right and bottom borders
354- respectively.
355- fill: Pixel fill value for constant fill. Default is 0. If a tuple of
359+ this is the padding for the left, top, right and bottom borders respectively.
360+ In torchscript mode padding as single int is not supported, use a tuple or
361+ list of length 1: ``[padding, ]``.
362+ fill (int or str or tuple): Pixel fill value for constant fill. Default is 0. If a tuple of
356363 length 3, it is used to fill R, G, B channels respectively.
357- This value is only used when the padding_mode is constant
364+ This value is only used when the padding_mode is constant. Only int value is supported for Tensors.
358365 padding_mode: Type of padding. Should be: constant, edge, reflect or symmetric. Default is constant.
366+ Only "constant" is supported for Tensors as of now.
359367
360368 - constant: pads with a constant value, this value is specified with fill
361369
@@ -372,68 +380,12 @@ def pad(img, padding, fill=0, padding_mode='constant'):
372380 will result in [2, 1, 1, 2, 3, 4, 4, 3]
373381
374382 Returns:
375- PIL Image: Padded image.
383+ PIL Image or Tensor : Padded image.
376384 """
377- if not _is_pil_image (img ):
378- raise TypeError ('img should be PIL Image. Got {}' .format (type (img )))
379-
380- if not isinstance (padding , (numbers .Number , tuple )):
381- raise TypeError ('Got inappropriate padding arg' )
382- if not isinstance (fill , (numbers .Number , str , tuple )):
383- raise TypeError ('Got inappropriate fill arg' )
384- if not isinstance (padding_mode , str ):
385- raise TypeError ('Got inappropriate padding_mode arg' )
386-
387- if isinstance (padding , Sequence ) and len (padding ) not in [2 , 4 ]:
388- raise ValueError ("Padding must be an int or a 2, or 4 element tuple, not a " +
389- "{} element tuple" .format (len (padding )))
390-
391- assert padding_mode in ['constant' , 'edge' , 'reflect' , 'symmetric' ], \
392- 'Padding mode should be either constant, edge, reflect or symmetric'
393-
394- if padding_mode == 'constant' :
395- if isinstance (fill , numbers .Number ):
396- fill = (fill ,) * len (img .getbands ())
397- if len (fill ) != len (img .getbands ()):
398- raise ValueError ('fill should have the same number of elements '
399- 'as the number of channels in the image '
400- '({}), got {} instead' .format (len (img .getbands ()), len (fill )))
401- if img .mode == 'P' :
402- palette = img .getpalette ()
403- image = ImageOps .expand (img , border = padding , fill = fill )
404- image .putpalette (palette )
405- return image
406-
407- return ImageOps .expand (img , border = padding , fill = fill )
408- else :
409- if isinstance (padding , int ):
410- pad_left = pad_right = pad_top = pad_bottom = padding
411- if isinstance (padding , Sequence ) and len (padding ) == 2 :
412- pad_left = pad_right = padding [0 ]
413- pad_top = pad_bottom = padding [1 ]
414- if isinstance (padding , Sequence ) and len (padding ) == 4 :
415- pad_left = padding [0 ]
416- pad_top = padding [1 ]
417- pad_right = padding [2 ]
418- pad_bottom = padding [3 ]
419-
420- if img .mode == 'P' :
421- palette = img .getpalette ()
422- img = np .asarray (img )
423- img = np .pad (img , ((pad_top , pad_bottom ), (pad_left , pad_right )), padding_mode )
424- img = Image .fromarray (img )
425- img .putpalette (palette )
426- return img
427-
428- img = np .asarray (img )
429- # RGB image
430- if len (img .shape ) == 3 :
431- img = np .pad (img , ((pad_top , pad_bottom ), (pad_left , pad_right ), (0 , 0 )), padding_mode )
432- # Grayscale image
433- if len (img .shape ) == 2 :
434- img = np .pad (img , ((pad_top , pad_bottom ), (pad_left , pad_right )), padding_mode )
385+ if not isinstance (img , torch .Tensor ):
386+ return F_pil .pad (img , padding = padding , fill = fill , padding_mode = padding_mode )
435387
436- return Image . fromarray (img )
388+ return F_t . pad (img , padding = padding , fill = fill , padding_mode = padding_mode )
437389
438390
439391def crop (img , top , left , height , width ):
0 commit comments