Plotting vector in 3D in Matlab - matlab

I'm studying Linear Algebra. I would like to visualize a vector [2, 1, 2] in 3D. I used the following command:
quiver3(0,0,0,2,1,2)
And either my understanding of Linear Algebra is off or I'm doing something wrong with MATLAB. But what the plot looks like to me is that it's plotting vector [1.8, 0.9, 1.8].

By default, quiver3 will use whatever scaling that optimizes the display of the vectors.
quiver3(...,scale) automatically scales the vectors to prevent them from overlapping, and then multiplies them by scale. scale = 2 doubles their relative length, and scale = 0.5 halves them. Use scale = 0 to plot the vectors without the automatic scaling.
You'll want to specify the scale parameter as 0 to prevent this automatic scaling and to accurately represent the data that you provide
quiver3(0, 0, 0, 2, 1, 2, 0);

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).

Calculating a volume of a mesh object in MATLAB

I am using geom3d to model 3D geometric shapes. Specifically, I am interested to calculate a volume of the ellipsoid after slicing it with an arbitrary plane. I am using the following code (here for simplicity I will use a sphere and cut it in the center).
[x, y, z] = sphere(30);
[f, v, c] = surf2patch(x, y, z, z, 'triangles');
meshVolume(v, f)
This calculates a volume of a sphere as expected (4/3*pi).
Now, I slice it in half.
P = createPlane([0, 0, 0], [0, 0, 1]);
[v1 f1] = clipConvexPolyhedronHP(v, f, P);
drawMesh(v1, f1, 'facealpha', 0.5)
Now if I calculate the volume, I get incorrect value (significantly smaller than half of the initial volume).
meshVolume(v1, f1)
What is the reason for the incorrect result?
(I have already answerd on Mathworks File Exchange page, but I think it can be useful to put it also here)
Using determinant without 'abs' is the correct way of computing volume of meshes. By doing that way you can handle non convex meshes, and even polyhedra with holes. But the faces of the mesh must be oriented consistently (usually outwards of the mesh).
A similar topic is given here
Using the absolute value of the determinant will give correct result only for convex polyhedra. So I would use it only as a quick hack for specific application.
Regarding the original question, there was a bug in the computation of the clipped mesh, resulting in faces with inconsistent orientation, and therefore in wrong resulting volume. I have updated it so it should give better results.
(note: I am the author of the geom3d package)
Actually found a bug in the implementation of the meshVolume function.
The function divides the volume into tetrahedra, which are 3-dimensional solids that have 4 vertices, 6 edges, and 4 triangular faces.
Then the total volume of the body is the sum of the volumes of all tetrahedra.
The code computes the volume by calculating the determinant of the vertices.
vols(i) = det(tetra) / 6;
It turns out that sometimes this determinant can be negative due to a different order of the rows (vertices coordinates).
The correct formula should include absolute value of the determinant.
vols(i) = abs(det(tetra) / 6);
That solves the problem. I've reported the bug on geom3d webpage.
For more details about tetrahedra see here

3D HSV image histogram in Matlab, with different no. of bins for each channel?

