基于盲源分离与贝叶斯非局部均值(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)。
相关推荐
Fuxiao___42 分钟前
C 语言核心知识点讲义(循环 + 函数篇)
算法·c#
漫随流水1 小时前
c++编程:反转字符串(leetcode344)
数据结构·c++·算法
穿条秋裤到处跑3 小时前
每日一道leetcode(2026.03.31):字典序最小的生成字符串
算法·leetcode
MyBFuture3 小时前
Halcon 金字塔与边缘检测技术解析
人工智能·计算机视觉·halcon
Westward-sun.4 小时前
基于 OpenCV DNN 模块实现图像风格迁移
人工智能·神经网络·opencv·计算机视觉·dnn
CoovallyAIHub5 小时前
VisionClaw:智能眼镜 + Gemini + Agent,看一眼就能帮你搜、帮你发、帮你做
算法·架构·github
模拟器连接器曾工5 小时前
PLC视觉检测原理有哪些?
人工智能·计算机视觉·视觉检测·plc视觉检测
CoovallyAIHub5 小时前
低空安全刚需!西工大UAV-DETR反无人机小目标检测,参数减少40%,mAP50:95提升6.6个百分点
算法·架构·github
CoovallyAIHub5 小时前
IEEE Sensors | 湖南大学提出KGP-YOLO:先定位风电叶片再检测缺陷,三数据集mAP均超87%
算法
Yupureki5 小时前
《算法竞赛从入门到国奖》算法基础:动态规划-路径dp
数据结构·c++·算法·动态规划