Difference between fft points and fft in vector - matlab

Given a vector X of length L, what is the difference between fft(X) and fft(X,L)?
Does it mean we are taking the fft on L points when using fft(X) and the fft of vector L when doing fft(X,L)?

As per the documentation on fft:
Y = fft(X) computes the discrete Fourier transform (DFT) of X using a fast Fourier transform (FFT) algorithm.
If X is a vector, then fft(X) returns the Fourier transform of the vector.
Y = fft(X,n) returns the n-point DFT. If no value is specified, Y is the same size as X.
If X is a vector and the length of X is less than n, then X is padded with trailing zeros to length n.
If X is a vector and the length of X is greater than n, then X is truncated to length n.
Meaning that in case you have a vector X of length L, fft(X) and fft(X,L) are equivalent.
The interesting bit comes when you call fft(X,n) with n~=L.
If n<L your input vector X will be trucated, i.e. you will use less measurements and get a shorted Fourier sequence.
If n=L; discussed above
If n>L your vector X is zero-padded: X = [X zeros(L-n,1)] (for a row vector X). What this will do is interpolation in the frequency domain. This is most easily seen from the formulae at the bottom of the documentation:
if we increase n, we get a longer vector Y. However, since you padded zeros, and not a continuation of the signal, its Fourier transform will be an interpolation between frequencies. Normally you'd have the frequencies as given by W(n) running from your sampling frequency, f_s all the way up to f_n = Nyquist/2 in L steps, i.e. as many data points as you have: linspace(F_s,f_n,L). What you are doing when zero padding is putting more points into the same space: linspace(F_s,f_n,n), without adding information.

Related

Dimension of Filter in 3-D Convolution in MATLAB

The function to perform an N-dimensional convolution of arrays A and B in matlab is shown below:
C = convn(A,B) % returns the N-dimensional convolution of arrays A and B.
I am interested in a 3-D convolution with a Gaussian filter.
If A is a 3 x 5 x 6 matrix, what do the dimensions of B have to be?
The dimensions of B can be anything you want. There is no set restriction in terms of size. For the Gaussian filter, it can be 1D, 2D or 3D. In 1D, what will happen is that each row gets filtered independently. In 2D, what will happen is that each slice gets filtered independently. Finally, in 3D you will be doing what is expected in 3D convolution. I am assuming you would like a full 3D convolution, not just 1D or 2D.
You may be interested in the output size of convn. If you refer to the documentation, given the two N dimensional matrices, for each dimension k of the output and if nak is the size of dimension k for the matrix A and nbk is the size of dimension k for matrix B, the size of dimension of the output matrix C or nck is such that:
nck = max([nak + nbk - 1, nak, nbk])
nak + nbk - 1 is straight from convolution theory. The final output size of a dimension is simply the sum of the two sizes in dimension k subtracted by 1. However should this value be smaller than either of nak or nbk, we need to make sure that the output size is compatible so that any of the input matrices can fit in the final output. This is why you have the final output size and bounded by both A and B.
To make this easier, you can set the size of the filter guided by the standard deviation of the distribution. I would like to refer you to my previous Stack Overflow post: By which measures should I set the size of my Gaussian filter in MATLAB?
This determines what the output size of a Gaussian filter should be given a standard deviation.
In 2D, the dimensions of the filter are N x N, such that N = ceil(6*sigma + 1) with sigma being the desired standard deviation. Therefore, you would allocate a 3D matrix of size N x N x N with N = ceil(6*sigma + 1);.
Therefore, the code you would want to use to create a 3D Gaussian filter would be something like this:
% Example input
A = rand(3, 5, 6);
sigma = 0.5; % Example
% Find size of Gaussian filter
N = ceil(6*sigma + 1);
% Define grid of centered coordinates of size N x N x N
[X, Y, Z] = meshgrid(-N/2 : N/2);
% Compute Gaussian filter - note normalization step
B = exp(-(X.^2 + Y.^2 + Z.^2) / (2.0*sigma^2));
B = B / sum(B(:));
% Convolve
C = convn(A, B);
One final note is that if the filter you provide has any of its dimensions that are beyond the size of the input matrix A, you will get a matrix using the constraints of each nck value, but then the border elements will be zeroed due to zero-padding.

