Question:
实现一个函数来完成频率域滤波。函数格式是“filter2d_freq(input_img, filter) → output_img”, 这里的“filter”是给定的滤波器。如有需要,可以修改函数格式。根据卷积定理,你需要对给定的图片和滤4波器做离散傅里叶变换/快速傅里叶变换 (DFT / FFT),然后将他们乘起来,最后做离散傅里叶反变换/快速傅里叶反变换来获得滤波结果。因此,基于“dft2d”(或者“fft2d”)来实现“filter2d_freq”应该是比较简单的。当然,你需要注意一些细节,比如缠绕误差(wraparound error)(参加书本的第 4.7节)请载入你的输入图像,用你的程序"filter2d_freq"来完成:
1. 分别用 3 x 3,7 x 7 和 11 x 11 的均值滤波器来平滑你输入的图像,将相应的三个输出结果粘贴到报告里。
2. 用 3 x 3 的拉普拉斯滤波器来锐化你输入的图像(本上有 4 种拉普拉斯滤波器,参见图3.37,你可以使用其中任意一种),并将输出结果放在报告中。
3. 详细描述你是如何实现滤波操作的,也就是说,针对“filter2d_freq”函数进行算法说明,字数不能超过两页。
Answer:
function filter2d_freq(I,filter) %读取原图像 if isstr(I) img = imread(I); end [M,N] = size(img); %取出图像高度和宽度 [m,n] = size(filter); %取出滤波器高度和宽度 ori = double(img); % 0填充图像矩阵和滤波器 P = 2*M; Q = 2*N; f = zeros(P,Q); h = zeros(P,Q); f(1:M,1:N) = img; f(M+1:P,1:Q) = 0; f(1:M,N+1:Q) = 0; h(1:m,1:n) = filter; h(m+1:P,1:Q) = 0; h(1:m,n+1:Q) = 0; f1 = double(f); %转为double类型便于计算 h1 = double(h); s = 0; h = 0; %中心化图像和滤波器 for x=1:P for y=1:Q if rem(x+y,2) f1(x,y) = -f1(x,y); h1(x,y) = -h1(x,y); end end end %作图像和滤波器的傅里叶变化 for x=1:P for v=1:Q for y=1:Q s = s + f1(x,y) * exp((-1i) * 2 * pi * v * y / Q); h = h + h1(x,y) * exp((-1i) * 2 * pi * v * y / Q); end f2(x,v) = s; h2(x,v) = h; s = 0; h = 0; end end for u=1:P for v=1:Q for x=1:P s = s + f2(x,v) * exp((-1i) * 2 * pi * u * x / P); h = h + h2(x,v) * exp((-1i) * 2 * pi * u * x / P); end F(u,v) = s; H(u,v) = h; s = 0; h = 0; end end %作频率域乘积 for u=1:P for v=1:Q G(u,v) = H(u,v) * F(u,v); end end %作图像和滤波器的傅里叶反变换 for u=1:P for y=1:Q for v=1:Q s = s + G(u,v) * exp((1i) * 2 * pi * v * y / Q); end g1(u,y) = s; s = 0; end end for x=1:P for y=1:Q for u=1:P s = s + g1(u,y) * exp((1i) * 2 * pi * u * x / P) / P; end g2(x,y) = real(s); %取实部 s = 0; end end %再次中心化 for x=1:P for y=1:Q if rem(x+y,2) g2(x,y) = -g2(x,y); end end end %截取M*N大小矩阵 for x=1:M for y=1:N g(x,y) = g2(x,y); end end %输出结果 figure subplot(221) imshow(img)%显示原图像 axis on title(['原图像']); max = 0; for u=1:M for v=1:N if (g(u,v) > max) max = g(u,v); end end end scale = 256/max; for u=1:M for v=1:N g(u,v) = g(u,v) * scale; end end %g = ori - g; 拉普拉斯算子使用该公式;如果算子中间像素为正数,请把‘-’变‘+’; subplot(222) imshow(uint8(g))%显示滤波后图像; axis on title(['滤波后图像']);
Algorithm description:
我是根据书本 4.7.3 节内容按照它所描述的步骤一步步实现频率域滤波算法的。具体步骤 如下: 1. 选择填充参数 P=2M,Q=2N; 2. 对输入图像和滤波器补 0,生成 P*Q 大小的图像矩阵和滤波器; 3. 中心化,用(1) x y 乘以图像矩阵以及滤波器移到其变换的中心; 4. 计算图像跟滤波器的 DFT,生成 F(u,v)和 H(u,v); 5. 用阵列相乘形成乘积 G(u,v) = H(u,v) * F(u,v); 6. 作傅里叶反变换,公式为: g(x,y) = {real[Ʒ-1[G(u,v)]]} * (1) x y 7. 从 g(x,y)的左上限提取 M*N 区域,得到最终处理结果 g(x,y)。 相关代码: 矩阵补 0: % 0 填充图像矩阵和滤波器 P = 2*M; Q = 2*N; f = zeros(P,Q); h = zeros(P,Q); f(1:M,1:N) = img; f(M+1:P,1:Q) = 0; f(1:M,N+1:Q) = 0; h(1:m,1:n) = filter; h(m+1:P,1:Q) = 0; h(1:m,n+1:Q) = 0; 中心化,傅里叶正变换和反变换跟上一个代码基本类似,就不再附上; 频率域乘积: %作频率域乘积 for u=1:P for v=1:Q G(u,v) = H(u,v) * F(u,v); end end 截取 M*N 大小图像作为输出 %截取 M*N 大小矩阵 for x=1:M for y=1:N g(x,y) = g2(x,y); end end