代码复现如下:
%% 建立正方形矩阵
clc
close all
clear all
M = 256; % 矩阵高度
N2 = 256; % 矩阵宽度
S0 = zeros(M,N2);
S0(M/8+1:M*7/8,N2/8+1:N2*7/8) = 1;
%验证
figure;colormap gray;imagesc(S0);axis off image
%% 原始信号频谱
S0_ff = fftshift(fft2(fftshift(S0)));
S0_ff = abs(S0_ff);
S0_ff = S0_ff./max(max(S0_ff));
S0_ff = 20*log10(S0_ff+1e-4);
%验证
figure;colormap gray;imagesc(S0_ff);axis off image
1.fftshift
Y = fftshift(X)
通过将零频分量移动到数组中心,重新排列傅里叶变换 X
。如果 X
是向量,则 fftshift
会将 X
的左右两半部分进行交换。如果 X
是矩阵,则 fftshift
会将 X
的第一象限与第三象限交换,将第二象限与第四象限交换。如果 X
是多维数组,则 fftshift
会沿每个维度交换 X
的半空间。fftshift(0,fs)=(-fs/2,fs/2)
2.fft2
Y = fft2(X)
使用快速傅里叶变换算法返回矩阵的二维傅里叶变换,这等同于计算 fft(fft(X).').'
。如果 X
是一个多维数组,fft2
将采用高于 2 的每个维度的二维变换。输出 Y
的大小与 X
相同。
3.abs
Y = abs(X)
返回数组 X
中每个元素的绝对值。如果 X
是复数,则 abs(X)
返回复数的模。在本代码里为取信号的模值。
4.max(max(A))
矩阵的最大值要用两次max函数,即max(max(A))为矩阵A中的最大值。
除以矩阵最大值是为了归一化。
5.+1e-4
因为矩阵中存在0值,log0=-inf
%% 扭曲信号
S1 = zeros(M,N2);%行对应于y,列对应于x
theta = pi/12;
for ii = 1:M
for jj = 1:N2
x = jj-N2/2;%移至中心
y = ii-M/2;%移至中心
At = [1 0; sin(theta) cos(theta)]*[x y].';%见书公式2.42
xx = round(At(1,1)+N2/2);
yy = round(At(2,1)+M/2);
% xx = round(x+N/2);
% yy = round(x*sin(-theta)+y*cos(-theta)+M/2);
if(xx>=1 && xx<= N2 && yy>=1 && yy<=M)
S1(ii,jj) = S0(xx,yy);
% S1(yy,xx) = S0(ii,jj);
end
end
end
%验证
figure;colormap gray;imagesc(S1);axis off image
1.round
取整函数,取四舍五入的值,若为0.5,则取离原点远的值,例如round(4.5)=5,round(-4.5)=-5
2.-N2/2,-M/2
旋转矩阵需要图像位于中心才能使用
3..'
.'为转置,‘为共轭转置
B = A.'
返回 A
的非共轭转置,即每个元素的行和列索引都会互换。如果 A
包含复数元素,则 A.'
不会影响虚部符号。例如,如果 A(3,2)
是 1+2i
且 B = A.'
,则元素 B(2,3)
也是 1+2i
。
%% 扭曲信号频谱
S1_ff=fftshift(fft2(fftshift(S1)));
S1_ff=abs(S1_ff);
S1_ff=S1_ff./max(max(S1_ff));
S1_ff=20*log(S1_ff+1e-4);
%验证
figure;colormap gray;imagesc(S1_ff);axis off image
%% 旋转信号
S2=zeros(M,N2);
for ii=1:M
for jj=1:N2
x=jj-N2/2;
y=ii-M/2;
At=[cos(theta) -sin(theta);sin(theta) cos(theta)]*[x y].';
xx=round(At(1,1)+N2/2);
yy=round(At(2,1)+M/2);
if(xx>=1&&xx<=N2&&yy>=1&&yy<=M)
S2(ii,jj)=S0(yy,xx);
end
end
end
%验证
figure;colormap gray;imagesc(S2);axis off image
%% 旋转信号频谱
S2_ff=fftshift(fft2(fftshift(S2)));
S2_ff=abs(S2_ff);
S2_ff=S2_ff/max(max(S2_ff));
S2_ff=20*log(S2_ff+1e-4);
%验证
figure;colormap gray;imagesc(S2_ff);axis off image
最后附上完整代码:
%% 建立正方形矩阵
clc
close all
clear
M = 256; % 矩阵高度
N2 = 256; % 矩阵宽度
S0 = zeros(M,N2);
S0(M/8+1:M*7/8,N2/8+1:N2*7/8) = 1;
%验证
%figure;colormap gray;imagesc(S0);axis off image
%% 原始信号频谱
S0_ff = fftshift(fft2(fftshift(S0)));
S0_ff = abs(S0_ff);
S0_ff = S0_ff./max(max(S0_ff));
S0_ff = 20*log10(S0_ff+1e-4);
%验证
%figure;colormap gray;imagesc(S0_ff);axis off image
%% 扭曲信号
S1 = zeros(M,N2);%行对应于y,列对应于x
theta = pi/12;
for ii = 1:M
for jj = 1:N2
x = jj-N2/2;%移至中心
y = ii-M/2;%移至中心
At = [1 0; sin(theta) cos(theta)]*[x y].';%见书公式2.42
xx = round(At(1,1)+N2/2);
yy = round(At(2,1)+M/2);
% xx = round(x+N/2);
% yy = round(x*sin(-theta)+y*cos(-theta)+M/2);
if(xx>=1 && xx<= N2 && yy>=1 && yy<=M)
S1(ii,jj) = S0(xx,yy);
% S1(yy,xx) = S0(ii,jj);
end
end
end
%验证
%figure;colormap gray;imagesc(S1);axis off image
%% 扭曲信号频谱
S1_ff=fftshift(fft2(fftshift(S1)));
S1_ff=abs(S1_ff);
S1_ff=S1_ff./max(max(S1_ff));
S1_ff=20*log(S1_ff+1e-4);
%验证
%figure;colormap gray;imagesc(S1_ff);axis off image
%% 旋转信号
S2=zeros(M,N2);
for ii=1:M
for jj=1:N2
x=jj-N2/2;
y=ii-M/2;
At=[cos(theta) -sin(theta);sin(theta) cos(theta)]*[x y].';
xx=round(At(1,1)+N2/2);
yy=round(At(2,1)+M/2);
if(xx>=1&&xx<=N2&&yy>=1&&yy<=M)
S2(ii,jj)=S0(yy,xx);
end
end
end
%验证
%figure;colormap gray;imagesc(S2);axis off image
%% 旋转信号频谱
S2_ff=fftshift(fft2(fftshift(S2)));
S2_ff=abs(S2_ff);
S2_ff=S2_ff/max(max(S2_ff));
S2_ff=20*log(S2_ff+1e-4);
%验证
%figure;colormap gray;imagesc(S2_ff);axis off image
%% 绘图
figure;colormap gray
subplot(2,3,1),imagesc(S0);axis off image
title('(a)时域,原始信号')
subplot(2,3,4),imagesc(S0_ff);axis off image
title('(b)原始信号频谱')
subplot(2,3,2),imagesc(S1);axis off image
title('(c)时域,扭曲信号')
subplot(2,3,5),imagesc(S1_ff);axis off image
title('(d)扭曲信号频谱')
subplot(2,3,3),imagesc(S2);axis off image
title('(e)时域,旋转信号')
subplot(2,3,6),imagesc(S2_ff);axis off image
title('(f)旋转信号频谱')
sgtitle('图2.2 包含数据扭曲和旋转的傅里叶变换对')