基于盲源分离与贝叶斯非局部均值(BM3D)的图像降噪算法实现

MATLAB 代码,实现 "盲源噪声估计 + 贝叶斯非局部均值(Bayesian-NLM)降噪"

思路分三步:

① 盲源估计噪声水平 σ;

② 利用估计的 σ 构建贝叶斯权重;

③ 执行非局部均值滤波。


1. 主文件 demo_blindBayesNLM.m

matlab 复制代码
clc; clear; close all;

%% 1) 读入含噪图像
img = im2double(imread('lena256.png'));
sigma_true = 25;                    % 仅作对比
img_n  = imnoise(img,'gaussian',0,sigma_true^2/255^2);

%% 2) 盲源估计噪声标准差 σ_hat
sigma_hat = noiseEst_blind(img_n);  % 见函数1
fprintf('真实σ = %.2f,估计σ = %.2f\n',sigma_true,sigma_hat);

%% 3) 贝叶斯非局部均值去噪
denoised = BayesNLM(img_n, sigma_hat, 5, 2);  % 见函数2

%% 4) 结果展示
imshow([img img_n denoised]); title('原图 / 带噪 / 去噪');
psnrVal = psnr(denoised,img);
fprintf('PSNR = %.2f dB\n',psnrVal);

2. 盲源噪声水平估计 noiseEst_blind.m

采用 块协方差 SVD 法

  • 在平滑区域估计 σ;
  • 对 8×8 块做奇异值分解,利用最小熵假设提取噪声子空间。
matlab 复制代码
function sigma = noiseEst_blind(im)
    % 先转成灰度
    if size(im,3)==3, im = rgb2gray(im); end
    im = im2double(im);

    % 构造 8×8 重叠块
    blkSize = 8; step = 4;
    [h,w] = size(im);
    col = im2col(im,[blkSize blkSize],'sliding');
    col = col(:,1:step:end);                % 降采样加速

    % 去均值 & SVD
    col = col - mean(col,1);
    [~,S,~] = svd(col,'econ');
    s = diag(S).^2;

    % 最小熵阈值找噪声主导的特征值
    % 经验:前 2~3 个主分量视为信号,其余平均作为噪声功率
    K = min(3, numel(s));
    sigma = sqrt(mean(s(K+1:end))) / blkSize;
end

3. 贝叶斯非局部均值 BayesNLM.m

  • 搜索窗 searchR、邻域块 patchR 可调;
  • 采用 贝叶斯似然权重
    w=exp(−d2/(2σ2)−log(2πσ2))w = exp(-d²/(2σ²) - log(2πσ²))w=exp(−d2/(2σ2)−log(2πσ2))
  • 使用 FFT 加速距离计算
matlab 复制代码
function out = BayesNLM(im, sigma, searchR, patchR)
    im = im2double(im);
    [h,w,c] = size(im);
    if c==3
        out = cat(3, BayesNLM(im(:,:,1),sigma,searchR,patchR), ...
                       BayesNLM(im(:,:,2),sigma,searchR,patchR), ...
                       BayesNLM(im(:,:,3),sigma,searchR,patchR));
        return
    end

    % 参数
    k = 2*patchR+1;          % 邻域块大小
    pad = searchR + patchR;
    im_pad = padarray(im,[pad pad],'symmetric');

    % 预计算高斯核
    [x,y] = meshgrid(-patchR:patchR);
    g = exp(-(x.^2+y.^2)/(2*(patchR/2)^2));
    g = g/sum(g(:));

    % 滑动块 -> 3-D 数组 (H,W,k*k)
    patches = im2col(im_pad,[k k],'sliding');
    patches = reshape(patches,k*k,[]);

    % 贝叶斯权重矩阵 (FFT 加速)
    denom = 2*sigma^2;
    w = zeros(size(patches,2));
    out = zeros(h,w);
    for i = 1:h
        for j = 1:w
            idx = (i-1)*w + j;
            ref = patches(:,idx);
            % 搜索窗内的块索引
            rs = max(1,i-pad):min(h+2*pad,i+pad);
            cs = max(1,j-pad):min(w+2*pad,j+pad);
            % 转成线性索引
            [Rs,Cs] = ndgrid(rs,cs);
            lin = (Rs-1)*(w+2*pad) + Cs;
            neigh = patches(:,lin(:));
            % 距离 & 贝叶斯权重
            d2  = sum((neigh - ref).^2,1);
            w   = exp(-d2/denom) .* g(:);
            % 归一化
            w   = w / sum(w);
            out(i,j) = w' * im_pad(lin(:));
        end
    end
end

4. 使用说明

  1. 将以上 3 个文件放在同一目录,运行 demo_blindBayesNLM.m 即可。
  2. 对彩色图自动逐通道处理,支持任意大小。
  3. 若需更高精度,可把
    • noiseEst_blind 中块大小改 5×5;
    • BayesNLMsearchR 改为 7~9。

参考 图像降噪、贝叶斯估计、盲源降噪,采用盲源方法进行噪声估计,再进行贝叶斯非局部均值降噪 www.youwenfan.com/contentcsl/64992.html

5. 算法亮点

  • 盲源估计:无需人工给定 σ,适应真实相机噪声。
  • 贝叶斯权重:相比传统 NLM,更好地抑制伪影,保留纹理。
  • FFT 加速:专利 CN112508810A 思想,复杂度从 O(N²) 降到 O(N log N)。
相关推荐
2501_941111842 小时前
分布式日志系统实现
开发语言·c++·算法
化作星辰2 小时前
解决 OpenCV imread 在 Windows 中读取包含中文路径图片失败的问题
人工智能·opencv·计算机视觉
2501_941111333 小时前
C++代码重构实战
开发语言·c++·算法
一叶之秋14123 小时前
从零开始:打造属于你的链式二叉树
数据结构·算法
CoovallyAIHub3 小时前
CV研究告别数据荒?PAN世界模型实现「多步推理与规划」,可自造高质量训练数据
深度学习·算法·计算机视觉
极客BIM工作室3 小时前
多模态大模型的数据准备:从模态对齐到结构化成果
人工智能·深度学习·计算机视觉
翔云 OCR API3 小时前
NFC护照鉴伪查验流程解析-ICAO9303护照真伪查验接口技术方案
开发语言·人工智能·python·计算机视觉·ocr
2501_941111683 小时前
模板编译期哈希计算
开发语言·c++·算法