【图像处理】高斯模糊——最优雅的模糊算法

均值模糊(每个像素 = 邻域平均)会产生"方块感"。

高斯模糊通过模拟自然界的光学衍射,让模糊更真实、更平滑。

而可分离性的发现,让它从"理论上漂亮"变成了"实践上高效"。


一、均值模糊的问题

均值模糊核(Box Filter):

复制代码
┌ 1/9  1/9  1/9 ┐
│ 1/9  1/9  1/9 │
└ 1/9  1/9  1/9 ┘

每个邻域像素的权重完全相同,不管距离中心多远。

这有什么问题?不符合自然界的规律

想象一张照片放在毛玻璃后面------近处的像素影响更大,远处的影响更小,而不是等权重。均值模糊无法模拟这种衰减,结果在边缘处会产生轻微的"阶梯感"(Box Filter 的频域特性是sinc函数,会产生振铃效应)。


二、高斯函数:自然界的"衰减规律"

高斯函数(正态分布)描述了很多自然现象的衰减模式:

复制代码
一维高斯函数:
G(x) = (1 / √(2πσ²)) · exp(-x² / 2σ²)

二维高斯函数:
G(x, y) = (1 / 2πσ²) · exp(-(x² + y²) / 2σ²)

其中 σ(sigma)= 标准差,控制模糊的"半径":

  • σ 小:曲线窄而高,权重集中在中心,模糊范围小
  • σ 大:曲线宽而平,权重分布广,模糊范围大

二维高斯函数的可视化

复制代码
        σ = 1.0 的 5×5 高斯权重(示意):

        0.0030  0.0133  0.0219  0.0133  0.0030
        0.0133  0.0596  0.0983  0.0596  0.0133
        0.0219  0.0983  0.1621  0.0983  0.0219
        0.0133  0.0596  0.0983  0.0596  0.0133
        0.0030  0.0133  0.0219  0.0133  0.0030

        中心权重最大(0.1621),向四周递减

这就是高斯模糊"更自然"的原因:距离越近,影响越大,完全符合直觉


三、σ 与核尺寸的关系

高斯函数理论上延伸到无穷远,但实际中,超过 3σ 距离的权重已经小到可以忽略(只有 0.3% 的能量)。

实践约定 :核半径 r = ⌈3σ⌉,核尺寸 = 2r + 1

σ 核半径 r 核尺寸
0.5 2 5×5
1.0 3 7×7(或用 3-tap 近似)
1.4 5 11×11(或用 5-tap 近似)
2.0 6 13×13(或用 7-tap 近似)

本框架的预定义核使用 Pascal 三角近似,这是高斯核的整数近似(误差很小):

复制代码
σ≈1.0(3-tap):  [1, 2, 1] / 4       = [0.25, 0.5, 0.25]
σ≈1.4(5-tap):  [1, 4, 6, 4, 1] / 16 = [0.0625, 0.25, 0.375, 0.25, 0.0625]
σ≈2.0(7-tap):  [1, 6, 15, 20, 15, 6, 1] / 64

Pascal 三角的每一行正好是二项式展开系数,形状与高斯核极为接近。


四、可分离性:高斯模糊最重要的性质

二维高斯 = 水平一维 × 垂直一维

复制代码
G₂D(x, y) = (1/2πσ²) · exp(-(x²+y²)/2σ²)
           = [(1/√(2πσ²)) · exp(-x²/2σ²)] × [(1/√(2πσ²)) · exp(-y²/2σ²)]
           = G₁D(x) × G₁D(y)

二维高斯核可以分解为两个一维高斯核的乘积

为什么这很重要?

方法一:直接 2D 卷积

复制代码
每个像素 = kW × kH 次乘加
全图复杂度 = W × H × kW × kH

5×5 核,100×100 图:100×100×25 = 250,000 次运算

方法二:可分离(先水平再垂直)

复制代码
水平 pass:每像素 kW 次,全图 = W × H × kW
垂直 pass:每像素 kH 次,全图 = W × H × kH
总计 = W × H × (kW + kH)

5×5 核,100×100 图:100×100×(5+5) = 100,000 次运算
→ 节省 60%!

更大核时,节省更显著

核尺寸 2D 直接 可分离 节省比例
3×3 9 ops 6 ops 33%
5×5 25 ops 10 ops 60%
7×7 49 ops 14 ops 71%
15×15 225 ops 30 ops 87%
k×k k² ops 2k ops (k-2)/k

可分离性是高斯模糊的核心优化,不懂这个就无法理解为什么高斯模糊在工业中被广泛使用。


五、可分离实现的正确性证明

