【opencv】高斯核是怎么通过参数ksize和sigma计算得到的 cv2.getGaussianKernel(),cv.GaussianBlur()

1. 高斯核

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

参数使用如下图:
【opencv】高斯核是怎么通过参数ksize和sigma计算得到的 cv2.getGaussianKernel(),cv.GaussianBlur()_第1张图片

虽然不能直接通过函数获取二维高斯核,但是可以通过公式 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 ) = 1 2 π σ x σ y e − 1 2 [ ( x − μ ) 2 σ x 2 + ( y − μ ) 2 σ y 2 ] 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 ) = 1 2 π σ 2 e − ( x − μ ) 2 + ( y − μ ) 2 2 σ 2 f(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)

【opencv】高斯核是怎么通过参数ksize和sigma计算得到的 cv2.getGaussianKernel(),cv.GaussianBlur()_第2张图片

可以看出,我们自己的代码得出的结果和 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()

你可能感兴趣的:(OpenCV,opencv,python)