用fft实现反褶积与MATLAB中的反褶积函数有什么不同?
我陷入了这样的困境:用fft实现反褶积与MATLAB中的反褶积函数有什么不同?,matlab,signal-processing,Matlab,Signal Processing,我陷入了这样的困境: function [ y ] = mydeconv( c,x ) lx=length(x); lc=length(c); %lt=lx+lc; c=[c zeros(1,lx)]; x=[x zeros(1,lc)]; y = ifft(real((fft(c)) ./(fft(x)))); end 结果是: mydeconv([1 2 3 3 2 1],[1 1 1]) ans = Column 1
function [ y ] = mydeconv( c,x )
lx=length(x);
lc=length(c);
%lt=lx+lc;
c=[c zeros(1,lx)];
x=[x zeros(1,lc)];
y = ifft(real((fft(c)) ./(fft(x))));
end
结果是:
mydeconv([1 2 3 3 2 1],[1 1 1])
ans =
Column 1
NaN + 0.000000000000000i
Column 2
NaN + NaNi
Column 3
NaN + NaNi
Column 4
NaN + 0.000000000000000i
Column 5
NaN + NaNi
Column 6
NaN + NaNi
Column 7
NaN + 0.000000000000000i
Column 8
NaN + NaNi
Column 9
NaN + NaNi
而deconv
函数的结果就是:
deconv([1 2 3 3 2 1],[1 1 1])
ans =
1 1 1 1
原则上,它应该可以工作,我不明白它有什么问题。由于填充向量
x
的长度是原始向量的倍数,因此在fft(x)
的频域中,最终得到零。当观察到这样的零点时,可以通过选择不同(更长)的长度来避免这种情况:
function [ y ] = mydeconv( c,x )
lx=length(x);
lc=length(c);
if (lc >= lx)
lt = lc;
while (1)
xpadded = [x zeros(1,lt-length(x))];
Xf = fft(xpadded);
if (min(abs(Xf)) > 0)
break;
end
lt = lt + 1;
end
cpadded = [c zeros(1,lt-length(c))];
Cf = fft(cpadded);
y = real(ifft(Cf ./ Xf));
y = y(1:lc-lx+1);
else
y = [];
end
end
由于填充向量
x
的长度是原始向量的倍数,因此在fft(x)
的频域中最终得到零。当观察到这样的零点时,可以通过选择不同(更长)的长度来避免这种情况:
function [ y ] = mydeconv( c,x )
lx=length(x);
lc=length(c);
if (lc >= lx)
lt = lc;
while (1)
xpadded = [x zeros(1,lt-length(x))];
Xf = fft(xpadded);
if (min(abs(Xf)) > 0)
break;
end
lt = lt + 1;
end
cpadded = [c zeros(1,lt-length(c))];
Cf = fft(cpadded);
y = real(ifft(Cf ./ Xf));
y = y(1:lc-lx+1);
else
y = [];
end
end
代码中有两个问题: 首先,您应该获取IFFT输出的
real
部分,而不是单个FFT的部分
其次,您应该防止出现零除零的情况,在您的示例中,这种情况会导致NaN
您可以通过修改行计算y
来实现上述两个功能,如下所示:
y = real(ifft((eps+fft(c)) ./ (eps+fft(x))));
请注意,eps
是一个小的正数,用于防止零除以零的情况。这样,输出为:
disp(y)
% 1.0000 1.0000 1.0000 1.0000 0.0000 -0.0000 0.0000 0.0000 0.0000
代码中有两个问题: 首先,您应该获取IFFT输出的
real
部分,而不是单个FFT的部分
其次,您应该防止出现零除零的情况,在您的示例中,这种情况会导致NaN
您可以通过修改行计算y
来实现上述两个功能,如下所示:
y = real(ifft((eps+fft(c)) ./ (eps+fft(x))));
请注意,eps
是一个小的正数,用于防止零除以零的情况。这样,输出为:
disp(y)
% 1.0000 1.0000 1.0000 1.0000 0.0000 -0.0000 0.0000 0.0000 0.0000
为什么你要在一个FFT后面取
real
值?事实上,起初我没有,但我读了一些,这会更正答案,但是没有,它没有给出正确的答案。为什么你要在一个FFT后面取real
值?事实上,起初我没有,但我读了一些,这将更正答案,但事实并非如此,如果没有真实的答案,它就不会给出正确的答案。非常感谢,这太精辟了。再问一个问题,我如何删除小数点后的多余零?如果您确定c=conv(x,y)
,那么您只需选择第一个length(c)-length(x)+1
元素的y
。在一般情况下,您可以选择包含序列总能量99%以上的前几个元素。请注意,如果任何FFT值等于-eps
,您将立即返回,并遇到同样的除以零问题。@SleuthEye:很公平。如果这是一个问题,可以稍微修改计算,以防止全部被零除:y=real(ifft((fft(c)。*conj(fft(x))+eps)。/(eps+abs(fft(x))。^2))
。非常感谢,非常简洁。还有一个问题,我如何删除小数点后多余的零?如果您确实知道c=conv(x,y)
,那么您可以简单地选择y
的第一个length(c)-length(x)+1
元素。在一般情况下,您可以选择包含序列总能量99%以上的前几个元素。请注意,如果任何FFT值等于-eps
,您将立即返回,并遇到同样的除以零问题。@SleuthEye:很公平。如果这是一个问题,可以稍微修改计算,以防止全部被零除:y=real(ifft((fft(c)。*conj(fft(x))+eps)。/(eps+abs(fft(x))。^2))
。我怎么知道这两个向量是否有反褶积呢?假设c
的长度至少是x
的长度,并且x
或c
在任何地方都不是严格的0,那么有一个y
,根据卷积定理,它将是conv(x,y)=>,而c=ifft(fft(xpadded)。*fft(ypadded))
。那么这只是一个基本的代数,可以得到相反的ypadded=ifft(fft(c)。/fft(xpadded))
同样存在。我怎么知道这两个向量是否有反褶积呢?假设c
的长度至少是x
的长度,并且x
或c
在任何地方都不是严格的0,那么就有一个y
,根据卷积定理,conv(x,y)=c
,而c=ifft(fft(xpadded)。*fft(ypadded))
。那么这只是一个基本的代数,可以得到相反的ypadded=ifft(fft(c)。/fft(xpadded))
同样存在。