复制代码
可分离 = 先水平卷积,再垂直卷积

设水平核 H = [h₋₁, h₀, h₁](1D)
  垂直核 V = [v₋₁, v₀, v₁](1D)

水平卷积后:
  temp[x, y] = Σ input[x+i, y] · H[i]
                i

再做垂直卷积:
  output[x, y] = Σ temp[x, y+j] · V[j]
                  j
               = Σ (Σ input[x+i, y+j] · H[i]) · V[j]
                  j   i
               = Σ Σ input[x+i, y+j] · H[i] · V[j]
                  i j
               = Σ Σ input[x+i, y+j] · kernel2D[i][j]
                  i j

其中 kernel2D[i][j] = H[i] · V[j]
这正是 2D 卷积的定义,证毕。

六、实现:水平 + 垂直两 Pass

swift 复制代码
public func apply(to bitmap: MLBitmap) -> MLBitmap {
    let kernel1D = makeKernel1D(for: radius)
    // 先水平卷积,再垂直卷积,等效于 2D 高斯卷积
    let horizontal = applyHorizontal(bitmap, kernel: kernel1D)
    return applyVertical(horizontal, kernel: kernel1D)
}

关键设计:显式独立输出缓冲区

swift 复制代码
private func applyHorizontal(_ bitmap: MLBitmap, kernel: [Float]) -> MLBitmap {
    let kRadius = kernel.count / 2

    // 显式复制,而非依赖 CoW 隐式分离
    // 这让读写分离在代码层面清晰可见
    var outputPixels = bitmap.pixels   // 复制(包括 Alpha 通道)
    let src = bitmap.pixels            // 只读源

    for y in 0..<bitmap.height {
        for x in 0..<bitmap.width {
            var sumR: Float = 0
            var sumG: Float = 0
            var sumB: Float = 0

            for k in 0..<kernel.count {
                let px  = min(max(x + k - kRadius, 0), bitmap.width - 1)
                let idx = bitmap.index(x: px, y: y)
                let w   = kernel[k]
                sumR += Float(src[idx])     * w
                sumG += Float(src[idx + 1]) * w
                sumB += Float(src[idx + 2]) * w
            }

            let i = bitmap.index(x: x, y: y)
            outputPixels[i]     = UInt8(clamping: Int(sumR.rounded()))
            outputPixels[i + 1] = UInt8(clamping: Int(sumG.rounded()))
            outputPixels[i + 2] = UInt8(clamping: Int(sumB.rounded()))
            // outputPixels[i+3] 已从 bitmap.pixels 复制,Alpha 保持不变
        }
    }

    return MLBitmap(width: bitmap.width, height: bitmap.height, pixels: outputPixels)
}

为什么显式独立缓冲区比 CoW 更安全?

隐式 CoW 写法

swift 复制代码
var result = bitmap   // 还没写入,result 和 bitmap 共享底层存储
result.pixels[0] = 1  // 第一次写入时,CoW 触发,result 分离为独立副本
// 之后读 bitmap,写 result,是正确的

问题:如果有人"优化"成 let src = result.pixels(而非 bitmap.pixels),在 CoW 触发后,src 指向的是旧的共享存储,但 result.pixels 的写入已经在新存储上------这会产生微妙的 bug,很难察觉。

显式写法 让意图清晰:src = bitmap.pixels 明确说明"我在读原始数据",任何人修改时都能看出错误。


七、动态核生成

对于自定义 σ,需要动态计算核:

swift 复制代码
private func gaussianKernel1D(sigma: Float) -> [Float] {
    precondition(sigma > 0, "sigma must be positive")

    let r    = Int(ceil(3 * sigma))   // 半径:覆盖 ±3σ(99.7% 能量)
    let size = 2 * r + 1             // 奇数尺寸

    var kernel = [Float](repeating: 0, count: size)
    var sum: Float = 0

    for i in 0..<size {
        let x = Float(i - r)          // 相对中心的偏移(-r ~ 0 ~ +r)
        kernel[i] = exp(-x * x / (2 * sigma * sigma))  // 高斯函数(省略常数项)
        sum += kernel[i]
    }

    // 归一化:权重之和 = 1,保证亮度不变
    return kernel.map { $0 / sum }
}

为什么省略常数项 1/√(2πσ²)

因为最后要归一化(除以 sum),常数项会被消掉,省略它不影响结果,但减少了计算量。


八、高斯模糊 vs 均值模糊的视觉对比

对同一张图像:

操作 描述 视觉特点
不处理 原图 清晰,有噪点
均值模糊 3×3 Box Filter 轻微模糊,边缘略有"阶梯感"
高斯模糊 σ=1 3-tap 平滑自然,无阶梯感
高斯模糊 σ=2 7-tap 更模糊,细节减少,但依然自然

