Principle of FFT in multidimensional array - matlab

How can one explain the principle of fft in a multidimensional array?
Y = fft(X)
If X is a multidimensional array, then fft(X) treats the values along the first array dimension whose size does not equal 1 as vectors and returns the Fourier transform of each vector.
I don't understand it very well.
X=[1 2 ; 3 4];
X(:,:,2)=[5 6 ; 7 8]

Let's take the 2D case for simplicity.
Given a 2D matrix of data, X, one can treat each row vector individually and perform a one-dimensional discrete Fourier transform. This will decompose each row into one dimensional frequency components. No attention is given to whether the rows of the matrix are correlated, and so every row of the output matrix will have some non-zero components.
Alternatively, using fft2, one can decompose X into its constituent two-dimensional frequency components. I find this easiest to think about in analogy with the DCT, where you can visualize the 2D basis easily
With the 2D FFT, correlations between rows would affect the output of the FFT. It's possible a single 2D frequency component (which is more like a surface than a wave) could contain all the energy of the 2D FFT, and so the output matrix could be much sparser than when treating the rows individually.
This analogy can be continued in to n-dimensions, with higher dimensional frequency components potentially capturing the higher dimensional structure in your data.

Related

Partial fft of multidimensional array

I have a 3D array of dimension (NX,NY,NZ) which represents a variable in physical space, let's say velocities, taken from a simulation in a 3D domain.
1) I want to Fourier-transform only the dimensions X and Z, how should I use the built-in function fft in this case? At some point I want to also get back to the physical space, but only on X, so the same question applies.
2) I read that FFTW uses only 2*N/3 points, should I specify NX and NZ as the number of retained modes or fewer?
3) When using the FFTW package, is there any issue with the coefficient in front of the integral defining the Fourier transformation? Does this package assume that my domain is 2pix2pix2pi?
1°) The function for 2D FFT is fft2, and it will by default apply to the two first dimensions of the array. That is, fft2(velocities) will give you a 3D array with NZ Fourier transforms along dimensions X and Y
In order to do the FFT along other dimensions, you have to manually decompose the 2D FFT as two 1D FFTs. fft will work by default along dimension 1 and produce as many samples as there were in the input. fft(X[],n) does the same, but along dimension n.
Thus, you may compute a 2D FFT of your 3D array, along dimensions X and Z with the command:
my_FFT = fft(fft(velocities),[],3);
2°) There will be as many samples out as samples in.
3°) I believe the normalization by the size of the array is fully applied on the reverse transform, and not at all on the direct transform.
fft([1 0 0 0 0 0])
ans =
1 1 1 1 1 1
To maintain normalization, a coefficient sqrt(NX*NZ) should be applied (multiply when doing FFT, divide when doing an IFFT).

How to measure the pairwise cosine for a data matrix in MATLAB

Assume there is a data matrix (MATLAB)
X = [0.8147, 0.9134, 0.2785, 0.9649, 0.9572;
0.9058, 0.6324, 0.5469, 0.1576, 0.4854;
0.1270, 0.0975, 0.9575, 0.9706, 0.8003]
Each column represent a feature vector for a sample.
What is the fastest way to get the pairwise consine similarity measure in X in MATLAB? such as we want to compute the symmetric S is 5X5 matrix, the element in S(3,4) is the consine between the third column and fourth column.
Note: The consine measurment cos(a,b) means the angle bettween vector a and b.
If you have the Statistics Toolbox, use pdist with the 'cosine' option, followed by squareform. Note that:
pdist considers rows, not columns, as observations. So you need to transpose the input.
The output is 1 minus the cosine similarity. So you need to subtract the result from 1.
To get the result in the form of a symmetric matrix apply squareform.
So, you can use
S = 1 - squareform(pdist(X.', 'cosine'));

MATLAB Sum along some columns within 3D matrix

Let's assume I have a 8x6x2 matrix signals. I would like to sum along the columns excluding the first column. When using the following code, MATLAB concatenates the 3D matrix to a big 2D (8x11) matrix, which is different from the result I am looking for.
sum(signals(:, 2:end), 2)
I am actually looking for a 8x1x2 3D vector comprising the sums of column 2 to six from each third dimension.
Since your matrix is a 3D matrix, you need to include a colon as the third subscript in your indexing. If you only specify two subscripts, then MATLAB will collapse all trailing dimensions into the last dimension you've specified.
sum(signals(:, 2:end, :), 2)

Do 1-D convolution along each row of a matrix

Did a quick search and couldn't find much about this. Say I have a 2D matrix and a 1D 'response function'. I want to convolve each row of the 2D matrix with the response function. I can do this by:
for i=1:numrows
answer(:,i) = conv(2dmatrix(:,i),response_function,'same');
end
but it's super slow! Any tips to accelerate this?
Thanks
This code reproduces your results on randomly generated matrices:
conv2(response_function,1,2dmatrix,'same')
conv2 allows you to convolute along rows and columns separately, so do nothing to the rows, 1, and convolve the columns by response_function.
To convolve along each row, swap the order of the first two function arguments.
conv2 has somewhat weird syntax, I would prefer using convn for generalized n dimensional convolution. When one of the inputs is just a row vector then convolution in every other dimension is essentially a convolution with [1] so it doesn't change anything, only preforming convolution along each row. Similarly if your a matrix convoluted with a column vector then it would do convolution along each column.
answer = convn(2dmatrix, response_function);

Variable levels of smoothing within the same Matlab matrix

I currently have a large matrix M (~100x100x50 elements) containing both positive and negative values. At the moment, if I want to smooth this matrix, I use the smooth3 function to apply a gaussian kernel over the entire 3-D matrix.
What I want to achieve is a variable level of smoothing within this matrix - i.e.. different parts of the matrix M are smoothed to different levels of sigma depending of the value in a similar 3-D matrix, d (with values ranging from 0 to 1). Where d is 0, no smoothing occurs, where d is 1 a maximum level of smoothing occurs.
The fact that the matrix is 3-D is trivial. Smoothing in 3 dimensions is nice, but not essential, and my current code (performing various other manipulations) handles each of the 50 slices of M separately anyway. I am happy to replace smooth3 with a convolution of M with a gaussian function, and perform this convolution over each slice individually. What I can't figure out is how to vary the sigma level of this gaussian function (based on d) given its location in M and output the result accordingly.
An alternative approach may be to use matrix d as a mask for a very smooth version of matrix Ms and somehow manipulate M and Ms to give an equivalent result, however I'm not convinced that this will work as I can't think of a function to combine M and Md that won't give artefacts of each of M or Ms when 0 < d < 1...any thoughts?
[I'm using 2009b, and only have access to the Signal Processing toolbox.]
You should have a look at the Guided Image Filter. It is a computationally efficient generalization of the bilateral filter.
http://research.microsoft.com/en-us/um/people/jiansun/papers/guidedfilter_eccv10.pdf
It will allow you to do proper smoothing based on your guidance matrix.