我正在MATLAB中测试维纳滤波器以恢复模糊的图像。我正在使用conv2()来模糊原始图像。如果对conv2()使用'full'选项,则一切正常。但是,当我更改为“相同”或“有效”时,突然在恢复的图像中出现了许多伪像,并且维纳滤镜失败了。请参阅下面的模糊图像,从“完全”卷积恢复,从“相同”卷积恢复。
这是我对维纳过滤器的实现:
% load image
img = rgb2gray(imread('cameraman.jpg'));
[W, H] = size(img);
dim = 300;
img_fft = fft2(img,dim,dim);
% create blur kernel
kernel = ones(5) / 25;
kernel_fft = fft2(kernel,dim,dim);
% The option here makes huge difference 'same'/'full'/'valid'
img_blur = conv2(img,kernel,'same');
img_blur_fft = fft2(img_blur,dim,dim);
% Wiener filtering
k = 1e-5;
kernel_fft_conj = conj(kernel_fft);
img_wiener_freq = kernel_fft_conj .* img_blur_fft ./ (kernel_fft .* kernel_fft_conj + k);
img_wiener_ifft = ifft2(img_wiener_freq);
img_wiener_ifft = img_wiener_ifft(1:W,1:H);
在现实生活中,模糊的图像永远不会具有圆形或完全卷积的形式,如何正确实现维纳滤镜,使其不依赖于图像的边界?
答案 0 :(得分:1)
您为正则化参数k
选择了一个非常小的值。在'full'
情况下,此方法可以很好地工作,因为没有噪声,并且输入与预期值完全匹配。但是,在'same'
情况下,输入不完全匹配。如果要使用圆形卷积(例如,通过在傅立叶域中相乘),那么您还将获得精确的结果。
存在正则化参数是为了防止小偏差膨胀并破坏整个输出图像。
使用k = 1e-2
得到了合理的结果(1e-1
使图像模糊,1e-3
在整个图像中仍然显示出很多伪像,但是可以进一步微调该值,我没有付出更多的努力。)
这是我使用的代码,有一些重要的区别:
img = imread('cameraman.tif');
% create blur kernel
kernel = ones(5) / 25;
% The option here makes huge difference 'same'/'full'/'valid'
img_blur = conv2(img,kernel,'same');
img_blur_fft = fft2(img_blur);
% Wiener filtering
kernel_fft = padarray(kernel,size(img)-size(kernel),0,'post');
kernel_fft = circshift(kernel_fft,-floor(size(kernel)/2));
kernel_fft = fft2(kernel_fft);
k = 1e-2;
kernel_fft_conj = conj(kernel_fft);
img_wiener_freq = kernel_fft_conj .* img_blur_fft ./ (kernel_fft .* kernel_fft_conj + k);
img_wiener_ifft = ifft2(img_wiener_freq);
请注意,我没有在fft2
和ifft2
函数中使用size参数。在这种情况下,最好不要使用零填充图像。
kernel
图片以非常特定的方式填充。 FFT假定原点位于输入的左上角像素中。 fft2(kernel,dim,dim)
会导致内核在右边和底部用零填充,但这会使内核相对于FFT的原点偏移。这种移位也会使去卷积图像也发生移位(仅2像素,这很难注意到,但是请查看img_wiener_ifft-double(img)
以获得OP的代码,而此代码可以看到这种移位)。