Hallo zusammen 
Grob gesagt möchte ich Bilder (PGM-Datei) filtern, und zwar so:
Ich habe ein Eingabebild (2d-Array). Auf diese Matrix wird dann eine Kernelmatrix angewendet.
Dabei wird jeder Pixel des Ursprungsbildes durch eine Linearkombination seiner Nachbarschaft und sich selbst ersetzt. Die Einträge der Kernelmatrix stellen dabei die Gewichte dieser Linearkombination dar. Bezeichnen wir A als Ausgangsbild und mit A(i,j) den Pixel in der i-ten Zeile und in der j-ten Spalte, dann ist die diskrete Faltung definiert als: A ∶= B ∗ K. Die neuen Pixelwerte des Ausgangsbildes berechnen sich durch:
A(i, j) = ∑ ∑ B(i + x − a1, j + y − a2) ⋅ K(x, y), Summezeichen: jeweils von x=1 (y=1) nach n
In der Formel oben steht dabei n für die Filtergröße, a1 für die x-Koordinate und a2 für die y-Koordinate des Kernelmittelpunktes.
Hilfreicher Link: hier
Ich hab nun eine Methode linearFilter(Image image, float [][] kernel) wobei Image ein Objekt mit folgenden fertigen Methoden ist: getData() liefert float[][], getHeight(), getWidth, getPixel(height,width), setPixel(float value, int heigth, int width).
so sieht nun meine linearFilter-Methode aus:
So weit so gut. Das GROßE PROBLEM und meine Frage:
Ich soll den Bildrand folgendermaßen Behandeln:
Für Pixelwerte am Rand ist der Kernel eventuell zu groß und greift ins Leere. Dafür wird eine sogenannte Randbehandlungsstrategie benötigt. Die Werte außerhalb des Bildrandes werden dann einfach dem Wert des örtlich nöchsten Nachbarns auf dem Bildrand gleichgesetzt. Betrachten Sie folgende für diesen Spezialfall.

Ich hab verstanden was zu tun ist, aber keine (sinnvolle/ absehbar lösbare) Idee wie ich dies nun umsetzen kann. Ein 2d-Array hat ja keine "-1"-Indizes, wo ich einfach die werte reinpacken kann. Und eine neue Matrix mit zwei dimensionen größer (für 3x3 Kernel, anders wenn dieser 5x5 oder so ist) mit erstellen, wo das bild in der "mitte" ist stell ich mir auch schwierig vor, sodass ich dann den kernel nicht ab [0][0] laufen lassen muss.
Hätte jemand dafür eine idee und stimmt mein Ansatz soweit?
Tausend Dank für jede Antwort!
Grob gesagt möchte ich Bilder (PGM-Datei) filtern, und zwar so:
Ich habe ein Eingabebild (2d-Array). Auf diese Matrix wird dann eine Kernelmatrix angewendet.
Dabei wird jeder Pixel des Ursprungsbildes durch eine Linearkombination seiner Nachbarschaft und sich selbst ersetzt. Die Einträge der Kernelmatrix stellen dabei die Gewichte dieser Linearkombination dar. Bezeichnen wir A als Ausgangsbild und mit A(i,j) den Pixel in der i-ten Zeile und in der j-ten Spalte, dann ist die diskrete Faltung definiert als: A ∶= B ∗ K. Die neuen Pixelwerte des Ausgangsbildes berechnen sich durch:
A(i, j) = ∑ ∑ B(i + x − a1, j + y − a2) ⋅ K(x, y), Summezeichen: jeweils von x=1 (y=1) nach n
In der Formel oben steht dabei n für die Filtergröße, a1 für die x-Koordinate und a2 für die y-Koordinate des Kernelmittelpunktes.
Hilfreicher Link: hier
Ich hab nun eine Methode linearFilter(Image image, float [][] kernel) wobei Image ein Objekt mit folgenden fertigen Methoden ist: getData() liefert float[][], getHeight(), getWidth, getPixel(height,width), setPixel(float value, int heigth, int width).
so sieht nun meine linearFilter-Methode aus:
Java:
/**
* This method implements a linear filter with discrete convolution
*
* @param image the image which should be filtered
* @param kernel the kernel used for the linear filter
* @return the filtered image
*/
public Image linearFilter(Image image, float[][] kernel) {
Image filtered = image.clone();
// TODO
int n = kernel[0].length; // erlaubt, da kernel immer nxn
int i = 0;
int j = 0;
int x = 0;
int y = 0;
int a1 = (int) Math.floor(n / 2);
int a2 = (int) Math.floor(n / 2);
for (i = 0; i < filtered.getData().length; i++) {
for (j = 0; j < filtered.getData()[0].length; j++) {
for (x = 0; x < n; x++) {
for (y = 0; y < n; y++) {
filtered.getData()[i][j] = image.getData()[i + x - a1][j + y - a2] * kernel[x][y];
}
}
}
}
return filtered;
}
So weit so gut. Das GROßE PROBLEM und meine Frage:
Ich soll den Bildrand folgendermaßen Behandeln:
Für Pixelwerte am Rand ist der Kernel eventuell zu groß und greift ins Leere. Dafür wird eine sogenannte Randbehandlungsstrategie benötigt. Die Werte außerhalb des Bildrandes werden dann einfach dem Wert des örtlich nöchsten Nachbarns auf dem Bildrand gleichgesetzt. Betrachten Sie folgende für diesen Spezialfall.

Ich hab verstanden was zu tun ist, aber keine (sinnvolle/ absehbar lösbare) Idee wie ich dies nun umsetzen kann. Ein 2d-Array hat ja keine "-1"-Indizes, wo ich einfach die werte reinpacken kann. Und eine neue Matrix mit zwei dimensionen größer (für 3x3 Kernel, anders wenn dieser 5x5 oder so ist) mit erstellen, wo das bild in der "mitte" ist stell ich mir auch schwierig vor, sodass ich dann den kernel nicht ab [0][0] laufen lassen muss.
Hätte jemand dafür eine idee und stimmt mein Ansatz soweit?
Tausend Dank für jede Antwort!