Description
🚀 The feature
Currently torchvision.transforms.v2.GaussianBlur
takes a kernel_size
and sigma
but has no means of adjusting the padding_mode
(as in Conv2d
). I propose either (1) adding such an argument or (2) changing the default padding mode from "reflect"
to "symmetric"
.
Happy to submit a PR if there's interest.
Motivation, pitch
The padding mode "reflect"
is not intensity preserving, that is, the average pixel value can change after blurring (even though the kernel sums to 1). This would be fixed if the padding mode "symmetric"
was used. This mirrors opencv's GaussianBlur()
, which defaults to BORDER_REFLECT_101
, and instead BORDER_REFLECT
must be used for the intensity preserving behavior. Instead, scipy's scipy.ndimage.gaussian_filter
defaults to the confusingly named "reflect"
(pytorch's "symmetric"
) and pytorch's "reflect"
is instead "mirror"
.
In summary,
- torch
"reflect"
/ opencvBORDER_REFLECT_101
/ scipy"mirror"
: not intensity preserving, default for torch and opencv. - torch
"symmetric"
/ opencvBORDER_REFLECT
/ scipy"reflect"
: intensity preserving, default for scipy.
I find the scipy behavior more intuitive and I see no reason to prefer "reflect"
over "symmetric"
as a default. If we want to maintain strict equivalence to opencv, then we should add an argument to customize the padding like opencv and scipy.
import cv2 as cv
import numpy as np
import torch
from torchvision.transforms.v2.functional import gaussian_blur
from scipy.ndimage import gaussian_filter
if __name__ == "__main__":
img = np.zeros((8, 8))
img[[0, -1], :] = 1
img[:, [0, -1]] = 1
img /= np.sum(img)
print(f"original: {np.sum(img):.6f}")
blur = gaussian_filter(img, 1, radius=2)
print(f" scipy: {np.sum(blur):.6f}")
blur = gaussian_filter(img, 1, radius=2, mode="mirror")
print(f" scipy: {np.sum(blur):.6f}")
blur = cv.GaussianBlur(img, (5, 5), 1, borderType=cv.BORDER_REFLECT)
print(f" opencv: {np.sum(blur):.6f}")
blur = cv.GaussianBlur(img, (5, 5), 1)
print(f" opencv: {np.sum(blur):.6f}")
x = torch.tensor(np.expand_dims(img, 0))
blur = gaussian_blur(x, [5, 5], [1, 1])
print(f" torch: {torch.sum(blur):.6f}")
original: 1.000000
scipy: 1.000000
scipy: 0.731235
opencv: 1.000000
opencv: 0.731235
torch: 0.731235
somewhat related: opencv/opencv#9863
Alternatives
No response
Additional context
No response