频域解释:高斯模糊的频域响应也是高斯形状(高斯函数是自身的傅里叶变换),这是其不产生振铃效应的根本原因。均值模糊的频域响应是 sinc 函数,有旁瓣,会产生振铃。


九、应用场景

场景 使用原因
Sobel 预处理 消除噪点,避免噪点被误识别为边缘
人像美化 皮肤磨皮(模糊皮肤,保留边缘)
景深效果 模糊背景,突出主体
缩略图生成 先模糊再采样,避免摩尔纹
图像去噪 高斯噪声 + 高斯模糊 = 降噪(但会丢失细节)

十、小结

概念 核心内容
高斯函数 G(x)=exp(-x²/2σ²),距离越远权重越小
σ 的意义 控制模糊半径,核尺寸 ≈ 6σ+1
可分离性 2D 高斯 = 水平 1D × 垂直 1D,复杂度从 O(k²) 降至 O(k)
Pascal 近似 整数权重近似高斯核,无需浮点运算(实际本框架用浮点)
归一化 权重之和必须 = 1,否则亮度改变
比均值好 无振铃效应,更接近自然光学模糊

思考题

  1. 为什么 sigma = 0 的高斯核等价于恒等核(不做任何处理)?
  2. 对同一张图像先后做两次高斯模糊(σ₁ 和 σ₂),等效于一次 σ = √(σ₁² + σ₂²) 的高斯模糊,这个性质叫什么?它对实际应用有什么意义?
  3. "先缩小图像再放大"和"直接高斯模糊"在视觉效果上有什么区别?哪种方式产生的模糊更接近高斯模糊?

答案:1. σ=0 时 exp(-x²/0) 在 x=0 是 1,x≠0 是 0,即恒等核,只保留中心权重;2. 叫"高斯卷积的加法性质"或"卷积的递推性",意味着可以用多次小模糊替代一次大模糊,在 Metal 中特别有用(可以多次 ping-pong 渲染);3. 缩小再放大会产生像素化/方块感,高斯模糊更自然平滑,视觉质量更好。

如果这篇对你有一点启发:

点个赞,让更多人少踩一个坑

转发给那个正在纠结的人

也欢迎关注我------

我们一起,把认知变成长期复利。

往期推荐:

一图了解几种常用卷积核
一图了解卷积的核心原理
一张图带你了解------卷积到底是什么?
一图了解饱和度:控制色彩鲜艳程度的关键
一图了解OCR的处理流程及相关图像处理技术
一图了解二值化与阈值,从灰度到黑白的决策
一张图了解图像处理中的亮度、对比度与实现
颜色科学与灰度化
从"图片"到"内存"------你真正理解图像处理的第一天
iPhone相册背后的图像处理知识(下)
iPhone相册背后的图像处理知识(中)
iPhone相册背后的图像处理知识(上)
一张图了解图像处理的本质
图像到底是什么图像处理技术概要图
AI时代,软件工程师必备概念全景图

相关推荐
中科GIS地理信息培训2 小时前
【ArcGIS Pro 3.7新增功能2】新型高光谱图像工具:连续谱去除、PCA与 MNF 降低数据复杂性、使用波长直接计算、支持STAC等
人工智能·arcgis·目标跟踪
hughnz2 小时前
执行数字化建井计划——提升钻井过程自动化
人工智能·机器人
武子康2 小时前
调查研究-141 全球机器人产业深度调研报告【03篇】机器人产业六大利润池:从核心零部件到软件平台的商业逻辑
人工智能·ai·机器人·具身智能·openclaw·调查报告·hermesagent
天行健,君子而铎2 小时前
AI赋能·精准适配——知影-API风险监测系统筑牢教育数据流转安全防线
大数据·人工智能·安全
XTIOT6662 小时前
俄罗斯诚信标签Chestny ZNAK技术约束分析与智能化应对思路
大数据·人工智能·嵌入式硬件·物联网
朴马丁2 小时前
流程PLM的智能化未来:AI与数字孪生如何赋能工艺优化与预测性运营
大数据·人工智能·ai·流程行业plm
Dfreedom.2 小时前
目标检测演进之路:从手工设计到数据驱动
人工智能·目标检测·计算机视觉·cv
@大迁世界2 小时前
iPhone 18e,可能不再“低一档”
ios·iphone
星纬智联技术2 小时前
AI搜索引擎正在改变引用标准:品牌内容需要重建哪些内容判断体系
人工智能·aigc·搜索引擎优化