基于盲源分离与贝叶斯非局部均值(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)。
相关推荐
Jerry4 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry6 小时前
LeetCode 459. 重复的子字符串
算法
海石8 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石8 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
Jerry10 小时前
LeetCode 151. 反转字符串中的单词
算法
a11177613 小时前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜13 小时前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry13 小时前
LeetCode 541. 反转字符串 II
算法
Jerry13 小时前
LeetCode 344. 反转字符串
算法
搞科研的小刘选手14 小时前
【香港大学主办&IEEE出版】第六届计算机视觉、应用与算法国际学术会议(CVAA 2026)
算法·计算机视觉·应用·学术会议