DCT rows instead of columns

I was aquainted in using the fft in matlab with the code
fft(signal,[],n)
where n tells the dimension on which to apply the fft as from Matlab documentation:
http://www.mathworks.it/it/help/matlab/ref/fft.html
I would like to do the same with dct.
Is this possible? I could not find any useful information around.
Thanks for the help.
Luigi
dct does not have the option to pick a dimension like fft. You will have to either transpose your input to operate on rows or pick one vector from your signal and operate on that.
yep!
try it:
matrix = dctmtx(n);
signal_dct = matrix * signal;
Edit
Discrete cosine transform.
Y = dct(X) returns the discrete cosine transform of X.
The vector Y is the same size as X and contains the discrete cosine transform coefficients.
Y = dct(X,N) pads or truncates the vector X to length N before transforming.
If X is a matrix, the dct operation is applied to each column. This transform can be inverted using IDCT.
% Example:
% Find how many dct coefficients represent 99% of the energy
% in a sequence.
x = (1:100) + 50*cos((1:100)*2*pi/40); % Input Signal
X = dct(x); % Discrete cosine transform
[XX,ind] = sort(abs(X)); ind = fliplr(ind);
num_coeff = 1;
while (norm([X(ind(1:num_coeff)) zeros(1,100-num_coeff)])/norm(X)<.99)
num_coeff = num_coeff + 1;
end;
num_coeff

How to do windowing, FFT and display result

