I need to write a method using an ArrayList but I can't quite figure out how to do it.
I was able to do it with just using an array and I was wondering if there was an easy way to change it so that it does implement an ArrayList.
Here is my current code:
//public ArrayList<Integer> getPixelsInWindow(int wSize, int x, int y) {
//ArrayList<Integer> values = new ArrayList<Integer>();
public int[] getPixelsInWindow(int wSize, int x, int y) {
int [] values;
int xMin = 0;
int xMax = 0;
int yMin = 0;
int yMax = 0;
xMin = x - (wSize / 2);
if (xMin < 0)
xMin = 0;
yMin = y - (wSize / 2);
if (yMin < 0)
yMin = 0;
xMax = x + (wSize / 2);
if (xMax >= rowN)
xMax = rowN - 1;
yMax = y + (wSize / 2);
if (yMax >= columnN)
yMax = columnN - 1;
int differenceX = xMax-xMin;
int differenceY = yMax-yMin;
values = new int[(differenceX + 1) * (differenceY + 1)];
int j = 0;
for(int i = xMin;i < xMax + 1;i++){
for(int k = yMin;k < yMax + 1;k++){
values[j] = img[i][k];
if(j == 0){
}
j++;
}
}
return values;
}
This was done quickly and not tested... but the idea is there, I am sure:
...
List<Integer> values = new ArrayList<Integer>();
int j = 0;
for(int i = xMin;i < xMax + 1;i++){
for(int k = yMin;k < yMax + 1;k++){
values.add(new Integer(img[i][k]));
...
}
}
Related
I have this problem, i have a NxM matrix and i want to multiply it by a 3x3 matrix just as a convolutional matrix multiplication
example in this link
This are the code of the matrix:
int width = img.getWidth();
int height = img.getHeight();
int matrix[][] = new int[width][height];
int edgeMatrix[][] = {
{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}
};
This is the code of the cycle:
for (int x = 0; x < width; x++) {
w = 0;
holderX = x;
for (w = 0; w < 3; w++) {
v = 0;
if (w > 0)
x++;
for (v = 0; v < 3; v++) {
sum = sum + matrix[v][x] * edgeMatrix[v][w];
if (w == 2 && v == 2)
x = holderX;
}
}
}
This cycle already multiply the first "row" of 3 of the matrix.
T tried in a different ways to achieve this but i just cant get that when the matrix reach the end of the width automatically the N value increase one and then starts over again and in the same time the value still working on the internal matrix multiplication.
Thanks for the help.
You dont need holderX, but need one more loop.
int width = img.getWidth();
int height = img.getHeight();
int input[][] = img.getPixels(); // or whatever api you use
int output[][] = new int[height][width];
int kernel[][] = {
{-1,-1,-1},
{-1,8,-1},
{-1,-1,-1}
};
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int accumulator = 0;
for (int v = 0; v < 3; v++) {
for (int w = 0; w < 3; w++) {
int sy = y + v - 1;
int sx = x + w - 1;
if (sy >= 0 && sy < height && sx >= 0 && sx < width)) {
accumulator += input[sy][sx] * kernel[v][w];
}
}
}
output[sy][sx] = accumulator;
}
}
I found a method to do Delaunay triangulation, but I don't quite understand what the inputs int[] x, int[] y, int[] z are.
import java.awt.Point;
import java.util.Iterator;
import java.util.TreeSet;
public class DelaunayTriangulation{
int[][] adjMatrix;
DelaunayTriangulation(int size){
this.adjMatrix = new int[size][size];
}
public int[][] getAdj(){
return this.adjMatrix;
}
// n = Number of points
// adjMatrix = what point is connected to what (double)
public TreeSet getEdges(int n, int[] x, int[] y, int[] z){
TreeSet result = new TreeSet();
if(n == 2){
this.adjMatrix[0][1] = 1;
this.adjMatrix[1][0] = 1;
result.add(new GraphEdge(new GraphPoint(x[0], y[0]), new GraphPoint(x[1], y[1])));
return result;
}
for(int i = 0; i < n - 2; i++){
for(int j = i + 1; j < n; j++){
for (int k = i + 1; k < n; k++){
if(j == k){
continue;
}
int xn = (y[j] - y[i]) * (z[k] - z[i]) - (y[k] - y[i]) * (z[j] - z[i]);
int yn = (x[k] - x[i]) * (z[j] - z[i]) - (x[j] - x[i]) * (z[k] - z[i]);
int zn = (x[j] - x[i]) * (y[k] - y[i]) - (x[k] - x[i]) * (y[j] - y[i]);
boolean flag;
if(flag = (zn < 0 ? 1 : 0) != 0){
for(int m = 0; m < n; m++){
flag = (flag) && ((x[m] - x[i]) * xn + (y[m] - y[i]) * yn + (z[m] - z[i]) * zn <= 0);
}
}
if (!flag){
continue;
}
result.add(new GraphEdge(new GraphPoint(x[i], y[i]), new GraphPoint(x[j], y[j])));
result.add(new GraphEdge(new GraphPoint(x[j], y[j]), new GraphPoint(x[k], y[k])));
result.add(new GraphEdge(new GraphPoint(x[k], y[k]), new GraphPoint(x[i], y[i])));
this.adjMatrix[i][j] = 1;
this.adjMatrix[j][i] = 1;
this.adjMatrix[k][i] = 1;
this.adjMatrix[i][k] = 1;
this.adjMatrix[j][k] = 1;
this.adjMatrix[k][j] = 1;
}
}
}
return result;
}
public TreeSet getEdges(TreeSet pointsSet){
if((pointsSet != null) && (pointsSet.size() > 0)){
int n = pointsSet.size();
int[] x = new int[n];
int[] y = new int[n];
int[] z = new int[n];
int i = 0;
Iterator iterator = pointsSet.iterator();
while (iterator.hasNext()){
Point point = (Point)iterator.next();
x[i] = (int)point.getX();
y[i] = (int)point.getY();
z[i] = (x[i] * x[i] + y[i] * y[i]);
i++;
}
return getEdges(n, x, y, z);
}
return null;
}
}
Like in your comment it transform the problem and lifts the points to a paraboloid then takes the bottom convex hull and project it back to 2d by omitting the third co-ordinate.
I just started with world generation and I've been looking for tutorials on perlin noise everywhere but sadly there are not alot to be found on Google.
The last days I followed a tutorial but I can't get my code to work.
Here is my Java method.
private static double[][] createNoise(int xn, int yn, int sps) {
int m = yn * sps;
int n = xn * sps;
double[][] u = new double[yn + 1][];
double[][] v = new double[yn + 1][];
double[][] x = new double[m][];
double[][] y = new double[m][];
double[][] z = new double[m][];
for (int i = 0; i < m; i++) {
x[i] = new double[n];
y[i] = new double[n];
z[i] = new double[n];
}
for (int i = 0; i < yn + 1; i++) {
u[i] = new double[xn + 1];
v[i] = new double[xn + 1];
}
for (int i = 0; i < xn + 1; i++) {
for (int j = 0; j < yn + 1; j++) {
u[i][j] = nextRandom();
v[i][j] = nextRandom();
}
}
double hx = xn / (n - 1);
double hy = yn / (m - 1);
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x[i][j] = hx * j;
y[i][j] = hy * i;
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int xc = (int)x[i][j];
int yc = (int)y[i][j];
if (x[i][j] % 1 == 0 && x[i][j] != 0 ) xc = xc - 1;
if (y[i][j] % 1 == 0 && y[i][j] != 0 ) yc = yc - 1;
double xr = x[i][j] - xc;
double yr = y[i][j] - yc;
double s11[] = {-xr, -yr};
double s21[] = {-xr, 1 - yr};
double s22[] = {1 - xr, 1 - yr};
double s12[] = {1 - xr, -yr};
double q11 = s11[0] * u[yc][xc] + s11[1] * v[yc][xc];
double q21 = s21[0] * u[yc + 1][xc] + s21[1] * v[yc + 1][xc];
double q22 = s22[0] * u[yc + 1][xc + 1] + s22[1] * v[yc + 1][xc + 1];
double q12 = s12[0] * u[yc][xc + 1] + s12[1] * v[yc][xc + 1];
z[i][j] = lerp(x[i][j], y[i][j], xc, xc + 1, yc, yc + 1, q11, q12, q21, q22);
}
}
return z;
}
The heightmap that the method returns sadly enough looks like this
As you can see, the first row/column is working, but after that the algorithm seems to fail.
I made sure that the method
nextRandom();
returns a float value between -1 & 1.
Thanks alot!
Thanks to user #gawi for pointing this out.
hx = xn / (n - 1);
will divide 2 integers, and most likely return 0.
You can fix this by casting a double to it:
double hx = (double)xn / (n - 1);
Then the map just works!
So basically I am trying to fill the array[] element with 9 values, however I am not sure how to get the index within this code. I want it to fill the next element in the array each time.
public boolean check(int data[][], int x, int y){
int array[] = new int[9];
int xmax = x+3;
int ymax = y+3;
for(int i = x; i<xmax; i++){
for(int j = y; j<ymax; j++){
array[] = data[i][j];//array[what here?]
}
}
}
for (int i = x; i < xmax; ++i) {
for (int j = y; j < ymax; ++j) {
array[3 * (i - x) + (j - y)] = data[i][j];
}
}
I have a matrix which represents an image and I need to cycle over each pixel and for each one of those I have to compute the sum of all its neighbors, ie the pixels that belong to a window of radius rad centered on the pixel.
I came up with three alternatives:
The simplest way, the one that recomputes the window for each pixel
The more optimized way that uses a queue to store the sums of the window columns and cycling through the columns of the matrix updates this queue by adding a new element and removing the oldes
The even more optimized way that does not need to recompute the queue for each row but incrementally adjusts a previously saved one
I implemented them in c++ using a queue for the second method and a combination of deques for the third (I need to iterate through their elements without destructing them) and scored their times to see if there was an actual improvement. it appears that the third method is indeed faster.
Then I tried to port the code to Java (and I must admit that I'm not very comfortable with it). I used ArrayDeque for the second method and LinkedLists for the third resulting in the third being inefficient in time.
Here is the simplest method in C++ (I'm not posting the java version since it is almost identical):
void normalWindowing(int mat[][MAX], int cols, int rows, int rad){
int i, j;
int h = 0;
for (i = 0; i < rows; ++i)
{
for (j = 0; j < cols; j++)
{
h = 0;
for (int ry =- rad; ry <= rad; ry++)
{
int y = i + ry;
if (y >= 0 && y < rows)
{
for (int rx =- rad; rx <= rad; rx++)
{
int x = j + rx;
if (x >= 0 && x < cols)
{
h += mat[y][x];
}
}
}
}
}
}
}
Here is the second method (the one optimized through columns) in C++:
void opt1Windowing(int mat[][MAX], int cols, int rows, int rad){
int i, j, h, y, col;
queue<int>* q = NULL;
for (i = 0; i < rows; ++i)
{
if (q != NULL)
delete(q);
q = new queue<int>();
h = 0;
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][rx];
}
}
q->push(mem);
h += mem;
}
}
for (j = 1; j < cols; j++)
{
col = j + rad;
if (j - rad > 0)
{
h -= q->front();
q->pop();
}
if (j + rad < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][col];
}
}
q->push(mem);
h += mem;
}
}
}
}
And here is the Java version:
public static void opt1Windowing(int [][] mat, int rad){
int i, j = 0, h, y, col;
int cols = mat[0].length;
int rows = mat.length;
ArrayDeque<Integer> q = null;
for (i = 0; i < rows; ++i)
{
q = new ArrayDeque<Integer>();
h = 0;
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][rx];
}
}
q.addLast(mem);
h += mem;
}
}
j = 0;
for (j = 1; j < cols; j++)
{
col = j + rad;
if (j - rad > 0)
{
h -= q.peekFirst();
q.pop();
}
if (j + rad < cols)
{
int mem = 0;
for (int ry =- rad; ry <= rad; ry++)
{
y = i + ry;
if (y >= 0 && y < rows)
{
mem += mat[y][col];
}
}
q.addLast(mem);
h += mem;
}
}
}
}
I recognize this post will be a wall of text. Here is the third method in C++:
void opt2Windowing(int mat[][MAX], int cols, int rows, int rad){
int i = 0;
int j = 0;
int h = 0;
int hh = 0;
deque< deque<int> *> * M = new deque< deque<int> *>();
for (int ry = 0; ry <= rad; ry++)
{
if (ry < rows)
{
deque<int> * q = new deque<int>();
M->push_back(q);
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int val = mat[ry][rx];
q->push_back(val);
h += val;
}
}
}
}
deque<int> * C = new deque<int>(M->front()->size());
deque<int> * Q = new deque<int>(M->front()->size());
deque<int> * R = new deque<int>(M->size());
deque< deque<int> *>::iterator mit;
deque< deque<int> *>::iterator mstart = M->begin();
deque< deque<int> *>::iterator mend = M->end();
deque<int>::iterator rit;
deque<int>::iterator rstart = R->begin();
deque<int>::iterator rend = R->end();
deque<int>::iterator cit;
deque<int>::iterator cstart = C->begin();
deque<int>::iterator cend = C->end();
for (mit = mstart, rit = rstart; mit != mend, rit != rend; ++mit, ++rit)
{
deque<int>::iterator pit;
deque<int>::iterator pstart = (* mit)->begin();
deque<int>::iterator pend = (* mit)->end();
for(cit = cstart, pit = pstart; cit != cend && pit != pend; ++cit, ++pit)
{
(* cit) += (* pit);
(* rit) += (* pit);
}
}
for (i = 0; i < rows; ++i)
{
j = 0;
if (i - rad > 0)
{
deque<int>::iterator cit;
deque<int>::iterator cstart = C->begin();
deque<int>::iterator cend = C->end();
deque<int>::iterator pit;
deque<int>::iterator pstart = (M->front())->begin();
deque<int>::iterator pend = (M->front())->end();
for(cit = cstart, pit = pstart; cit != cend; ++cit, ++pit)
{
(* cit) -= (* pit);
}
deque<int> * k = M->front();
M->pop_front();
delete k;
h -= R->front();
R->pop_front();
}
int row = i + rad;
if (row < rows && i > 0)
{
deque<int> * newQ = new deque<int>();
M->push_back(newQ);
deque<int>::iterator cit;
deque<int>::iterator cstart = C->begin();
deque<int>::iterator cend = C->end();
int rx;
int tot = 0;
for (rx = 0, cit = cstart; rx <= rad; rx++, ++cit)
{
if (rx < cols)
{
int val = mat[row][rx];
newQ->push_back(val);
(* cit) += val;
tot += val;
}
}
R->push_back(tot);
h += tot;
}
hh = h;
copy(C->begin(), C->end(), Q->begin());
for (j = 1; j < cols; j++)
{
int col = j + rad;
if (j - rad > 0)
{
hh -= Q->front();
Q->pop_front();
}
if (j + rad < cols)
{
int val = 0;
for (int ry =- rad; ry <= rad; ry++)
{
int y = i + ry;
if (y >= 0 && y < rows)
{
val += mat[y][col];
}
}
hh += val;
Q->push_back(val);
}
}
}
}
And finally its Java version:
public static void opt2Windowing(int [][] mat, int rad){
int cols = mat[0].length;
int rows = mat.length;
int i = 0;
int j = 0;
int h = 0;
int hh = 0;
LinkedList<LinkedList<Integer>> M = new LinkedList<LinkedList<Integer>>();
for (int ry = 0; ry <= rad; ry++)
{
if (ry < rows)
{
LinkedList<Integer> q = new LinkedList<Integer>();
M.addLast(q);
for (int rx = 0; rx <= rad; rx++)
{
if (rx < cols)
{
int val = mat[ry][rx];
q.addLast(val);
h += val;
}
}
}
}
int firstSize = M.getFirst().size();
int mSize = M.size();
LinkedList<Integer> C = new LinkedList<Integer>();
LinkedList<Integer> Q = null;
LinkedList<Integer> R = new LinkedList<Integer>();
for (int k = 0; k < firstSize; k++)
{
C.add(0);
}
for (int k = 0; k < mSize; k++)
{
R.add(0);
}
ListIterator<LinkedList<Integer>> mit;
ListIterator<Integer> rit;
ListIterator<Integer> cit;
ListIterator<Integer> pit;
for (mit = M.listIterator(), rit = R.listIterator(); mit.hasNext();)
{
Integer r = rit.next();
int rsum = 0;
for (cit = C.listIterator(), pit = (mit.next()).listIterator();
cit.hasNext();)
{
Integer c = cit.next();
Integer p = pit.next();
rsum += p;
cit.set(c + p);
}
rit.set(r + rsum);
}
for (i = 0; i < rows; ++i)
{
j = 0;
if (i - rad > 0)
{
for(cit = C.listIterator(), pit = M.getFirst().listIterator();
cit.hasNext();)
{
Integer c = cit.next();
Integer p = pit.next();
cit.set(c - p);
}
M.removeFirst();
h -= R.getFirst();
R.removeFirst();
}
int row = i + rad;
if (row < rows && i > 0)
{
LinkedList<Integer> newQ = new LinkedList<Integer>();
M.addLast(newQ);
int rx;
int tot = 0;
for (rx = 0, cit = C.listIterator(); rx <= rad; rx++)
{
if (rx < cols)
{
Integer c = cit.next();
int val = mat[row][rx];
newQ.addLast(val);
cit.set(c + val);
tot += val;
}
}
R.addLast(tot);
h += tot;
}
hh = h;
Q = new LinkedList<Integer>();
Q.addAll(C);
for (j = 1; j < cols; j++)
{
int col = j + rad;
if (j - rad > 0)
{
hh -= Q.getFirst();
Q.pop();
}
if (j + rad < cols)
{
int val = 0;
for (int ry =- rad; ry <= rad; ry++)
{
int y = i + ry;
if (y >= 0 && y < rows)
{
val += mat[y][col];
}
}
hh += val;
Q.addLast(val);
}
}
}
}
I guess that most is due to the poor choice of the LinkedList in Java and to the lack of an efficient (not shallow) copy method between two LinkedList.
How can I improve the third Java method? Am I doing some conceptual error? As always, any criticisms is welcome.
UPDATE Even if it does not solve the issue, using ArrayLists, as being suggested, instead of LinkedList improves the third method. The second one performs still better (but when the number of rows and columns of the matrix is lower than 300 and the window radius is small the first unoptimized method is the fastest in Java)
UPDATE2 Which tool can I use to profile my code and have a richer understanding of which instruction takes the most time? I'm on Mac OS X and using NetBeans Profiler just shows me that the three methods end up with different times (It seems I'm not able to scope within each method)
UPDATE3 I'm scoring the times in java using System.nanoTime() can this lead to inaccurate estimates?:
long start, end;
start = System.nanoTime();
simpleWindowing(mat, rad);
end = System.nanoTime();
System.out.println(end-start);
start = System.nanoTime();
opt1Windowing(mat, rad);
end = System.nanoTime();
System.out.println(end-start);
start = System.nanoTime();
opt2Windowing(mat, rad);
end = System.nanoTime();
System.out.println(end-start);
LinkedList is a very bad choice for a list with where you do random access.
For each get(int) scans the list until the request index is reached.
get(1) is quite fast, but get(100) is 100 times slower and get(1000) is a 1000 times slower than get(1)
You should change that to use ArrayList instead and initialize the ArrayList with the expected size to avoid unnecessary resizing of the internal Array.
Edit
While my coments about get() and LinkedList are correct, they do not apply in this context. I somehow overlooked that there is no random access to the list.
Use an int[] instead of a List.
Lists store Objects requiring a conversion from int to Integer and back.
I indeed implemented two optimized versions for that routine:
the first one, as User216237 suggested, makes use of an array of int as a queue to cache the summed column values as the algorithm scans the image by columns
the other one implements a Summed Area Table in order to compute every rectangualar area of sums by accessing this table just four times (It is independent from the window radius).
One technique can be arbitrary faster than the other according to the specific domain in which it is implemented. In mine, the summed area table had to be computed several times and so it resulted slower than the first method for a radius value lesser than 20 pixel.
About timing your code: System.nanoTime() is ok (i don't think you can get better since it's using OS timers as far as i know), but:
don't try to measure too short of a task, then the accuracy isnt so good. I think anything less than a few milliseconds will give you potential trouble. References, anyone?
measure multiple times, and take the median of the measurements. Outside effects can severely slow the execution, making your estimation useless. Taking the mean doesn't work too well because it is sensitive to such outliers.
many JVMs have JIT compiler, you may want to execute your code multiple times before you measure, so the compiler doesn't kick in somewhere in the middle of your measurement and half of your measurements are suddenly 10x faster than the rest. Better measure after your VM has "warmed up".