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))
我需要用归一化的高斯核对我的图像进行卷积。当然我可以自己定义一个函数,但我更愿意使用 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))