维纳滤波器无法通过相同大小的卷积对模糊图像进行过滤
Wiener filter failed for blurry image by same size convolution
我正在 MATLAB 中测试维纳滤波器以恢复模糊图像。我正在使用 conv2() 来模糊原始图像。如果我对 conv2() 使用 'full' 选项,一切正常。但是当我改成'same'或者'valid'的时候,恢复后的图像突然出现了很多伪影,维纳滤波失败了。请参阅下面的模糊图像,'full' 卷积恢复,'same' 卷积恢复。
这是我对维纳滤波器的实现:
% 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);
由于在现实生活中模糊图像从来没有圆形或全卷积的形式,我怎样才能正确地实现维纳滤波器使其不依赖于图像的边界?
您为正则化参数选择了一个非常小的值 k
。这在 'full'
情况下工作正常,因为没有噪音并且输入与预期完全匹配。但是,在 'same'
的情况下,输入并不完全匹配。如果您要使用循环卷积(例如通过傅里叶域中的乘法),那么您也会得到一个精确的结果。
正则化参数的存在是为了防止小偏差放大并破坏整个输出图像。
我使用 k = 1e-2
得到了合理的结果(1e-1
使图像模糊,1e-3
仍然在整个图像中显示出很多伪影,但可以进一步 fine-tune这个值,我没有比那个付出更多的努力了)。
这是我使用的代码,有一些重要的区别:
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
函数使用大小参数。在这种情况下,最好不要用零填充图像。
kernel
图像以一种非常特殊的方式填充。 FFT 假定原点位于输入的 top-left 像素中。 fft2(kernel,dim,dim)
导致用零向右和底部填充内核,但这会使内核相对于 FFT 的原点偏移。这种偏移导致反卷积图像也发生偏移(仅移动 2 个像素,很难注意到,但请查看 img_wiener_ifft-double(img)
的 OP 代码和此代码以查看此偏移)。
我正在 MATLAB 中测试维纳滤波器以恢复模糊图像。我正在使用 conv2() 来模糊原始图像。如果我对 conv2() 使用 'full' 选项,一切正常。但是当我改成'same'或者'valid'的时候,恢复后的图像突然出现了很多伪影,维纳滤波失败了。请参阅下面的模糊图像,'full' 卷积恢复,'same' 卷积恢复。
这是我对维纳滤波器的实现:
% 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);
由于在现实生活中模糊图像从来没有圆形或全卷积的形式,我怎样才能正确地实现维纳滤波器使其不依赖于图像的边界?
您为正则化参数选择了一个非常小的值 k
。这在 'full'
情况下工作正常,因为没有噪音并且输入与预期完全匹配。但是,在 'same'
的情况下,输入并不完全匹配。如果您要使用循环卷积(例如通过傅里叶域中的乘法),那么您也会得到一个精确的结果。
正则化参数的存在是为了防止小偏差放大并破坏整个输出图像。
我使用 k = 1e-2
得到了合理的结果(1e-1
使图像模糊,1e-3
仍然在整个图像中显示出很多伪影,但可以进一步 fine-tune这个值,我没有比那个付出更多的努力了)。
这是我使用的代码,有一些重要的区别:
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
函数使用大小参数。在这种情况下,最好不要用零填充图像。kernel
图像以一种非常特殊的方式填充。 FFT 假定原点位于输入的 top-left 像素中。fft2(kernel,dim,dim)
导致用零向右和底部填充内核,但这会使内核相对于 FFT 的原点偏移。这种偏移导致反卷积图像也发生偏移(仅移动 2 个像素,很难注意到,但请查看img_wiener_ifft-double(img)
的 OP 代码和此代码以查看此偏移)。