feat: rauschfilter + mandelbrot

master
qhga 3 years ago
parent d6cd29f2fc
commit e8b8114014
Signed by: phga
GPG Key ID: 5249548AA705F019

@ -1 +1 @@
((nil . ((projectile-project-install-cmd . "mvn -B clean compile assembly:single && java -jar target/*.jar"))))
((nil . ((projectile-project-compilation-cmd . "mvn -B clean compile assembly:single && java -jar target/*.jar"))))

@ -18,10 +18,11 @@ DEVICE=1
# DEFAULT = 0
TARGET=31
# How many shifts for N (e.g. if N should be 8, N_LSHIFTS should be 3)
# Targes 2X and 3X depend on this parameter
# Parameter for various tasks (e.g. if N should be shifted 3 times, MULTI_PARAM should be 3)
# Targes 2X and 3X depend on this parameter (1 << MULTI_PARAM)
# Target 4X (N to the left and right of x_0)
# DEFAULT = 25
N_LSHIFTS=3
MULTI_PARAM=3
mvn -B clean compile assembly:single && java -jar target/*.jar $DEVICE $TARGET $N_LSHIFTS
mvn -B clean compile assembly:single && java -jar target/*.jar $DEVICE $TARGET $MULTI_PARAM
```

@ -1,12 +1,12 @@
package edu.thi.phga.aparapi_test;
import com.aparapi.device.OpenCLDevice;
import javafx.application.Application;
public class App {
public static int choice;
public static OpenCLDevice device;
public static int multiParam;
private static void printHeader(final String txt) {
final String spacer =
"######################################################################";
@ -25,11 +25,11 @@ public class App {
if (args.length > 1) {
target = Integer.parseInt(args[1]);
}
int shift = 25;
App.multiParam = 25;
if (args.length > 2) {
shift = Integer.parseInt(args[2]);
App.multiParam = Integer.parseInt(args[2]);
}
final int[] b = new int[1 << shift];
final int[] b;
switch (target) {
case 0:
OpenCLGetMemoryInfo.getInfo();
@ -47,6 +47,7 @@ public class App {
break;
// REDUCE
case 20:
b = new int[1 << App.multiParam];
java.util.Arrays.fill(b, 1);
OpenCLReduce1.start(b);
java.util.Arrays.fill(b, 1);
@ -59,27 +60,33 @@ public class App {
OpenCLReduce5.start(b);
break;
case 21:
b = new int[1 << App.multiParam];
java.util.Arrays.fill(b, 1);
OpenCLReduce1.start(b);
break;
case 22:
b = new int[1 << App.multiParam];
java.util.Arrays.fill(b, 1);
OpenCLReduce2.start(b);
break;
case 23:
b = new int[1 << App.multiParam];
java.util.Arrays.fill(b, 1);
OpenCLReduce3.start(b);
break;
case 24:
b = new int[1 << App.multiParam];
java.util.Arrays.fill(b, 1);
OpenCLReduce4.start(b);
break;
case 25:
b = new int[1 << App.multiParam];
java.util.Arrays.fill(b, 1);
OpenCLReduce5.start(b);
break;
// PREFIX
case 30:
b = new int[1 << App.multiParam];
// Up to 1 << 27
java.util.Arrays.fill(b, 1);
OpenCLPrefix1.start(b);
@ -88,18 +95,27 @@ public class App {
OpenCLPrefix2.start(b);
break;
case 31:
b = new int[1 << App.multiParam];
// Up to 1 << 27
java.util.Arrays.fill(b, 1);
OpenCLPrefix1.start(b);
break;
case 32:
b = new int[1 << App.multiParam];
// Up to 1 << 28
java.util.Arrays.fill(b, 1);
OpenCLPrefix2.start(b);
break;
case 40:
// multiParam defines smoothing
System.out.println("Spawning window Filter");
Application.launch(Rauschfilter.class);
break;
case 50:
// multiParam defines ZOOM
System.out.println("Spawning window Mandelbrot");
Application.launch(Mandelbrot.class);
break;
}
}
}

@ -0,0 +1,138 @@
package edu.thi.phga.aparapi_test;
import java.util.ArrayDeque;
import java.util.Deque;
import com.aparapi.Range;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelFormat;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.image.WritablePixelFormat;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class Mandelbrot extends Application{
private static Rectangle2D bounds = Screen.getPrimary().getBounds();
private static final int BREITE = (int) (bounds.getWidth() * 0.8);
private static final int HOEHE = BREITE * 9 / 16;
private double[] farbe = new double[BREITE * HOEHE];
private double[] saturation = new double[BREITE * HOEHE];
private MandelbrotKernel k = new MandelbrotKernel(farbe, saturation);
private Range r;
// (x1, y1) = links oben, (x2, y2) = rechts unten
private double x1 = -3.0;
private double x2 = 1.8;
private double y1 = (x2 - x1) * HOEHE / BREITE / 2;
private double y2 = -y1;
// Wie scharf ist das Bild (Ab wann sagen wir |Z_n| <= 2 für alle Z_n)
private int maxIter = 200;
private int exponent = 0;
private WritableImage image = new WritableImage(BREITE, HOEHE);
private WritablePixelFormat<java.nio.ByteBuffer> format = PixelFormat.getByteBgraPreInstance();
private PixelWriter pw = image.getPixelWriter();
private PixelReader pr = image.getPixelReader();
private Deque<byte[]> imageStack = new ArrayDeque<>();
private Deque<double[]> frameStack = new ArrayDeque<>();
private Stage stage;
private void zeichne() {
stage.setTitle("KAO: Computing...");
k.setParameters(x1, y1, x2, y2, maxIter);
k.execute(r);
for (int i = 0; i < farbe.length; i++) {
Color c = Color.hsb(farbe[i], saturation[i], 0.5);
pw.setColor(i % BREITE, i / BREITE, c);
}
setTitle();
}
private void setTitle() {
stage.setTitle(String.format("KAO: Mandelbrot (Zoom: %d^%d, n = %d)",
App.multiParam, exponent, maxIter));
}
private void zoomIn(MouseEvent e) {
byte[] buffer = new byte[4 * BREITE * HOEHE];
pr.getPixels(0, 0, BREITE, HOEHE, format, buffer, 0, 4 * BREITE);
imageStack.push(buffer);
frameStack.push(new double[] { x1, y1, x2, y2 });
double x = x1 + (x2 - x1) * e.getX() / BREITE;
double y = y1 + (y2 - y1) * e.getY() / HOEHE;
double dx = (x2 - x1) / App.multiParam / 2;
double dy = (y2 - y1) / App.multiParam / 2;
x1 = x - dx;
x2 = x + dx;
y1 = y - dy;
y2 = y + dy;
maxIter *= 2;
exponent++;
zeichne();
}
private void zoomOut(KeyEvent e) {
String key = e.getText();
System.out.println("Key: " + key);
if (key.equals("q") && !imageStack.isEmpty()) {
double[] frame = frameStack.pop();
x1 = frame[0];
y1 = frame[1];
x2 = frame[2];
y2 = frame[3];
maxIter /= 2;
pw.setPixels(0, 0, BREITE, HOEHE, format, imageStack.pop(), 0, 4 * BREITE);
setTitle();
}
}
@Override
public void start(Stage stage) {
// Set range
int maxWGSize = 16;
System.out.println("Using WGSize: " + maxWGSize);
r = Range.create2D(App.device, BREITE, HOEHE, maxWGSize, maxWGSize);
this.stage = stage;
ImageView view = new ImageView(image);
view.setFocusTraversable(true);
view.setOnMousePressed(this::zoomIn);
view.setOnKeyPressed(this::zoomOut);
zeichne();
stage.setScene(new Scene(new Group(view)));
stage.setResizable(false);
stage.sizeToScene();
stage.show();
}
}

@ -0,0 +1,147 @@
package edu.thi.phga.aparapi_test;
import com.aparapi.Kernel;
public class MandelbrotKernel extends Kernel {
private double[] farbe;
private double[] saturation;
private double x1, x2, y1, y2;
private int maxIter;
public MandelbrotKernel(double[] farbe, double[] saturation) {
this.farbe = farbe;
this.saturation = saturation;
}
public void setParameters(double x1, double y1, double x2, double y2, int maxIter) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.maxIter = maxIter;
}
// Formel:
// z_n = { 0, n=0
// z_(n-1)^2 + c, n>0
// c element von C (Complex)
// Bei uns ist c dann ein Pixel den wir einfärben
// bzw. der Punkt(x, y) (offset) für eine bestimmte Zahl der Mandelbrot Menge
// Schwarz == ist Teil der Menge (|z_k| <= 2)
// Farbe == sonst (|z_k| > 2) (Frühzeitiger Schleifenabbruch)
// Alle z_n beginnen bei 0
// Iter 1: z = 0^2 + c
// Iter 2: z = c^2 + c
// Iter 3: z = (c^2 + c)^2 + c
// ...
// Abbruch: |z| > 2 || Iter == maxIter (200)
// @Override public void run() {
// int b = getGlobalId(0); // horizontaler Index
// int h = getGlobalId(1); // vertikaler Index
// double cx = x1 + (x2 - x1) * b / getGlobalSize(0);
// double cy = y1 + (y2 - y1) * h / getGlobalSize(1);
// double x = cx , y = cy;
// double xx = x * x, yy = y * y;
// int i;
// for (i = 1; xx + yy < 4 && i <= maxIter; i++) {
// y = 2 * x * y + cy;
// x = xx - yy + cx;
// yy = y * y;
// xx = x * x;
// }
// int idx = h * getGlobalSize(0) + b;
// farbe[idx] = log(i) * 360;
// helligkeit[idx] = i < maxIter ? 1 : 0;
// }
@Override
public void run() {
int x = getGlobalId(0);
int y = getGlobalId(1);
int sizeX = getGlobalSize(0);
int sizeY = getGlobalSize(1);
double imageSizeX = x2 - x1;
double imageSizeY = y2 - y1;
// Skalierung
double cR = x1 + imageSizeX * x / sizeX;
double cI = y1 + imageSizeY * y / sizeY;
double zR = cR;
double zI = cI;
double zRQ = zR * zR;
double zIQ = zI * zI;
double zAbs = zIQ + zRQ;
int i = 0;
for (i = 1; i <= maxIter && zAbs < 4; i++) {
// WICHTIG REIHENFOLGE!!! zR wird überschrieben...
zI = 2 * zR * zI + cI; // 2 * xyi + c_imag
zR = zRQ - zIQ + cR; // x^2 - y^2 + c_real
zIQ = zI * zI;
zRQ = zR * zR;
zAbs = zIQ + zRQ;
}
int index = y * sizeX + x;
if (i < maxIter) {
saturation[index] = min(i * log(i) / maxIter + 0.2, 1);
farbe[index] = log(i) * 360;
} else {
saturation[index] = 0;
}
}
// z = z*z + c
// z^2 = (z_r + z_i*i) * (z_r + z_i*i)
// = (z_r * z_r) + (z_r * z_i*i + z_r * z_i * i) - (z_i * z_i) <- [i^2 = -1]
// = z_r^2 + 2*z_r*z_i*i - z_i^2
// = z_r^2 - z_i^2 + 2*i*z_r*z_i
// = x^2 - y^2 + 2xyi
// real + imag
// Nette Entdeckung :) #LaserShow WUBWUBWUBWUB
// @Override
// public void run() {
// int sizeX = getGlobalSize(0);
// int sizeY = getGlobalSize(1);
// double imageSizeX = (x2 - x1);
// double imageSizeY = (y2 - y1);
// int x = getGlobalId(0);
// int y = getGlobalId(1);
// double c_r = x + imageSizeX / sizeX;
// double c_i = y + imageSizeY / sizeY;
// double z_r = 0; // komplexe zahl
// double z_i = 0;
// double zb = 0;
// for (int i = 0; i < 200 && zb <= 4; i++) {
// // z = z*z + c
// // z^2
// z_r = z_r * z_r - z_i * z_i;
// z_i = z_r * z_i + z_r * z_i;
// // z + c;
// z_r += c_r;
// z_i += c_i;
// // sqrt(z_r^2 + z_i^2)
// zb = sqrt(z_r * z_r + z_i * z_i);
// }
// if (zb <= 4) {
// helligkeit[x + x * y] = 0;
// } else {
// helligkeit[x + x * y] = 1;
// }
// }
}

@ -3,6 +3,10 @@ package edu.thi.phga.aparapi_test;
import java.util.Arrays;
import java.util.stream.IntStream;
import com.aparapi.Kernel;
import com.aparapi.Range;
import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
@ -11,34 +15,43 @@ import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;
public class Rauschfilter extends javafx.application.Application {
public class Rauschfilter extends Application {
private static Rectangle2D bounds = Screen.getPrimary().getBounds();
private static final int BREITE = (int) (bounds.getWidth() * 0.8);
private static final int HOEHE = BREITE * 9 / 16;
private static final double OMEGA = 8 * Math.PI / BREITE;
private static final int FILTERLAENGE = 15;
// private static final int FILTERLAENGE = 15;
@Override
public void start(Stage stage) {
float[] noisy = new float[BREITE];
// float[] clean = new float[BREITE];
float[] clean = new float[BREITE];
Range r = Range.create(App.device, BREITE, Math.min(BREITE, 256));
for (int i = 0; i < BREITE; i++) {
noisy[i] = (float) (5 * Math.sin(i * OMEGA) + Math.random() - 0.5);
}
// Kernel k = new FilterKernel(noisy, clean)
Kernel k = new RauschfilterKernel(noisy, clean, App.multiParam);
System.out.println("Executing Kernel");
k.execute(r);
double ct = k.getConversionTime();
double et = k.getExecutionTime() - ct;
System.out.printf("Took %.2f ms to smooth out the wave with N = %d\n",
et, App.multiParam);
Canvas oben = getCanvas(noisy);
Canvas unten = getCanvas(clean);
VBox vbox = new VBox(oben);
VBox vbox = new VBox(oben, unten);
vbox.setStyle("-fx-background-color: whitesmoke");
stage.setScene(new Scene(vbox));
stage.setTitle("KAO: Mittelwertfilter der Ordnung " + (FILTERLAENGE - 1));
stage.setTitle("KAO: Mittelwertfilter der Ordnung " + (App.multiParam - 1));
stage.setResizable(false);
stage.sizeToScene();
stage.show();

@ -0,0 +1,33 @@
package edu.thi.phga.aparapi_test;
import com.aparapi.Kernel;
public class RauschfilterKernel extends Kernel {
private float[] noisy;
private float[] clean;
private int len;
RauschfilterKernel(float[] noisy, float[] clean, int len) {
this.noisy = noisy;
this.clean = clean;
this.len = len;
}
@Override
public void run() {
// y_i = 1/N(x_-N/2 + x_-N/2+1 + ... + x_-1 + x_0 + x_1 + ... + x_N/2-1 + x_N/2)
int i = getGlobalId();
float sum = 0;
for (int n = 1; n <= len; n++) {
// To the right of x
if (i + n < noisy.length) {
sum += noisy[i + n];
}
// To the left of x
if (i - n >= 0) {
sum += noisy[i - n];
}
}
// write into clean
clean[i] = (sum + noisy[i]) / len;
}
}

@ -1,4 +0,0 @@
open module edu.thi.phga.aparapi_test {
requires javafx.controls;
requires aparapi;
}

@ -0,0 +1,4 @@
// open module edu.thi.phga.aparapi_test {
// requires aparapi;
// requires javafx.controls;
// }
Loading…
Cancel
Save