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. 使用说明
- 将以上 3 个文件放在同一目录,运行
demo_blindBayesNLM.m即可。 - 对彩色图自动逐通道处理,支持任意大小。
- 若需更高精度,可把
noiseEst_blind中块大小改 5×5;BayesNLM的searchR改为 7~9。
参考 图像降噪、贝叶斯估计、盲源降噪,采用盲源方法进行噪声估计,再进行贝叶斯非局部均值降噪 www.youwenfan.com/contentcsl/64992.html
5. 算法亮点
- 盲源估计:无需人工给定 σ,适应真实相机噪声。
- 贝叶斯权重:相比传统 NLM,更好地抑制伪影,保留纹理。
- FFT 加速:专利 CN112508810A 思想,复杂度从 O(N²) 降到 O(N log N)。