I am working on developing a CBIR system where I am using HSV histogram as one of my features. For each image I want to compute a histogram which has say n1 bins for hue, n2 for saturation and n3 for value. I want a vector which will be n1xn2xn3 dimensional having all possible combinations of these bins.
for example: If I take a tuple (8, 12, 3) bins for hue, saturation and value respectively, then I want to compute a 8x12x3=288 dimensional vector.
In openCV we have the calcHist() function to do so but I failed to find a similar function in matlab.
here is what I have done
%roi1 is my region of interest, y1 is the vector
y1=[imhist(roi1(:,:,1),8)' imhist(roi1(:,:,2),12)' imhist(roi1(:,:,3),3)'];
but y1 would be 23 dimensional rather than the desired 288 dimensional. Please help me on this, if there is a function similar to calcHist() of openCV then suggest me so.
What you have computed is a series of single-dimension histograms, rather than the multi-dimensional histogram. For example, imhist(roi1(:,:,1),8)' is the counts of only the hue values, ignoring corresponding saturation or value of the pixel. There is code on the Mathworks site to compute an n-dimensional histogram, which should provide what you're after: http://www.mathworks.com/matlabcentral/fileexchange/23897-n-dimensional-histogram

How do I get the spectrum of 1D and 2D spatial filters used in images?

I would like to know how to obtain the spectrum of a spatial 1 dimensional and 2 dimensional sharpening filter in image processing.
The sharpening filters are:
[-1, 3, -1];
[-1, -1, -1; -1, 8, -1; -1, -1, -1];
In MATLAB, what should I do to get the spectrum of the filters, or how do I get the frequency components of these filters?
You can use Luis Mendo's post to determine the spectrum of your filter right away. Use either freqz for a 1D filter, or freqz2 for a 2D filter. Note that the plot using freqz and freqz2 are in terms of normalized frequency that spans between [-1,1].
However, I'd like to write this post to compliment Luis Mendo's and show you how the spectrum is derived.
Let's start with your first filter:
h1 = [-1,3,-1];
If you recall, the 1D Discrete-Time Fourier Transform (DTFT) is defined as:
Aside: Why the DTFT and not the Discrete Fourier Transform (DFT)?
Take special care that this is different from the Discrete Fourier Transform (DFT). The difference between them is that the DTFT is the traditional Fourier Transform applied to a discrete signal. From the continuous viewpoint, we apply the normal Fourier Transform where the spectrum is continuous in terms of frequency. It is essentially the same thing here for a discrete signal, but the transform is applied to a discrete signal. The output is also continuous in frequency, with the additional constraint that the spectrum is 2*pi periodic. For the DFT, it is essentially a sampled version of the DTFT in frequency domain. Therefore, the core difference between them both is that in the frequency domain, one is continuous while the other is a sampled version of the continuous counterpart. The reason why we need to sample the DTFT is so that you can actually store the spectra on computers and let programs process the spectra (i.e. MATLAB).
Your question asked to determine what the spectrum is, and in terms of a theoretical perspective, I will present the DTFT to you. When we actually plot the spectra, we are actually sampling the DTFT anyway, so when we see the spectra, you would be visualizing the DFT (more or less!).
A very good explanation about the differences between them both can be found on DSP StackExchange: https://dsp.stackexchange.com/questions/16586/difference-between-discrete-time-fourier-transform-and-discrete-fourier-transfor
Back to your question
For the definition of the DTFT, h[k] is a 1D signal, and omega is the angular frequency defined in radians. Therefore, you can consider your filter to be this 1D signal and when you filter in the spatial domain, it is the same as taking this signal, transforming it into the frequency domain and performing multiplication with another input signal in the frequency domain.
Therefore, if we consider that your filter is symmetric, the value of 3 is defined as the centre point. As such, you can think of h[k] as:
h = [-1 3 -1]
^ ^ ^
k = -1 0 1
Therefore, the frequency domain representation is simply a weighted sum of the filter coefficients with complex exponential terms. Substituting h[k] into the Fourier Transform formula, we get:
If you recall Euler's formula, we have:
Similarly:
If we add the two equations together, we can rearrange and solve for cos(x):
Going back to our transform of our 1D filter, we can do some factoring:
Note that the domain is between [-pi,pi], as the 1D Fourier Transform is 2*pi symmetric. As such, if you want to show the spectrum, simply plot using the above domain and use the equation that I just created, plotting the absolute value, as the magnitude of the spectrum is always positive:
w = linspace(-pi,pi);
h = abs(3 - 2*cos(w));
plot(w,h);
title('Magnitude of 1D spectrum');
axis([-pi, pi, 0, 5]);
linspace generates a linearly increasing array from -pi to pi with 100 points in between the ranges. You can override this behaviour by specifying a third parameter that manually tells linspace how many points you want to generate, but the default is 100 if you omit this parameter.
Note that I've made the y-axis extend from 0 so you can see where the curve starts at and it going up to 5 as this is the maximum value that is ever possible for h. This is what we get:
Indeed the above spectrum certainly looks like a high-pass filter, and because the magnitude at the DC frequency (w = 0) is 1, you are essentially adding the original signal on top of the high-pass filtering results, which thus "sharpens" your signal.
You can do the same process with the 2D case, though it will be a bit more involved. In the 2D case, the Discrete-Time Fourier Transform is defined to be:
We have two independent variables to consider, and we will have 2D spatial frequencies. w1 and k1 will operate along the rows of the 2D signal and w2 and k2 will operate along the columns of the 2D signal.
Given your mask:
h2 = [-1 -1 -1; -1 8 -1; -1 -1 -1]
As the shape of h2 is symmetric, the value of 8 will be location (w1,w2) = (0,0). Therefore, when we calculate the spectrum with the above equation, we get:
I'll save you the trouble with the simplification, but doing some rearranging and making use of Euler's formula, we get:
Note that:
I used the above property to make the simplifications possible. For the 2D case, we will define a meshgrid of coordinates that both range between [-pi,pi] for both dimensions, and we will plot this on a surface plot with surf. Remember to take the absolute value of the filter to show the magnitude:
[w1,w2] = meshgrid(linspace(-pi,pi));
h = abs(8 - 2*cos(w1+w2) - 2*cos(w1) - 2*cos(w2) - 2*cos(w1-w2));
surf(w1,w2,h);
title('2D spectrum of filter');
w1 and w2 provide unique combinations of the frequencies defined horizontally and vertically at each respective spatial location of the arrays. w1 and w2 will in fact be two-dimensional. For each unique combination of w1 and w2, we determine what the magnitude of the spectra will be. Once we calculate these, we can put all of this information together in a nice three-dimensional surface plot.
We thus get:
Take note that both dimensions span from [-pi,pi]. If you examine the spectrum, you will see that the DC component gets nulled to 0, which is actually a high-pass filter, and not a sharpening filter. See my note below.
Minor note
BTW, your 2D filter definition is not a 2D sharpening filter. It is simply a 2D Laplacian, which is an edge detection and thus a high-pass filter. It only detects edges. If you want to properly sharpen the image, make sure you add 1 to the centre of the kernel, and so what you're really after is:
h2 = [-1 -1 -1; -1 9 -1; -1 -1 -1];
The offset of 1 will ensure that you are leaving the original signal untouched, but also adding the high-pass results on top of the original signal to thus sharpen your input.
To plot the frequency response of a 1D FIR filter, use freqz:
h = [-1, 3, -1]; %// FIR impulse response
N = 128; %// number of frequency samples
freqz(h,1,N); %// "1" because the filter is not recursive
The frequency axis is normalized to half the sample frequency, as usual.
See the documentation of freqz for further options.
To plot the frequency response of a 2D FIR filter, use freqz2:
h = [-1, -1, -1; -1, 8, -1; -1, -1, -1]; %// FIR impulse response (filter mask)
N = 128; %// number of frequency samples
freqz2(h,N,N)
The frequency axes are normalized to half the sample frequency, as in the 1D case.
See the documentation of freqz2 for further options.

How to round off a curve (remove sharp corners) in matlab

Suppose there are two curves (described by two groups of data): curve 1 and curve 2. The two curves have more than two intersection points. A new curve 3 is obtained by keeping the upper part of the two curves. The problem is that there are several sharp corners at the intersection points on curve 3. How to smooth the curve by rounding off these corners using matlab?
Apply a convolution with a lowpass filter?
n = 4; %// adjust as needed. Higher value gives more smoothing
curve3_smooth = conv(curve3, ones(1,n)/n, 'same');
A better idea, as noted by #Hoki, is to apply the filter twice: once forwards and once backwards, to make the smoothing operation symmetric. You can achieve that with filtfilt:
n = 2;
curve3_smooth = filtfilt(ones(1,n)/n, 1, curve3);
Borrowing from Luis Mendo's post and your comments in his post, if you are given 2D data where each column is a single vector and you want to filter each of the columns separately, then use filter instead. You'd specify the dimension to be 1, as you want to filter along the rows. As such:
%// adjust as needed
n = 4;
smooth_curve = filter(ones(1,n)/n, 1, u, [], 1);