I'm trying to understand how to implement the Fast Fourier Transform using the separability property.
Image from the book: Gonzalez, R. C., and R. E. Woods. "Digital Image Processing, 4th Global Edition."
According to this, as I understand, we must compute the matrix of complex sinewave values like this:
Complex[] F = new Complex[i.width*i.height];
for (int x=0;x<i.img.length;x++){
F[x] = new Complex();
double theta = -2 * Math.PI * (x/(double)i.img.length);
F[x] = new Complex(Math.cos(theta), Math.sin(theta));
}
So, our matrix is a 1D array with the size of our image.
And then we have to take an image and multiply it with row-by-row array F, and then take the processed image and multiply it with column-by-column array F.
What i can't understand is how to properly perform this row-by-row and column-by-column multiplication.
Let's say we take F and separate its columns by chunks. I did it like this:
int chunk = image.width;
for(int f=0;f<F.length;f+=chunk){
row = Arrays.copyOfRange(F, f, Math.min(F.length,f+chunk));
for(int k=0; k < row.length; k++){
row[k] = row[k].mul(image[k]);
clone[k] = (byte) row[k].r;
}
}
But this is wrong, the row gets empty.
Should we actually cut the 1D F array like this in order to multiply it with pixel values? Or there's another way to compute the row-by-row and column-by-column multiplication? How it can be implemented in Java?
Related
I'm trying to get the most representative frequency (or first harmonic) from an audio file using the Noise FFT library (https://github.com/paramsen/noise). I have an array with the values of size x and the output array's size is x+2. I'm not familiar with Fourier Transform, so maybe I'm missing something, but from my understanding I should have something that represents the frequencies and stores the magnitude (or in this case a complex number from with to calculate it) of each one.
The thing is: since each position in the array should be a frequency, how can I know the range of the output frequencies, what frequency is each position or something like that?
Edit: This is part of the code I'm using
float[] mono = new float[size];
// I fill the array with the appropiate values
Noise noise = Noise.real(size);
float[] dst = new float[size + 2];
float[] fft = noise.fft(mono, dst);
// The result array has the pairs of real+imaginary floats in a one dimensional array; even indices
// are real, odd indices are imaginary. DC bin is located at index 0, 1, nyquist at index n-2, n-1
double greatest = 0;
int greatestIdx = 0;
for(int i = 0; i < fft.length / 2; i++) {
float real = fft[i * 2];
float imaginary = fft[i * 2 + 1];
double magnitude = Math.sqrt(real*real+imaginary*imaginary);
if (magnitude > greatest) {
greatest = magnitude;
greatestIdx = i;
}
System.out.printf("index: %d, real: %.5f, imaginary: %.5f\n", i, real, imaginary);
}
I just noticed something I had overlooked. When reading the comment just before the for loop (which is from the sample code provided in GitHub) it says that nyquist is located at the last pair of values of the array. From what I searched, nyquist is 22050Hz, so... To know the frequency corresponding to greatestIdx I should map the range [0,size+2] to the range [0,22050] and calculate the new value? It seems like a pretty unprecise measure.
Taking the prior things into account, maybe I should use another library for more precision? If that is the case, what would be one that let me specify the output frequency range or that gives me approximately the human hearing range by default?
I believe that the answer to your question is here if I understand it correctly https://stackoverflow.com/a/4371627/9834835
To determine the frequency for each FFT bin you may use the formula
F = i * sample / nFFt
where:
i = the FFT index
sample = the sample rate
nFft = your FFT size
I am trying to read a NetCDF file with 4 parameters (Time, Depth, Latitude, Longitude), I want to read the file at a constant Time and depth.
Right now I am reading the whole file and then getting the values in a 4D grid and then parsing the grid to get the values at constant depth and time into a 2D array
//I have read the values of time and depth in TimeArr and depthArr respectively
int depthIndex = binarySearchInArray(depthArr, d);
int timeIndex = binarySearchInArray(timeArr, d);
ArrayFloat.D4 tempArr = (ArrayFloat.D4) v.read();
float[][] grid = new float[(int) latArr.getSize()][(int) lonArr.getSize()];
for (int i = 0; i < latArr.getSize(); i++) {
for (int j = 0; j < lonArr.getSize(); j++) {
grid[i][j] = tempArr.get(timeIndex, depthIndex, i, j);
}
}
return grid;
The line ArrayFloat.D4 tempArr = (ArrayFloat.D4) v.read(); takes a lot of time to read the file if it's too large.
Also, it is pointless to read all the dimensions when I need it for only one.
Is there a way to directly read a file along 2 dimensions only (with 2 dimensions, Time and Depth, kept constant)?
Thank you so much in advance.
One way you can just read the data you need would be to use the read(int[] origin, int[] shape) method on the Variable:
// define the indexes where you would like the array
// subset to start
int[] origin = new int[] {timeIndex, depthIndex, 0, 0};
// define the overall size of the read to be done, starting
// at origin
int[] size = new int[] {1, 1, latSize, lonSize};
// read the subset
Array data4D = v.read(origin, size);
// remove any dimensions of size 1
Array data2D = data4D.reduce();
where latSize and lonSize are the size of those dimensions, respectively.
For more information, as well as for a few other approaches, see the netCDF-Java tutorial (specifically the Reading data from a Variable section).
Cheers!
How can I get the magnitudes and corresponding frequencies after performing FFT on a dataset. I need to plot the magnitude vs frequencies for a dataset. Also, why are we increasing the size of our FFT array as twice the size of actual dataset? Then the size of resulting output array is again different, Please help me understand this FFT code. Further, when is complexforward FFT and when realForward FFT is performed? Difference between the two? I need to perform FFT on a dataset and get the magnitude after FFT and corresponding frequencies for each magnitude.
int length = data.length;
FloatFFT_1D fftDo = new FloatFFT_1D(length);
float[] fft = new float[length * 2];
System.arraycopy(data, 0, fft, 0, length);
fftDo.complexForward(fft);
//for(double d: fft) {
//System.out.println(d);
//}
float outputfft[] = new float[(fft.length+1)/2];
if(fft.length%2==0){
for(int i = 0; i < length/2; i++){
outputfft[i]= (float) Math.sqrt((Math.pow(fft[2*i],2))+(Math.pow(fft[(2*(i))+1], 2)));
}
}else{
for(int i = 0; i < (length/2)+1; i++){
outputfft[i]= (float) Math.sqrt((Math.pow(fft[2*i],2))+(Math.pow(fft[(2*i)+1], 2)));
}
}
for (float f : outputfft) {
System.out.println(f);
}
The FFT of a real-valued data vector is by definition complex and symmetric. If you have a vector length of N samples you will get a FFT of N frequency data separated in frequency by Fs/N, where Fs is the sampling frequency. Your output vector is twice the size since the complex data is interleaved [re,im,re,im ...].
The output data is half the size since it is symmetric and you only need to view the first half corresponding to frequencies [0 .. Fs/2] the upper half is [-Fs/2 .. 0)
If you have an even-symmetric input data, X(-n)=X(n), or odd-symmetric, X(-n)=-X(n), you may use the realForward function
Im trying to implement something like discribed here and here, Specifically i want to be able to perform the following operation as in the following image :
That is, given N discrete points with constant time interval, i want to create a function that converges to those points as in the image...
So far what i did was :
imported jtransform
used it
private double[] doDFT(double[] data, int start, int end) {
DoubleFFT_1D doubleFFT_1D = new DoubleFFT_1D(end-start);
double[] array = new double[(end-start)*2];
for (int i=0;i<end-start;i++) {
array[i] = data[i+start];
array[i+1] = data[i+start+1];
}
doubleFFT_1D.complexForward(array);
return array;
}
and Now im stuck, how do i use the output array to produce the function that converges to the points in the original data array?
Just to clearify what i want : for example in the image the data array that is inputted to doDFT is the blue line plot, and what i want is to produce a function f that its image is the red line plot.
You probably want to set the imaginary component of your complex input to zero, not to the next point.
The functions you want are sinusoids. Each sinusoid will have a frequency of an FFT result bin index * Fs/N. The magnitude and phase of each sinusoid will be given by the complex value corresponding to its FFT result bin.
You can sum an increasing number of these sinusoids, starting with 1, to get your converging waveforms.
I'm doing a project in Java which includes (x,y) coordinates.
I have created a class of Cell which has protected integers X & Y;
Upon initialization, i do a for loop which sets an array of cell by multiplying the X & Y given by the user, say if X= 10 and Y = 10, i create an array of cells[100].
However, how can i search the array fast, without doing a for loop and checking each individual value very time?
Say I'm looking for the object that contains X=5 & y = 3.
I know i can go through with a for loop looking for object with values x and y, but i was wondering if there is a way to do a binary search and find "a bit faster" the object[i] that contains X=5 and Y=5.
Thank you very much.
The way to do this is to arrange the Cell objects in the array in a way so that there is a simple mapping from an X,Y coordinate to the Cell's index in the array.
For example, lets assume that X and Y go from 1 to 10. Suppose that we then arrange the Cells so that:
array[0] = Cell(1, 1);
array[1] = Cell(1, 2);
...
array[9] = Cell(1, 10);
array[10] = Cell(2, 1);
array[11] = Cell(2, 2);
...
array[99] = Cell(10, 10);
It should be easy to see that we can calculate the index of Cell(i,j) in the array and fetch the cell as follows:
public Cell getCell(Cell[] array, int i, int j) {
int index = (10 * (i - 1)) + (j - 1);
return array[index];
}
This is the approach that programming languages that support N-dimensional array types typically use to implement them.
This can be trivially modified to deal with cases where:
the constant 10 is something else
the matrix is not square,
the matrix has more than two dimensions
indexes run from 0 to N - 1 instead of 1 to N
etcetera
There are various other ways that you could represent 2-D matrices in Java. The simplest one is just using a Cell[][] cells which allows you to access cells as (for example) cells[i-1][j-1]. More complicated representations can be designed that use less space if the matrix is sparse (i.e. cells are missing) at the cost of more complex code and slower access times.
It sounds like (if you want to use binary search, anyway) you're setting element 0 to the Cell with x = 0, y = 0; element 1 to x = 0, y = 1, etc. If so you should be able to trivially compute the exact index of a given Cell:
// contains the Cell with x = desiredX, y = desiredY
yourArray[desiredX * X + desiredY];
If this is what you're doing, however, it'd probably be simpler to just make a 2-dimensional array:
yourArray = new Cell[X][Y];
...
yourArray[desiredX][desiredY];
the above two answers show the trivial method for getting the array index fast. id like to propose an alternative- use hashmaps with key, value pairings. the value could be objects. accessing hashmap elements run in constant time..