Question:
实现一个函数来完成 2 维离散傅里叶变换和反变换(DFT 和 IDFT)。函数格式为“dft2d (input_img,flags) → output_img”,该函数返回 DFT / IDFT 的结果。“flags”是一个参数,用于指定 DFT 或IDFT。如有需要,你可以修改该函数的格式。请载入你的输入图像,用你的程序来完成:
1. 对输入图像做离散傅里叶变换(DFT),并且把中心化后的傅里叶频谱粘贴到报告里。
2. 对上一个问题的结果做离散傅里叶反变换(IDFT),并把实部粘贴到报告里。 注意:实部与输入图像非常相似。
3. 详细描述你是如何实现 DFT / IDFT 的,也就是说,针对“dft2d”函数进行算法说明,字数不能超过两页。请集中在算法方面,不要简单地复制/粘贴代码。
Answer:
function [temp3] = dft2d(I,flag) %读取原图像 if isstr(I) img = imread(I); end [M,N] = size(img); %取出图像高度和宽度 temp1=double(img);%将矩阵转为浮点型便于计算 temp=temp1; s = 0; %中心化 if (flag == 0) for x=1:M for y=1:N if rem(x+y,2) temp1(x,y) = -temp1(x,y); end end end end %傅里叶变换,采用的是将二维DFT转为两个一维DFT %变换的第一部分,temp2为中间变量矩阵 for x=1:M for v=1:N for y=1:N s = s + temp1(x,y) * exp((-1i) * 2 * pi * v * y / N); end temp2(x,v) = s; s = 0; end end %变换的第二部分,temp为未进行中心化的生成矩阵,temp3为中心化后并通过傅里叶变换产生的频谱图 for u=1:M for v=1:N for x=1:M s = s + temp2(x,v) * exp((-1i) * 2 * pi * u * x / M); end temp(u,v) = s; temp3(u,v) = log(abs(s)); s = 0; end end %对频谱图标定 if (flag == 0) max = 0; for u=1:M for v=1:N if (temp3(u,v) > max) max = temp3(u,v); end end end scale = 256/max; for u=1:M for v=1:N temp3(u,v) = temp3(u,v) * scale; end end figure subplot(221) imshow(img)%显示原图像 axis on title(['原图像']); subplot(222) %imshow(temp3,[]) imshow(uint8(temp3)) axis on title(['傅里叶变换']); end %作傅里叶反变换,方法跟傅里叶正变换一样,都是采用二维转一维 if (flag == 1) for u=1:M for y=1:N for v=1:N s = s + temp(u,v) * exp((1i) * 2 * pi * v * y / N); end temp4(u,y) = s; s = 0; end end for x=1:M for y=1:N for u=1:M s = s + temp4(u,y) * exp((1i) * 2 * pi * u * x / M) / M; end temp5(x,y) = real(s); %temp5为反变换后的矩阵 s = 0; end end %标定 max = 0; for u=1:M for v=1:N if (temp5(u,v) > max) max = temp5(u,v); end end end scale = 256/max; for u=1:M for v=1:N temp5(u,v) = temp5(u,v) * scale; end end figure subplot(221) imshow(img)%显示原图像 axis on title(['原图像']); subplot(222) %imshow(temp5,[])%显示反变换图像 imshow(uint8(temp5)) axis on title(['反变换图像']); end
Algorithm description:
傅里叶正变换和反变换都是采用一样的方法,就是利用二维 DFT 的可分性,将二维变 换转为一维变换。按照书本所给公式,实现两个三重循环即可。公式如下:
代码实现如下: 傅里叶正变换: %傅里叶变换,采用的是将二维 DFT 转为两个一维 DFT %变换的第一部分,temp2 为中间变量矩阵 for x=1:M for v=1:N for y=1:N s = s + temp1(x,y) * exp((-1i) * 2 * pi * v * y / N); end temp2(x,v) = s; s = 0; end end %变换的第二部分,temp 为未进行中心化的生成矩阵,temp3 为中心化后并通过傅里叶变换产 生的频谱图 for u=1:M for v=1:N for x=1:M s = s + temp2(x,v) * exp((-1i) * 2 * pi * u * x / M); end temp(u,v) = s; temp3(u,v) = log(abs(s)); s = 0; end End 傅里叶反变换: %作傅里叶反变换,方法跟傅里叶正变换一样,都是采用二维转一维 if (flag == 1) for u=1:M for y=1:N for v=1:N s = s + temp(u,v) * exp((1i) * 2 * pi * v * y / N); end temp4(u,y) = s; s = 0; end end for x=1:M for y=1:N for u=1:M s = s + temp4(u,y) * exp((1i) * 2 * pi * u * x / M) / M; end temp5(x,y) = real(s); %temp5 为反变换后的矩阵 s = 0; end end