σ 滤波器(Sigma Filter)基本原理及其优化版本介绍
目录
σ 滤波器(Sigma Filter)基本原理
1. 核心思想:选择性均值滤波
2. 与其他滤波器的对比
3. 关键优势
4. 算法步骤(以灰度图像为例)
5. 直方图优化版本
5.1 为加速筛选过程,可引入局部直方图统计:
5.2 直方图优化的实现步骤
5.2.1 初始化直方图
5.2.2.滑动窗口更新直方图
5.2.3 基于直方图的快速筛选与计算
5.2.4 伪代码实现
σ 滤波器(Sigma Filter)基本原理
拉普拉斯算子过零点边缘检测原理以及抑制伪边缘的方法博文中所提到的Sigma Filter在此做一次简单的展开。
σ 滤波器是一种非线性图像滤波算法,主要用于降噪的同时保留图像边缘。其核心思想是:在滑动窗口内,仅对与中心像素灰度值(或颜色强度)差异小于特定阈值(称为容差阈值 σ)的像素进行均值计算,从而排除差异较大的噪声点,避免模糊边缘。
1. 核心思想:选择性均值滤波
- 滑动窗口:在图像上滑动一个大小为 W×W 的窗口(如 3×3、5×5)。
- 容差阈值 σ:设定一个阈值 σ(即 “tolerance”),用于判断窗口内像素是否属于 “有效像素”。
- 有效像素筛选:对于窗口内每个像素,若其灰度值(或颜色通道值)与中心像素的差异绝对值 ≤ σ,则认为是有效像素,参与均值计算;否则被忽略。
- 输出结果:中心像素的输出值为所有有效像素的均值。
数学表达式(灰度图像):
设中心像素坐标为 ,灰度值为
,窗口内像素集合为 N,则输出值为:
其中,K 为有效像素个数,δ(⋅) 为指示函数(条件满足时为 1,否则为 0)。
2. 与其他滤波器的对比
- 均值滤波器:对窗口内所有像素直接求平均,会模糊边缘(因噪声和边缘像素均参与计算)。
- 中值滤波器:用窗口内像素的中值替代中心像素,适合去除椒盐噪声,但对高斯噪声效果较差。
- 双边滤波器:通过空间权重(距离越远权重越低)和值域权重(差异越大权重越低)加权平均,效果类似 σ 滤波器,但计算复杂度更高(需计算高斯权重)。
- σ 滤波器可视为双边滤波器的简化版本:用 “硬阈值筛选”(矩形分布)替代双边滤波器的 “高斯权重”,计算更快。
3. 关键优势
- 边缘保留:排除差异大的像素(如边缘两侧的像素),避免均值计算时模糊边缘。
- 高斯噪声抑制:有效像素通常属于同一区域(如平滑区域或边缘同侧),其均值能有效降低高斯噪声。
- 计算效率:相比双边滤波器,无需计算复杂的高斯权重,适合实时处理(尤其优化后通过直方图统计加速)。
4. 算法步骤(以灰度图像为例)
5. 直方图优化版本
5.1 为加速筛选过程,可引入局部直方图统计:
- 预处理:在窗口滑动时,维护一个直方图,记录窗口内各灰度值的出现次数。
- 快速筛选:通过直方图直接统计与中心像素灰度值差异 ≤ σ 的像素总数及灰度和,避免逐像素比较。
- 复杂度优化:将时间复杂度从 O(W2) 降至 O(2σ+1)(与窗口大小解耦,仅依赖阈值范围)。
5.2 直方图优化的实现步骤
5.2.1 初始化直方图
- 对首个窗口(如左上角 3×3 窗口),遍历所有像素,统计各强度值的出现次数,存入直方图数组
hist
。 - 直方图长度为强度范围(如灰度图为 0~255,共 256 个 bin)。
5.2.2.滑动窗口更新直方图
- 当窗口向右或向下滑动时,仅需更新移出列 / 行和移入列 / 行的像素:
- 移出操作:将窗口左边界列(或上边界行)的像素强度值对应的
hist
计数减 1; - 移入操作:将窗口右边界列(或下边界行)的像素强度值对应的
hist
计数加 1。
- 移出操作:将窗口左边界列(或上边界行)的像素强度值对应的
5.2.3 基于直方图的快速筛选与计算
- 确定中心像素强度:设当前窗口中心像素强度为 M。
- 筛选有效像素:遍历直方图中强度范围为 [M−tol,M+tol] 的所有 bin,累加对应计数(得到有效像素数量 N)和强度总和(得到 sum)。
- 计算均值:若 N>0,则输出像素值为 sum/N;否则保留原值(如无有效像素,通常为噪声点)。
5.2.4 伪代码实现
def sigma_filter_histogram(input_img, tol, window_size=3):h, w = input_img.shapepad = window_size // 2output = np.zeros_like(input_img, dtype=np.float32)half_size = window_size // 2# 初始化直方图hist = np.zeros(256, dtype=np.int32) # 假设灰度范围0-255for i in range(pad, pad + window_size):for j in range(pad, pad + window_size):val = input_img[i, j]hist[val] += 1for x in range(h):for y in range(w):# 获取中心像素强度cx = x + padcy = y + padif cx >= h or cy >= w:continue # 边界处理,可扩展为镜像填充等M = input_img[cx, cy]# 计算有效强度范围low = max(0, M - tol)high = min(255, M + tol)# 累加有效像素的计数和总和count = 0total = 0for val in range(low, high + 1):count += hist[val]total += val * hist[val]if count > 0:output[cx, cy] = total / countelse:output[cx, cy] = M # 无有效像素时保留原值# 更新直方图(水平滑动:右移一列)if y < w - pad - 1:# 移出左边界列(当前列y)for i in range(cx - half_size, cx + half_size + 1):val = input_img[i, y]hist[val] -= 1# 移入右边界列(下一列y+pad+1)for i in range(cx - half_size, cx + half_size + 1):val = input_img[i, y + pad + 1]hist[val] += 1# 垂直滑动:下移一行时需类似更新上下边界行(此处简化,实际需处理换行逻辑)return output.astype(np.uint8)