shift the elements of a vector by non-integer shif

2019-07-18 04:23发布

问题:

I want to shift a vector by non-integer shift, linear interpolation seems to be not very accurate so I'm trying to use sinc interpolation by the following code which uses Fourier transform.

function y = fshift(x,s)
% FSHIFT Fractional circular shift
%   Syntax:
%
%       >> y = fshift(x,s)
%
%   FSHIFT circularly shifts the elements of vector x by a (possibly
%   non-integer) number of elements s. FSHIFT works by applying a linear
%   phase in the spectrum domain and is equivalent to CIRCSHIFT for integer
%   values of argument s (to machine precision).


needtr = 0; if size(x,1) == 1; x = x(:); needtr = 1; end;
N = size(x,1); 
r = floor(N/2)+1; f = ((1:N)-r)/(N/2); 
p = exp(-j*s*pi*f)'; 
y = ifft(fft(x).*ifftshift(p)); if isreal(x); y = real(y); end;
if needtr; y = y.'; end;

there is no problem in the code when i shift a square wave by integer shift but when the shift is non-integer the output suffers from significant fluctuations i.e.,

s=[zeros(1,20) ones(1,20) zeros(1,20)];
b=fshift(s,3.5);
stem(b)

How to overcome this problem and is there any other accurate method?

回答1:

Try this:

Let's say you are shifting by 3.5. Figure out what the oversampling value is (i.e. what value will change the shift into an integer - in this case it is 2).

ov = 2;
a = 3.5*ov;
y = downsample(circshift(interp(s,2).', -a),ov);

This still has some ringing at the edges, but much less than your sinc approach. I'm not sure if this is due to the gibbs phenomenon since you are essentially truncating or leakage, as mentioned in a comment.



回答2:

You can do this with the fourier shift theorem as you do, but with added filtering. I asked a similar question here. The reason that the result looks 'wrong' is because your input vector is not continuous. The result you are getting really is 'correct' (or at least true).

The problem you are seeing is called Gibbs Ringing. You can make this less extreme by using a low pass filter (this wikipedia link explains the solution pretty well) that has no ringing in its step response. Try your code with and without a gaussian filter. This artefact is often seen in MRI imaging (and many other signal processing situations) and is sometimes alleviated by filtering.