深入理解高斯滤波的原理、实现与应用
高斯滤波是一种线性滤波技术,使用高斯函数作为权重对图像进行平滑处理,广泛用于图像去噪和预处理。
高斯滤波基于高斯函数(正态分布)构建滤波器核,对图像进行卷积操作。与均值滤波不同,高斯滤波给距离中心点较近的像素分配更高的权重,从而在平滑图像的同时更好地保持边缘信息。
| 参数 | 说明 | 影响 |
|---|---|---|
| 核大小 | 滤波器窗口尺寸 | 越大平滑效果越强 |
| σ (sigma) | 标准差 | 决定高斯分布宽度 |
| 权重分布 | 中心高边缘低 | 保边效果优于均值滤波 |
二维高斯函数定义为:
G(x, y) = (1 / (2πσ2)) × e^(-(x2+y2)/(2σ2))
其中σ是标准差,控制高斯函数的宽度。离散化的高斯核可以通过采样这个函数并归一化得到。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def gaussian_filter_builtin(image_path, kernel_size=5, sigma=1.0):
"""
使用OpenCV内置函数实现高斯滤波
:param image_path: 输入图像路径
:param kernel_size: 滤波器大小,必须为奇数
:param sigma: 高斯核的标准差
:return: 原图和滤波后的图像
"""
# 读取图像
img = cv2.imread(image_path)
# 应用高斯滤波
filtered = cv2.GaussianBlur(img, (kernel_size, kernel_size), sigma)
return img, filtered
def create_gaussian_kernel(size, sigma):
"""
创建高斯核
:param size: 核大小,必须为奇数
:param sigma: 高斯核的标准差
:return: 高斯核
"""
kernel = np.zeros((size, size), dtype=np.float32)
center = size // 2
# 计算高斯核
for i in range(size):
for j in range(size):
x, y = i - center, j - center
kernel[i, j] = np.exp(-(x**2 + y**2) / (2 * sigma**2))
# 归一化
kernel = kernel / np.sum(kernel)
return kernel
def manual_gaussian_filter(image_path, kernel_size=5, sigma=1.0):
"""
手动实现高斯滤波
:param image_path: 输入图像路径
:param kernel_size: 滤波器大小,必须为奇数
:param sigma: 高斯核的标准差
:return: 高斯滤波后的图像
"""
# 读取图像
img = cv2.imread(image_path)
img_float = img.astype(np.float32)
height, width, channels = img.shape
# 创建高斯核
kernel = create_gaussian_kernel(kernel_size, sigma)
# 计算边界填充大小
pad_size = kernel_size // 2
# 对图像进行边界填充
padded_img = np.pad(img_float, ((pad_size, pad_size), (pad_size, pad_size), (0, 0)), mode='edge')
# 创建输出图像
filtered = np.zeros_like(img_float)
# 应用高斯滤波
for i in range(height):
for j in range(width):
for c in range(channels):
# 提取当前窗口
window = padded_img[i:i+kernel_size, j:j+kernel_size, c]
# 计算加权平均值
filtered[i, j, c] = np.sum(window * kernel)
return img, filtered.astype(np.uint8)
def separable_gaussian_filter(image_path, kernel_size=5, sigma=1.0):
"""
使用可分离滤波器实现高斯滤波
:param image_path: 输入图像路径
:param kernel_size: 滤波器大小,必须为奇数
:param sigma: 高斯核的标准差
:return: 原图和滤波后的图像
"""
# 读取图像
img = cv2.imread(image_path)
# 创建一维高斯核
kernel_1d = cv2.getGaussianKernel(kernel_size, sigma)
# 分别在水平和垂直方向应用滤波器
temp = cv2.filter2D(img, -1, kernel_1d.T) # 水平方向
filtered = cv2.filter2D(temp, -1, kernel_1d) # 垂直方向
return img, filtered
def adaptive_gaussian_filter(image_path, local_variance_threshold=100):
"""
自适应高斯滤波
:param image_path: 输入图像路径
:param local_variance_threshold: 局部方差阈值
:return: 原图和自适应滤波后的图像
"""
# 读取图像
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE).astype(np.float32)
height, width = img.shape
# 计算边界填充大小
kernel_size = 5
pad_size = kernel_size // 2
# 对图像进行边界填充
padded_img = np.pad(img, pad_size, mode='edge')
# 创建高斯核
sigma = 1.0
kernel = create_gaussian_kernel(kernel_size, sigma)
# 创建输出图像
filtered = np.zeros_like(img)
# 计算局部统计信息
for i in range(height):
for j in range(width):
# 提取当前窗口
window = padded_img[i:i+kernel_size, j:j+kernel_size]
# 计算局部方差
local_variance = np.var(window)
# 如果局部方差大于阈值,说明该区域可能是边缘或纹理区域
# 此时减少平滑程度
if local_variance > local_variance_threshold:
# 保持原始值或轻微平滑
filtered[i, j] = img[i, j]
else:
# 对平坦区域应用高斯滤波
filtered[i, j] = np.sum(window * kernel)
return cv2.cvtColor(img.astype(np.uint8), cv2.COLOR_GRAY2BGR), cv2.cvtColor(filtered.astype(np.uint8), cv2.COLOR_GRAY2BGR)
def bilateral_vs_gaussian_comparison(image_path):
"""
比较高斯滤波和双边滤波的效果
:param image_path: 输入图像路径
:return: 原图、高斯滤波结果和双边滤波结果
"""
# 读取图像
img = cv2.imread(image_path)
# 高斯滤波
gaussian_result = cv2.GaussianBlur(img, (15, 15), 2)
# 双边滤波
bilateral_result = cv2.bilateralFilter(img, 15, 80, 80)
return img, gaussian_result, bilateral_result
# 使用示例
if __name__ == "__main__":
# 注意:需要提供实际的图像路径
# img, result = gaussian_filter_builtin('image.jpg', 5, 1.0)
# manual_img, manual_result = manual_gaussian_filter('image.jpg', 5, 1.0)
# sep_img, sep_result = separable_gaussian_filter('image.jpg', 5, 1.0)
# adapt_img, adapt_result = adaptive_gaussian_filter('image.jpg', 100)
# comp_img, gauss_res, bi_res = bilateral_vs_gaussian_comparison('image.jpg')
pass
| 参数 | 说明 | 影响 |
|---|---|---|
| 核大小 | 滤波窗口尺寸 | 越大平滑效果越强 |
| σ (sigma) | 标准差 | 决定高斯分布宽度 |
| 权重分布 | 中心高,边缘低 | 保边效果优于均值滤波 |