维纳滤波—deconvwnr函数利用维纳滤波器来对图像模糊修复
function image_restoration_deconvwnr()
%Read image
I = im2double(imread('lena.tif'));
I=rgb2gray(I);
figure,subplot(2,3,1),imshow(I);
title('Original Image');
%Simulate a motion blur
LEN = 21;
THETA = 11;
PSF = fspecial('motion', LEN, THETA); %获得滤波算子 PSF
blurred = imfilter(I, PSF, 'conv', 'circular');
subplot(2,3,2),imshow(blurred);
title('Blurred Image');
%Restore the blurred image
wnr1 = deconvwnr(blurred, PSF, 0);
subplot(2,3,3),imshow(wnr1);
title('Restored Image');
%Simulate blur and noise
noise_mean = 0;
noise_var = 0.0001;
blurred_noisy = imnoise(blurred, 'gaussian', ...
noise_mean, noise_var);
subplot(2,3,4),imshow(blurred_noisy)
title('Simulate Blur and Noise')
%Restore the blurred and noisy image:First attempt
wnr2 = deconvwnr(blurred_noisy, PSF, 0);
subplot(2,3,5);imshow(wnr2);title('Restoration of Blurred, Noisy Image Using NSR = 0')
%Restore the Blurred and Noisy Image: Second Attempt
signal_var = var(I(:));
wnr3 = deconvwnr(blurred_noisy, PSF, noise_var / signal_var);
subplot(2,3,6),imshow(wnr3)
title('Restoration of Blurred, Noisy Image Using Estimated NSR');
end
维纳滤波需要估计图像的信噪比(SNR)或者噪信比(NSR),信号的功率谱使用图像的方差近似估计,噪声分布是已知的。从第一排中可以看出,若无噪声,此时维纳滤波相当于逆滤波,恢复运动模糊效果是极好的。从第二排可以看出噪信比估计的准确性对图像影响比较大的,二排中间效果几乎不可用。
逆滤波
function image_restoration_matlab()
% Display the original image.
I = im2double(imread('lena.tif'));
I=rgb2gray(I);
[hei,wid,~] = size(I);
subplot(2,3,1),imshow(I);
title('Original Image (courtesy of MIT)');
% Simulate a motion blur.
LEN = 21;
THETA = 11;
PSF = fspecial('motion', LEN, THETA);
blurred = imfilter(I, PSF, 'conv', 'circular');
subplot(2,3,2), imshow(blurred); title('Blurred Image');
% Inverse filter
If = fft2(blurred);
Pf = fft2(PSF,hei,wid);
deblurred = ifft2(If./Pf);
subplot(2,3,3), imshow(deblurred); title('Restore Image')
% Simulate additive noise.
noise_mean = 0;
noise_var = 0.0001;
blurred_noisy = imnoise(blurred, 'gaussian', ...
noise_mean, noise_var);
subplot(2,3,4), imshow(blurred_noisy)
title('Simulate Blur and Noise')
% Try restoration assuming no noise.
If = fft2(blurred_noisy);
deblurred2 = ifft2(If./Pf);
subplot(2,3,5), imshow(deblurred2)
title('Restoration of Blurred Assuming No Noise');
% Try restoration with noise is known.
noisy = blurred_noisy - blurred;
Nf = fft2(noisy);
deblurred2 = ifft2(If./Pf - Nf./Pf);
subplot(2,3,6), imshow(deblurred2)
title('Restoration of Blurred with Noise Is Known')
end
逆滤波对噪声非常敏感,除非我们知道噪声的分布情况(事实上,这也很难知道),逆滤波几乎不可用,可以从二排中间看出,恢复图像效果极差。但若知道噪声分布,也是可以完全复原信息的。可以从二排最后一张图可以看出。
注:图像恢复时需要用到 PSF 卷积核,该卷积核为生成运动模糊得卷积核,在实际应用场景是不知道的。
如何求解: PSF
PSF 是由 LEN 和 Theta 决定的,如果能求出 运动模糊的方向,和对应的偏移量就能求出 PSF
1、基本原理:
点扩散函数PSF主要有两个重要参数:(1)模糊方向;(2)模糊尺度。本次主要是针对第一个参数----模糊方向的估计进行了研究。运动模糊方向是指运动方向与水平方向的夹角,由文献得知运动模糊主要是降低了运动方向的高频成分,而对其他方向的高频成分影响较小。常见的辨识方法有频域法和倒谱法,wym 两种方法都试过,仿真实验结果表两种方法各有好处。
频域法的原理是将退化图像进行二维傅里叶变换,得到具有相互平行的规则明暗条纹的频谱。设暗纹与 x 轴正向夹角为 φ ,运动模糊方向与 x 轴夹角为 θ ,图像尺寸为 M × N,根据傅里叶变换的时频特性可以知道,可通过公式 tan(θ) = tan(φ − 90°) × M/N 得到模糊角度 θ ,因此只要通过 Radon 变换检测出频谱暗条纹与水平方向的夹角即可到运动模糊方向。
倒谱法的主要原理是先将退化图像进行二维傅里叶变换,然后取对数,再进行反傅里叶变换得到退化图像的倒频谱,分离出退化图像的模糊信息,进而通过 Radon 变换得到运动模糊方向。
Radon 变换是对频谱图上某一指定角度进行线积分,通过计算1°~180°的Radon变换得到180列的矩阵 R,每一列向量是图像在一个角度上沿一族直线的积分投影,因为积分直线束与频谱中的亮暗条纹平行,所以所得的投影向量中应有一个最大值,在频域法中最大值所对应的列数就等于模糊方向与x轴正方向水平夹角;在倒谱法中,最大值对应的列数 ±90°即为所求的模糊角度。
具体理论和公式推导就不列出来了。。有兴趣的同学请 STFW。。(什么?不知道什么是 STFW? 请自行 STFW。。)
2、算法实现:
(1)频域法
1) 对模糊图像进行灰度化,并计算其二维傅里叶变换;
2) 对傅里叶变换值的动态范围进行压缩;
3) 对压缩后的结果进行循环移位,使其低频成分居中;
4) 用canny算子对压缩居中后的频谱图像进行边缘检测使其二值化;
5) 将二值化后的频谱图做从1°~180°的radon变换;
6) 找出radon变换后的矩阵中的最大值,求出其对应的列数 n;
7) 通过公式 tan(θ) = tan(φ − 90°) × M/N = tan(n − 90°) × M/N 求出运动模糊方向。
实现代码:
close all;
clear all;
%% 读入并显示图像
filename = 'ex.jpg';
I = imread(filename);
figure
imshow(uint8(I));
title('原图');
%% 生成运动模糊图像
PSF = fspecial('motion',50, 120);
g = imfilter(I, PSF, 'circular');
figure
imshow(uint8(g));
title('运动模糊图');
%% 对运动模糊图像进行灰度化,并进行二维快速傅里叶变换,生成其频谱图
gb = rgb2gray(g);
figure
imshow(uint8(gb));
PQ = paddedsize(size(gb));
F = fft2(gb, PQ(1), PQ(2));
figure
imshow(uint8(F));
%% 将频谱压缩,居中
H = log(1+abs(F));
Hc = fftshift(H);
figure
imshow(uint8(Hc));
%% 用canny算子将压缩居中后的频谱图进行边缘检测,二值化
T = graythresh(Hc);
bw=edge(Hc, 'canny', T);
figure
imshow(bw);
%% 对二值化后的频谱图进行radon变换
theta = 1:180;
R = radon(bw, theta);
figure
imshow(R);
%% 计算出通过radon变换求出的模糊角度
MAX = max(max(R));
[m, n] = find(R == MAX);
[M,N] = size(Hc);
beita = atan(tan(n*pi/180)*M/N)*180/pi;
(2)倒谱法:
1) 对模糊图像进行灰度化,并计算其二维傅里叶变换;
2) 对傅里叶变换取对数,平方后再进行一次反傅里叶变换得到其倒频谱;
3) 对倒频谱动态范围进行压缩;
4) 对压缩后的结果进行循环移位,使其低频成分居中;
5) 用canny算子对压缩居中后的频谱图像进行边缘检测使其二值化;
6) 将二值化后的频谱图做从1°~180°的radon变换;
7) 找出radon变换后的矩阵中的最大值,其对应的列数±90°即为所求的模糊方向。
实现代码:
close all;
clear all;
%% 读入并显示图像
filename = 'ex.jpg';
I = imread(filename);
figure
imshow(uint8(I));
title('原图');
%% 生成运动模糊图像
PSF = fspecial('motion',80, 150);
g = imfilter(I, PSF, 'circular');
figure
imshow(uint8(g));
title('运动模糊图');
%% 对运动模糊图像进行灰度化,并进行二维快速傅里叶变换,生成其频谱图
gb = rgb2gray(g);
figure
imshow(uint8(gb));
PQ = paddedsize(size(gb));
F = fft2(gb, PQ(1), PQ(2));
figure
imshow(uint8(F));
%% 作出倒频谱
F1 = log(1+abs(F));
F2 = abs(F1).^2;
F3 = real(ifft2(F2));
figure
imshow(uint8(F3));
%% 将倒频谱压缩,居中
H = log(1+abs(F3)); % 将倒频谱动态范围进行压缩
Hc = fftshift(H); % 将压缩结果进行循环移位,使低频成分居中
figure
imshow(uint8(Hc));
%% 通过阈值处理,边缘检测“canny”算子二值化倒频谱
T = graythresh(Hc);
bw=edge(Hc, 'canny', T);
figure
imshow(bw);
%% 对倒频谱从1°到180°作radon变换,以求出模糊角度
theta = 1:180;
R = radon(bw, theta);
figure
imshow(R);
%% 计算出通过倒频谱radon变换估计出的模糊角度
MAX = max(max(R));
[m, n] = find(R == MAX);
if 90 < n <= 180
beita = n - 90;
else if 0 < n < 90
beita = n + 90;
else if n == [90;90] | n == [180;180]
beita = n(1);
end;
7、仿真结果及算法评价:
经过反复、多次、令人崩溃的调试参数,得出结论,模糊角度估计的精确度主要与边缘检测的阈值 T,运动模糊尺度和运动模糊方向这三个变量有关,经调试,阈值选取由graythresh 函数算出的全局阈值效果较好,而模糊尺度越小精度越低。
频域法:当模糊尺度大于20像素时,模糊方向处于0°~90°时,检测效果很好,误差低于0.5°,但当模糊尺度低于20像素时,由于中心化处理致使频谱图中间出现的十字亮线使模糊方向常为90°或180°;而当模糊尺度大于90°时,估计到的模糊方向像脱缰的野马。。完全不知道怎么才能估计出如此恶心的数据的。。
倒谱法:当模糊尺度大于40像素时,可以检测的模糊方向较大,基本从0°到180°都可以检测,不过误差在5°左右,模糊尺度小于40像素时误差就很大了,不能用作检测
关于偏移距离的计算 可以使用 折中法试探,每次试探一半的距离,然后根据恢复结果的图像质量进一步选取新的距离值。 关于图像质量评价可以使用纹理特征,例如 Sobel 滤波后的均值,或者 拉普拉斯算子 滤波的方差,或者取傅里叶变换后的高频信息均值。