1. 高斯核

高斯核可通过 函数 cv2.getGaussianKernel 获得,但该函数只能生成一维高斯核

参数使用如下图:
在这里插入图片描述

虽然不能直接通过函数获取二维高斯核,但是可以通过公式 kernel_x * kernel_y.T 计算得出(下面有例子)。


假设我们指定高斯核的尺寸为 7x7,kernel 的中心点像素坐标为 (3, 3)
sigma 可由公式计算得到: sigmaX = sigmY = 0.3 * ((ksize - 1) * 0.5 - 1) + 0.8 = 1.4
将每一个像素坐标 (0, 0), (0, 1)… 带入如下高斯函数,可以计算得到二维高斯核
f(x)=12πσxσye−12[(x−μ)2σx2+(y−μ)2σy2]f(x) = \frac{1}{{2π} \sigma_x \sigma_y} e^{-\frac{1}{2} [\frac{(x-μ)^2}{\sigma_x^2} + \frac{(y-μ)^2}{\sigma_y^2}]}f(x)=2πσxσy1e21[σx2(xμ)2+σy2(yμ)2] 因为 σx=σy\sigma_x = \sigma_yσx=σy ,公式简化为

f(x)=12πσ2e−(x−μ)2+(y−μ)22σ2f(x) = \frac{1}{{2π} \sigma^2} e^{-\frac{(x-μ)^2+(y-\mu)^2}{2\sigma^2}}f(x)=2πσ21e2σ2(xμ)2+(yμ)2


下面举例,代码内容包括:

  1. 通过 opencv的cv2.getGaussianKernel 函数,得到高斯核
  2. 我们自己手撸的代码,得到高斯核 (不要忘记归一化)
  3. 最后检测,我们自己的代码得出的结果是否等于cv2.getGaussianKernel 函数生成的结果
import cv2
import numpy as np
import math

"""
基础参数设置:
(1)我们指定高斯核的尺寸为 ksize=7x7
(2)sigma 可由公式计算得到: sigma = 0.3 * ((ksize - 1) * 0.5 - 1) + 0.8
"""
kernel_size = 7
sigma = 0.3 * ((kernel_size - 1) * 0.5 - 1) + 0.8
radium = kernel_size//2   # radium=3


""" 通过函数 cv2.getGaussianKernel 生成二维高斯核 """
kernel_1d = cv2.getGaussianKernel(ksize=kernel_size, sigma=sigma, ktype=cv2.CV_32F)
kernel_2d = kernel_1d * kernel_1d.T
print(kernel_2d)


""" 手撸高斯核,通过二维高斯公式计算得出 """ 
constant = 1/(2 * math.pi * sigma**2)
gaussian_kernel = np.zeros((kernel_size, kernel_size))
for i in range(0, kernel_size, 1):
    for j in range(0, kernel_size, 1):
        x = i-radium
        y = j-radium
        gaussian_kernel[i, j] = constant*math.exp(-0.5/(sigma**2)*(x**2+y**2))

gaussian_kernel = gaussian_kernel/gaussian_kernel.sum()  # 归一化
print('\n', gaussian_kernel)

在这里插入图片描述

可以看出,我们自己的代码得出的结果和 cv2.getGaussianKernel 函数得出的结果是一样的


2. 高斯模糊

例子包括:

  1. 读取图片,设置初始化参数值
  2. 通过函数 cv2.GaussianBlur 函数,对图像进行高斯模糊操作。
  3. 自己手撸代码实现高斯模糊。图像边界不做高斯模糊操作,使用原图的值
  4. 生成的高斯模糊图像,进行对比
import cv2
import numpy as np
import copy


# 读取图片
image = cv2.imread('images/lena.bmp', 0)
cv2.imshow('original', image)

# 初始化参数
rows, cols = image.shape
sigma = 0.84089642
kernel_size = np.int(np.round(sigma*3)*2+1)  # 一般高斯核尺寸通过计算得到:6*sigma+1 要保证尺寸的宽度和高度都为奇数
radium = kernel_size//2

# 通过函数 cv2.GaussianBlur 进行滤波处理(模糊处理)
result1 = cv2.GaussianBlur(image, ksize=(kernel_size, kernel_size), sigmaX=sigma)
cv2.imshow('result1', result1)

# 生成高斯核
kernel_1d = cv2.getGaussianKernel(ksize=kernel_size, sigma=sigma, ktype=cv2.CV_32F)
kernel_2d = kernel_1d * kernel_1d.T
# print(kernel_2d)

# 边缘保留原图想的像素值
result2 = copy.deepcopy(image)
for i in range(radium, rows-radium, 1):
    for j in range(radium, rows-radium, 1):
        result2[i, j] = (image[i-radium:i+radium+1, j-radium:j+radium+1] * kernel_2d).sum()
result2 = np.uint8(result2)

cv2.imshow('result2', result2)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