I'm trying to input a .wav file by
filename = 'C:\Users\kiit\Desktop\New folder\file.wav';
[y, Fs, nbits] = wavread(filename)
after that I'm calculate the length by-
L=length(y)
I've performed hamming window by-
w=window(#hamming,L);
when I perform fft by
F=fft(y,w)
It's showing warning as
Warning: FFT length must be a non-negative integer scalar.
F =
Empty matrix: 0-by-1
Any help??
Your fft command is wrong. The second argument is the FFT length, not the window.
Y = fft(X,n) returns the n-point DFT. fft(X) is equivalent to fft(X, n) where n
is the size of X in the first nonsingleton dimension. If the length of X is less
than n, X is padded with trailing zeros to length n. If the length of X is
greater than n, the sequence X is truncated. When X is a matrix, the length of
the columns are adjusted in the same manner.
To window, you apply (elementwise multiply) in the time domain (i.e. y.*w).
And to understand the output of fft:
Why does FFT produce complex numbers instead of real numbers?
Converting Real and Imaginary FFT output to Frequency and Amplitude

FFTW and fft with MatLab

I have a weird problem with the discrete fft. I know that the Fourier Transform of a Gauss function exp(-x^2/2) is again the same Gauss function exp(-k^2/2). I tried to test that with some simple code in MatLab and FFTW but I get strange results.
First, the imaginary part of the result is not zero (in MatLab) as it should be.
Second, the absolute value of the real part is a Gauss curve but without the absolute value half of the modes have a negative coefficient. More precisely, every second mode has a coefficient that is the negative of that what it should be.
Third, the peak of the resulting Gauss curve (after taking the absolute value of the real part) is not at one but much higher. Its height is proportional to the number of points on the x-axis. However, the proportionality factor is not 1 but nearly 1/20.
Could anyone explain me what I am doing wrong?
Here is the MatLab code that I used:
function [nooutput,M] = fourier_test
Nx = 512; % number of points in x direction
Lx = 50; % width of the window containing the Gauss curve
x = linspace(-Lx/2,Lx/2,Nx); % creating an equidistant grid on the x-axis
input_1d = exp(-x.^2/2); % Gauss function as an input
input_1d_hat = fft(input_1d); % computing the discrete FFT
input_1d_hat = fftshift(input_1d_hat); % ordering the modes such that the peak is centred
plot(real(input_1d_hat), '-')
hold on
plot(imag(input_1d_hat), 'r-')
The answer is basically what Paul R suggests in his second comment, you introduce a phase shift (linearly dependent on the frequency) because the center of the Gaussian described by input_1d_hat is effectively at k>0, where k+1 is the index into input_1d_hat. Instead if you center your data (such that input_1d_hat(1) corresponds to the center) as follows you get a phase-corrected Gaussian in the frequency domain:
Nx = 512; % number of points in x direction
Lx = 50; % width of the window containing the Gauss curve
x = linspace(-Lx/2,Lx/2,Nx); % creating an equidistant grid on the x-axis
%%%%%%%%%%%%%%%%
x=fftshift(x); % <-- center
%%%%%%%%%%%%%%%%
input_1d = exp(-x.^2/2); % Gauss function as an input
input_1d_hat = fft(input_1d); % computing the discrete FFT
input_1d_hat = fftshift(input_1d_hat); % ordering the modes such that the peak is centered
plot(real(input_1d_hat), '-')
hold on
plot(imag(input_1d_hat), 'r-')
From the definition of the DFT, if the Gaussian is not centered such that maximum occurs at k=0, you will see a phase twist. The effect off fftshift is to perform a circular shift or swapping of left and right sides of the dataset, which is equivalent to shifting the center of the peak to k=0.
As for the amplitude scaling, that is an issue with the definition of the DFT implemented in Matlab. From the documentation for the FFT:
For length N input vector x, the DFT is a length N vector X,
with elements
N
X(k) = sum x(n)*exp(-j*2*pi*(k-1)*(n-1)/N), 1 <= k <= N.
n=1
The inverse DFT (computed by IFFT) is given by
N
x(n) = (1/N) sum X(k)*exp( j*2*pi*(k-1)*(n-1)/N), 1 <= n <= N.
k=1
Note that in the forward step the summation is not normalized by N. Therefore if you increase the number of points Nx in the summation while keeping the width Lx of the Gaussian function constant you will increase X(k) proportionately.
As for signal leaking into the imaginary frequency dimension, that is due to the discrete form of the DFT, which results in truncation and other effects, as noted again by Paul R. If you reduce Lx while keeping Nx constant, you should see a reduction in the amount of signal in the imaginary dimension relative to the real dimension (compare the spectra while keeping peak intensities in the real dimension equal).
You'll find additional answers to similar questions here and here.

Linear convolution and cross-correlation of two vectors in Matlab using fft and same length output

I'm implementing an algorithm where I need to compute the linear convolution and cross-correlation between two 1D vectors a and b using the FFT. If the length of a is m and the length of b is n, then the total length of the resulting convolution will be m + n - 1.
However, the algorithm requires the output of the convolution to be the same length as the inputs. Since m = n, the input vectors are the same length.
In Matlab, given that both vectors have been zero-padded to length m + n - 1, the convolution is computed as:
ifft(fft(a).*fft(b))
Alternately, the cross-correlation between the two vectors is computed as:
fftshift(ifft(fft(a).*conj(fft(b))))
The output is of length m + n - 1. I need to zero-pad the vectors to ensure that circular convolution does not occur when using the FFT.
However, I would like the output length to be the same as the length of the inputs. An associated question (also on stackoverflow) shows how the correlation of two images can be trimmed.
How do I trim the 1D output vector so that it is the same length as the input vectors?
In MATLAB, conv(a, b, 'same') returns the central part of the convolution that is the same size as a. For cross correlation, you can use xcorr, which will give you the cross correlation result. I guess you need to crop the result by yourself to get the same size as input.
there are formulas:
c = a conv b;
where, a, b and c are in time domain; After trans to frequency domain, the formula change to
C = A * B;
where, A, B and C are fft result of a, b, and c respectively, and all of them are in frequency domain; so c = ifft(C);