Rust图像处理第24节- 噪声模型 + 中心极限定理:椒盐噪声 + CLT 可视化

🦀 Rust + WASM 实战系列 第 24 篇 阅读时间:约 5 分钟 | 实战可运行

📌 写在前面

任务 23 讲了怎么采 高斯和泊松噪声------这一篇讲第三种噪声(椒盐) + 一个为什么高斯无处不在的原理(中心极限定理)。

内容 物理场景 算法
椒盐噪声 老电视雪花、损坏照片 概率置 0/255
中心极限定理 解释"为什么高斯无处不在" 多个均匀之和 → 钟形

🚀 TL;DR

核心概念:

  • 椒盐噪声 = 每个像素 density 的概率被随机设为 0(黑)或 255(白)

  • CLT = 多个独立同分布随机变量之和 → 趋向正态分布(无论单个是什么分布)

    1 个均匀 → 矩形分布
    2 个之和 → 三角形
    4 个之和 → 鼓包
    12 个之和 → 几乎完美的正态


📖 目录

  1. 椒盐噪声:最简单也最暴力
  2. [3 种噪声对比(高斯 / 泊松 / 椒盐)](#3 种噪声对比(高斯 / 泊松 / 椒盐) "#%E4%BA%8C3-%E7%A7%8D%E5%99%AA%E5%A3%B0%E5%AF%B9%E6%AF%94%E9%AB%98%E6%96%AF--%E6%B3%8A%E6%9D%BE--%E6%A4%92%E7%9B%90")
  3. 中心极限定理:为什么高斯无处不在
  4. [CLT 可视化实现](#CLT 可视化实现 "#%E5%9B%9Bclt-%E5%8F%AF%E8%A7%86%E5%8C%96%E5%AE%9E%E7%8E%B0")
  5. 关键代码
  6. 前端效果展示
  7. 踩坑提醒
  8. 接下来

一、椒盐噪声:最简单也最暴力

算法(伪代码):

csharp 复制代码
for each pixel:
    if random() < density:
        if random() < 0.5:
            pixel = 0        // 黑点
        else:
            pixel = 255      // 白点
  • density:噪声像素占比(0~1)
  • 黑点白点各 50%------所以叫"椒盐"

Rust 代码:

rust 复制代码
#[wasm_bindgen]
pub fn salt_pepper_noise(pixels: &[u8], w: u32, h: u32, density: f32) -> Vec<u8> {
    for i in 0..n {
        let r = uniform_random();
        if r < density {
            // 随机设黑或白
            if (x & 1) == 0 {
                out[idx] = 0;
                // ...
            } else {
                out[idx] = 255;
                // ...
            }
        }
    }
}

二、3 种噪声对比(高斯 / 泊松 / 椒盐)

噪声 物理模型 算法 视觉 真实场景
高斯 N(0,σ2)N(0, \sigma^2) N(0,σ2) Box-Muller 平滑小波动 传感器热噪声
泊松 Poisson(λ)\text{Poisson}(\lambda) Poisson(λ) Knuth 颗粒感(暗处明显) 暗光摄影、医学影像
椒盐 概率置 0/255 随机数 黑白点散布 老电视、数据错误

三、中心极限定理:为什么高斯无处不在

定理(简化版):

多个独立的随机变量之和 → 当数量足够大时 ,趋向正态分布。

不管单个变量是什么分布!

直觉例子

n 个均匀分布之和 形状
1 矩形
2 三角形
3 鼓包
4 接近钟形
8 几乎正态
12 完全正态

关键 :每个均匀都是平的,但 12 个加起来 → 漂亮的钟形。

现实世界

几乎所有"复杂现象"都符合 CLT:

  • 测量误差 = 仪器误差 + 读数误差 + 温度漂移 + ...(多个独立随机)
  • 人类身高 = 基因 + 营养 + 运动 + 睡眠 + ...(多个独立因素)
  • 股票价格变化 = 无数交易者的买卖决策之和
  • 图像噪声 = 多个电路/光学噪声源叠加

→ 都近似正态 → 高斯无处不在


四、CLT 可视化实现

CLT 不需要 WASM------用 Math.random() 算就行,更简单更快:

javascript 复制代码
function computeHistogram(n) {
  // n = 几个均匀分布之和
  const N_SAMPLES = 10000
  const N_BINS = 40
  const bins = new Array(N_BINS).fill(0)

  for (let i = 0; i < N_SAMPLES; i++) {
    let sum = 0
    for (let j = 0; j < n; j++) {
      sum += Math.random()  // 0~1
    }
    // sum ∈ [0, n],归一化到 bin
    const bin = Math.floor(sum / n * N_BINS)
    bins[bin]++
  }
  return bins
}

滑块 n=1~12------读者拖动看柱状图从"矩形"变成"钟形"。

五、关键代码

rust 复制代码
#[wasm_bindgen]
pub fn salt_pepper_noise(pixels: &[u8], width: u32, height: u32, density: f32) -> Vec<u8> {
    let mut out = pixels.to_vec();
    let n = (width * height) as usize;
    let d = density.clamp(0.0, 1.0) as f64;

    for i in 0..n {
        // xorshift64 PRNG(同任务 23 的实现)
        let r = (xorshift_next() >> 11) as f64 / (1u64 << 53) as f64;
        
        if r < d {
            let idx = i * 4;
            if /* random bit */ {
                out[idx] = 0; out[idx+1] = 0; out[idx+2] = 0;  // 黑
            } else {
                out[idx] = 255; out[idx+1] = 255; out[idx+2] = 255;  // 白
            }
        }
    }
    out
}

核心 5 行------和第 23 节一样用自实现 PRNG。


六、前端效果展示

七、踩坑提醒

1. 椒盐 density 不能超过 0.5

rust 复制代码
let d = density.clamp(0.0, 1.0) as f64;

50% 时图基本全黑/全白------没有意义。前端限制 0~0.5。

2. 椒盐 = 模拟"传输错误",不是"自然噪声"

用途 适合
模拟老电视、坏照片 ✅ 椒盐
模拟真实相机噪声 ❌ 用泊松
模拟电子电路噪声 ❌ 用高斯

不要混用------它们是不同的物理模型。

3. CLT 需要 n > 30 才严格成立

我们画 n=1~12 主要是直觉演示------严格数学上 n ≥ 30 才"近似"。


八、接下来

任务 25:图像增强(自适应阈值 + 直方图均衡化)

任务 24 讲怎么加噪(破坏) 任务 25 讲怎么还原(修复)

两个工具:

  • 自适应阈值:处理光照不均
  • 直方图均衡化:让暗图变清晰

任务 26:概率驱动图像生成(随机游走 + 马尔可夫链 + 图像合成 + 修复)


一句话总结

椒盐噪声 = 概率置 0/255(最简单、最暴力)。

CLT = 多个独立随机变量之和 → 正态分布。

滑块 1~12 看柱状图从"平"变"钟"------为什么高斯无处不在的直觉。


📦 项目地址 :pixel-math-wasm 🦀 Rust + WebAssembly 实战系列


🏷️ 标签 :#Rust #WebAssembly #图像处理 #椒盐噪声 #中心极限定理 #高斯分布 #CLT

相关推荐
JavaPub-rodert13 分钟前
王仕宇分享:Oxigraph 是什么?用 Rust + RocksDB 搭一个轻量 RDF/SPARQL 知识图谱数据库
数据库·rust·知识图谱
tedcloud1232 小时前
Docker Compose 部署 Memos:从安装到备份恢复
linux·开发语言·jvm·后端·docker·容器·rust
l1t4 小时前
pgrust v0.4-beta 安装和查询测试
数据库·postgresql·rust·duckdb·pgrust
运维开发笔记12 小时前
5.Rust 向量(Vec)入门指南
rust
传奇开心果编程16 小时前
【Rust入门练中学】第5课:引用与借用
开发语言·rust·引用·编程语言理论·通用编程语言·借用
geovindu21 小时前
rust: Mediator Pattern
开发语言·后端·设计模式·rust·中介者模式·行为模式
传奇开心果编程21 小时前
【Rust入门练中学】第8课:错误处理
开发语言·rust·错误处理·编程语言理论·通用编程语言
传奇开心果编程1 天前
【Rust入门练中学】第9课:集合类型
开发语言·rust·编程语言理论·集合类型·通用编程语言
人人都是软件工程师1 天前
📚 Tesla AI 总监:让 LLM 把文档"编译"成持续生长的知识库 llm_wiki
人工智能·rust·开源
dennislee6661 天前
项目一多,终端标签就失控了:我用 Rust 写了个 macOS 启动工作台,还让 AI 能自己重启服务
rust