cv2 中的非标准化高斯核

Unnormalized gaussian kernel in cv2

我需要用归一化的高斯核对我的图像进行卷积。当然我可以自己定义一个函数,但我更愿意使用 cv2 函数,它肯定会更有效率。

cv2.GaussianBlur 已标准化,显然它没有关闭标准化的选项。

有什么提示吗?

如果你有归一化内核的过滤图像,以及非归一化内核的总和,你所要做的就是将归一化图像乘以总和。

卷积的规则是可以切换顺序:
将核乘以缩放器,然后对图像进行滤波,与对图像进行滤波并将结果乘以标量相同。

以下 Python 代码演示了解决方案:

# 
def gkern(kernlen=21, nsig=3):
    """Returns a 2D Gaussian kernel."""

    x = np.linspace(-nsig, nsig, kernlen+1)
    kern1d = np.diff(st.norm.cdf(x))
    kern2d = np.outer(kern1d, kern1d)
    return (kern2d/kern2d.sum(), kern2d.sum())

# Normalized Gaussian kernel
norm_h, norm_h_sum = gkern(21, 3)

# Simulate un-normalized kernel (sum = 3)
h = norm_h*3
h_sum = h.sum()

# Create random 160x120 image of type float32
img = np.float32(np.random.rand(120, 160))

# Filter with norm_h kernel
img_norm_h = cv2.filter2D(img, -1, norm_h)

# Filter with h kernel
img_h = cv2.filter2D(img, -1, h)

# Multiply img_norm_h by h_sum for getting the same result as img_h
img_norm_h_by_sum = img_norm_h * h_sum

max_abs_diff = np.max(cv2.absdiff(img_h, img_norm_h_by_sum))

print("max_abs_diff = {}".format(max_abs_diff))

注:
高斯滤波器可以实现为可分离滤波器,因此 cv2.GaussianBlur 可能比使用 cv2.filter2D.
更有效 cv2.filter2D用于演示原理。


cv2.GaussianBlur相比:

# Filter and multiply by sum
img_blur = cv2.GaussianBlur(img, (21, 21), 3) * norm_h_sum

# Multiply by sum and filter
img_h = cv2.filter2D(img, -1, norm_h*norm_h_sum)

img_blur_max_abs_diff = np.max(cv2.absdiff(img_blur, img_h))

print("img_blur_max_abs_diff = {}".format(img_blur_max_abs_diff))