I'm using an FFT class I found online to compute the FFT of an image. Here's the code to compute the FFT.
w (width) and h (height) are the same value in this instance.
FFT2 fft = new FFT2(w);
double[] realRow = new double[w];
double[] imagRow = new double[w];
double[][] realVals1 = new double[w][h];
double[][] imagVals1 = new double[w][h];
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
pixel = bmporiginal.getPixel(x, y);
R = (int) (Color.red(pixel));
G = (int) (Color.green(pixel) );
B = (int) (Color.blue(pixel));
I = ((R+G+B)/3);
I *= Math.pow(-1, (x+y) % 2.0 );
realRow[x] = I;
imagRow[x] = 0.0;
}
fft.fft(realRow, imagRow);
realVals1[y] = realRow;
imagVals1[y] = imagRow;
}
The values I need are being stored in realVals and ImagVals. I can print these values within the for loop and get good values. After leaving the for loops I print them again, and get nothing!!! What could be the problem? I appreciate your help!
You're reusing the same row arrays for every iteration of the loop.
So at the end of the two loops, your realVals1 and imagVals1 will each have h references to the same array. You need to create a new array on each iteration of the outer loop:
for (int y = 0; y < h; y++)
{
double[] realRow = new double[w];
double[] imagRow = new double[w];
for (int x = 0; x < w; x++)
{
...
}
fft.fft(realRow, imagRow);
realVals1[y] = realRow;
imagVals1[y] = imagRow;
}
Additionally, I believe your declarations for realVals1 and imagVals1 are a) inefficient and b) the wrong way round. I suspect you want:
double[][] realVals1 = new double[h][];
double[][] imagVals1 = new double[h][];
You're going to be replacing the elements anyway, so there's no point in populating a bunch of empty rows...
You're reusing the same array realRow and imagRow each time through the inner loop. Since Java works with references, when you assign realVals1[y]=realRow, you assign a reference. Since you always use the same array, you assign all the rows to the same array reference. Which is not what you want. You need to recreate realRow and imagRow to a new double[] at the top of the outer for loop.
Related
I just began studying java. One of the tasks was to create a function to create a reverse 2-dimensional array, for example, if the input array was {1,2}{3,4}, the new array must be {4,3}{2,1}. The code below is the method I created. The problem is that the old array d is affected by the loop along with c, so, in this case, it copies half of the values into c, but also replaces the last half of d, so the second half of c is just a mirrored first half, basically, in the example case both c and d will be like this in the end: {4,3}{3,4}. I checked c==d and c.equals(d) after cloning, both show false.
Also, I tried using Arrays.copy, the result was the same. Plus I want the method to work on the arrays that can have their sub-arrays with different lengths, for example, {1,2}{3}{4,5}, and I don't know if it'll work on such arrays.
static int[][] reversematrix(int[][] d) {
int[][] c = d.clone();
for (int i = d.length-1, x = 0; i >= 0; x++, i--) {
for (int j = d[i].length-1, y = 0; j>=0; y++, j--) {
c[x][y] = d[i][j];
}
}
return c;
Can you tell me how to make d(imput array) unaffected by the method/loop? I think the problem is in copying, so I'd love to know a proper way of copying a 2D array into a new object, but if it is in something else, please tell me waht it is.
UPD: Thanks to #sascha the solution was found. Here's the code if someone is interested:
static int[][] reversematrix(int[][] d) {
int[][] c = new int[d.length][];
for (int i = d.length-1, x = 0; i >= 0; x++, i--) {
c[x] = new int[d[i].length];
for (int j = d[i].length-1, y = 0; j>=0; y++, j--) {
c[x][y] = d[i][j];
}
}
return c;
}
Im trying to subtract the same element from a different array i.e., [0,0] - [0,0] and [0,1] - [0,1] but I'm just getting an array index out of bounds exception and I can't seem to work out why. Can anyone see a problem with the code?
//pixArray and avgPix already contain data
int[][] pixArray = new int[35][10];
int[][] avgPix = new int[35][1];
int[][] correctImg = new int[35][10];
public void correctImage() {
for (int r = 0; r < correctImg.length; r++) {
for (int c = 0; c < correctImg[r].length; c++) {
correctImg[r][c] = avgPix[r][c] - pixArray[r][c];
System.out.println(correctImg[r][c]);
}
}
}
I also need to change the loop so that avgPix only loops every time the pixArray column is 0 because avgPix only has 1 column can anyone suggest how I can do this?
You are running r and c based on correctImg's dimension [35][10] and avgPix has dimensions of [35][1]
int[][] avgPix = new int[35][1];
The loop in the provided code snippet uses r and c value from the outer/inner for loop, based on what's described in the question it will make sense to use avgPix[r][0] for all pixArray[r][c].
Not sure what you are trying to achieve but something like this will calculate difference with average
correctImg[r][c] = avgPix[r][0] - pixArray[r][c]
I am not sure if i get you, but if you need to execute the correctImg[r][c] = avgPix[r][c] - pixArray[r][c]; command only when c=0 then you dont need a loop
public void correctImage() {
for (int r = 0; r < correctImg.length; r++) {
correctImg[r][0] = avgPix[r][0] - pixArray[r][0];
}
}
Edit
after reading your comment on your question, i am still not sure what you are trying to do, (looping avgPix every 10th time?).
Maybe an IF statement is more appropriate
The second (useless) dimension of the avgPix is length 1, but the other arrays that you iterate over of length 10. This means that when c > 0, those data points do not exist in avgPix.
In fact, because the second dimension of that array is length 1, it's pretty much useless. Instead, you should just not worry about a second dimension at all. To make it obvious:
int[][] pixArray = new int[35][10];
int[][] avgPix = new int[35]; //no need for 2D array, since it is an average of row values
int[][] correctImg = new int[35][10];
public void correctImage() {
for (int r = 0; r < correctImg.length; r++) {
int rowAverage = avgPix[r]; //this doesn't depend on c
for (int c = 0; c < correctImg[r].length; c++) {
correctImg[r][c] = rowAverage- pixArray[r][c];
System.out.println(correctImg[r][c]);
}
}
}
in my Java source i must execute following lines very often:
vecX = EigenMat.multiply(vecX);
vecY = EigenMat.multiply(vecY);
EigenMat is a N x N Matrix with N~40
vecX/vecY is a N x 1 vector (intern a RealMatrix to)
I used the "Sampler" from VisualFM to find some hotspots in my code and
org.apache.commons.math3.linear.Array2DRowRealMatrix.<init>()
org.apache.commons.math3.linear.Array2DRowRealMatrix.multiply()
have a very high runtime.
I'm not a java professional but i think every multiplication a new vector is created. Can i reassign the old one?
Maybe i should switch to JBLAS to speed it up?
Matyro
Edit:
Single core only
i think every multiplication a new vector is created
Yes, it is. Source code of multiply():
public Array2DRowRealMatrix multiply(final Array2DRowRealMatrix m) {
// Safety check.
MatrixUtils.checkMultiplicationCompatible(this, m);
final int nRows = this.getRowDimension();
final int nCols = m.getColumnDimension();
final int nSum = this.getColumnDimension();
final double[][] outData = new double[nRows][nCols];
// Will hold a column of "m".
final double[] mCol = new double[nSum];
final double[][] mData = m.data;
// Multiply.
for (int col = 0; col < nCols; col++) {
// Copy all elements of column "col" of "m" so that
// will be in contiguous memory.
for (int mRow = 0; mRow < nSum; mRow++) {
mCol[mRow] = mData[mRow][col];
}
for (int row = 0; row < nRows; row++) {
final double[] dataRow = data[row];
double sum = 0;
for (int i = 0; i < nSum; i++) {
sum += dataRow[i] * mCol[i];
}
outData[row][col] = sum;
}
}
return new Array2DRowRealMatrix(outData, false);
}
Input vector m is copied, as stated in a comment Copy all elements of column "col" of "m" so that will be in contiguous memory.
Can i reassign the old one?
Yes, you can perform the multiplication by yourself, writing two loops. Use getData() to get a reference to the underlying double[][] data.
I've initialized a 1d and 2d array and now I basically just want to be able to perform matrix multiplication on them. However, I'm not quite getting the proper answer. I think I've mixed up the for loop where I try to ensure I only multiply the correct values, but can't quite get the hang of it.
edit: I've fixed it, I was misunderstanding what the length method of a 2D array returned (thought it returned columns and not rows). The below code is my corrected code. Thanks everyone.
public static double[] getOutputArray(double[] array1D, double[][] array2D) {
int oneDLength = array1D.length;
int twoDLength = array2D[0].length;
double[] newArray = new double[array2D[0].length]; // create the array that will contain the result of the array multiplication
for (int i = 0; i < twoDLength; i++) { // use nested loops to multiply the two arrays together
double c = 0;
for (int j = 0; j < oneDLength; j++) {
double l = array1D[j];
double m = array2D[j][i];
c += l * m; // sum the products of each set of elements
}
newArray[i] = c;
}
return newArray; // pass newArray to the main method
} // end of getOutputArray method
There are some problems, first of all, you should decide how the vectors represented, are you multiplying from left or right.
For the maths: vector 1xn times matrix nxm will result in 1xm, while matrix mxn times nx1 result in mx1.
I think the following would work for you:
public static double[] getOutputArray(double[] array1D, double[][] array2D) {
int oneDLength = array1D.length;
int twoDLength = array2D.length;
double[] newArray = new double[twoDLength]; // create the array that will contain the result of the array multiplication
assert twoDLength >0 && array2D[0].length == oneDLength;
for (int i = 0; i < twoDLength; i++) { // use nested loops to multiply the two arrays together
double c = 0;
for (int j = 0; j < oneDLength; j++) {
double l = array1D[j];
double m = array2D[i][j];
c += l * m; // sum the products of each set of elements
}
newArray[i] = c;
}
return newArray; // pass newArray to the main method
} // end of getOutputArray method
I hope I did not make a mistake, while trying to fix.
I'm working on some simulation of gas particles.
My problem is that I made 3 two-dimensional integer tables. One for pressure value of particle, and another two to describe x and y movement of particle.
Although I make arraycopy and clone it still somehow manage to change values in global table
private void translate() {
int [][] VectorXBuff = new int[500][500];
System.arraycopy(VectorX.clone(), 0, VectorXBuff, 0, VectorX.length);
int [][] VectorYBuff = new int[500][500];
System.arraycopy(VectorY.clone(), 0, VectorYBuff, 0, VectorX.length);
int [][] FieldBuff = new int[500][500];
System.arraycopy(FieldMatrix.clone(), 0, FieldBuff, 0, VectorX.length);
for (int y = 0; y < FieldMatrix.length; y++){
for (int x = 0; x < FieldMatrix.length; x++){
if(FieldBuff[x][y]!= 0 && FieldBuff[x][y]!= 9 ){
FieldBuff[x + VectorXBuff[x][y]][y + VectorYBuff[x][y]] = Integer.valueOf(FieldBuff[x][y]);
FieldBuff[x][y] = 0;
VectorXBuff[x + VectorXBuff[x][y]][y + VectorYBuff[x][y]] = Integer.valueOf(VectorXBuff[x][y]);
VectorYBuff[x + VectorXBuff[x][y]][y + VectorYBuff[x][y]] = Integer.valueOf(VectorYBuff[x][y]);
VectorXBuff[x][y] = 0;
VectorYBuff[x][y] = 0;
}
}
}
}
This is because you only copy one dimension of your two dimension array. So you are still referencing the same arrays and therefore modifying it in the original one.
Basically, you have a source object [[1,2],[3,4]] and when you do a copy you are copying the pointer to [1,2] and [3,4] into a new array.
As the clone does a shallow copy (check Does calling clone() on an array also clone its contents?) this in the end resumt to just creating another array of the exactly same instances of arrays in memory.