Symmetric Padding

Has anybody figured out how to do symmetric padding of an image tensor?

The current pad function can do constant padding, zero-order hold padding (replicate) or reflection padding, but it can’t do symmetric padding. The difference between symmetric and reflection padding is best seen in the tensorflow help:

t = tf.constant([[1, 2, 3], [4, 5, 6]])
paddings = tf.constant([[1, 1,], [2, 2]])
# 'constant_values' is 0.
# rank of 't' is 2.
tf.pad(t, paddings, "CONSTANT")  # [[0, 0, 0, 0, 0, 0, 0],
                                 #  [0, 0, 1, 2, 3, 0, 0],
                                 #  [0, 0, 4, 5, 6, 0, 0],
                                 #  [0, 0, 0, 0, 0, 0, 0]]

tf.pad(t, paddings, "REFLECT")  # [[6, 5, 4, 5, 6, 5, 4],
                                #  [3, 2, 1, 2, 3, 2, 1],
                                #  [6, 5, 4, 5, 6, 5, 4],
                                #  [3, 2, 1, 2, 3, 2, 1]]

tf.pad(t, paddings, "SYMMETRIC")  # [[2, 1, 1, 2, 3, 3, 2],
                                  #  [2, 1, 1, 2, 3, 3, 2],
                                  #  [5, 4, 4, 5, 6, 6, 5],
                                  #  [5, 4, 4, 5, 6, 6, 5]]
3 Likes

Do you know if there haas been any way to use convnets with symmetric padding in pytorch?

Hi @Felipe_bivort_haiek, I managed to find a workaround before. You can achieve symmetric padding by manually making the index arrays. For example, this function will do 2d padding for you:

import torch
import numpy as np
from typing import Tuple

def symm_pad(im: torch.Tensor, padding: Tuple[int, int, int, int]):
     h, w = im.shape[-2:]
     left, right, top, bottom = padding
 
     x_idx = np.arange(-left, w+right)
     y_idx = np.arange(-top, h+bottom)
 
     def reflect(x, minx, maxx):
         """ Reflects an array around two points making a triangular waveform that ramps up
         and down,  allowing for pad lengths greater than the input length """
         rng = maxx - minx
         double_rng = 2*rng
         mod = np.fmod(x - minx, double_rng)
         normed_mod = np.where(mod < 0, mod+double_rng, mod)
         out = np.where(normed_mod >= rng, double_rng - normed_mod, normed_mod) + minx
         return np.array(out, dtype=x.dtype)

     x_pad = reflect(x_idx, -0.5, w-0.5)
     y_pad = reflect(y_idx, -0.5, h-0.5)
     xx, yy = np.meshgrid(x_pad, y_pad)
     return im[..., yy, xx]
1 Like