Fehlersuche beim Weichzeichner-Algorithmus

Status
Nicht offen für weitere Antworten.

LMnd

Mitglied
Hallo zusammen!

EDIT: ACHTUNG: mittlerweile hab ich herausgefunden, dass es nicht an der Größe liegt, sondern am Verhältnis Höhe / Breite. Ist es nicht gleich, dann treten die Verschiebungen auf. Leider weiss ich nicht warum. So, weiter im Originaltext:

Ich habe einen Weichzeichner geschrieben, und ihn auf kleinen Bildern (512*512) getestet. Schien zu funktionieren:
out51.jpg


auf größeren Bildern hab ich aber das Problem, dass er bestimmte Bereiche mit falschen Werten überlagert (man beachte die Desktopsymbole am folgendem Bild):

große Bilder, desshalb als Link:
http://img.photobucket.com/albums/v484/Thomas87/out_breit_3.jpg
http://img.photobucket.com/albums/v484/Thomas87/out_breit_5.jpg

Die beiden großen Bilder sind entsprechend ihrem Namen mit strenght = 3 bzw 5 gemacht worden.

Ich bin nicht Programmiersprachen - bewandert genug um rauszufinden, woran es liegt, sitze jetzt schon seit mehreren Stunden dran, hab diverse Sachen probiert, aber nichts will gelingen.

Hier der Code:

Code:
/*
 *  momentan wird noch auf dem Originalbild gearbeitet,
 *  dh der Filter beeinflusst sich selber im Bilddurchlauf.
 *  sinnvolle strenght Werte zum testen: ungerade Zahlen zwischen 3 und 11
 *  
 */


public class Weichzeichner extends Filter {
	int hmax = BildLae; //Bildhöhe
	int wmax = BildBre; //BildBreite
	
	public Weichzeichner(Image im2){
		super(im2);
	}
	
	//prüft, ob der Punkt mit den Koordinaten h,w im Bild ist
	public boolean imBild (int h, int w){
		boolean bool=false;
		if (h>=0 && h<hmax && w>=0 && w<wmax) bool = true;
		return bool;
	}
	
	public void weichzeichnen(int strenght){

		//berechnet für die ungerade strenght Zahl die Mitte also zb 4 für 7
		int mitte = (strenght - 1)/2; 
		//sum0 = Summe rot, sum1 = Summe Grün, sum2 = Summe Blau
		int sum0, sum1, sum2;
		//abstand 1: Abstand in Spalten vom Mittelpunkt mitte,mitte
		//abstand 2: Abstand in Zeilen
		int abstand1=0, abstand2=0;
		//abstand = 1 + Summe der Abstände ... also gesammt-abstand
		double abstand;
		double z; //zähler
		
		//zeilen, spalten durchlaufen
		for (int h=0; h<hmax; h++){
			for (int w=0; w<wmax; w++){
				
				//z und sum0,sum1,sum2 bei jedem Durchlauf zurücksetzen
				z = 0;
				sum0 = sum1 = sum2 = 0;
				
				//die strenght * strenght "Matrix" durchlaufen
				for (int s1=1; s1<=strenght; s1++){
					for (int s2=1; s2<=strenght; s2++){
						
						//wenn Punkt im Bild, int "abstand" berechnen
						if (imBild(h+mitte-s1,w+mitte-s2) == true){
							if (s1<mitte) abstand1 = mitte-s1;
							if (s1>mitte) abstand1 = s1-mitte;
							if (s1==mitte) abstand1 = 0;
							if (s2<mitte) abstand2 = mitte-s2;
							if (s2>mitte) abstand2 = s2-mitte;
							if (s2==mitte) abstand2 = 0;
							abstand = abstand1 + abstand2 +1;
							
							//zu z addieren, damit wir später wieder teilen können
							//z ist nach Schleifenbeendigung die Summe der 1/Abstände
							z=z + (1 / abstand);
							
							//die RGB Werte entsprechend der Gewichtung 1/abstand addieren
							sum0 = (int)(sum0 + im.getPixel(h+mitte-s1,w+mitte-s2,0)/abstand);
							sum1 = (int)(sum1 + im.getPixel(h+mitte-s1,w+mitte-s2,1)/abstand);
							sum2 = (int)(sum2 + im.getPixel(h+mitte-s1,w+mitte-s2,2)/abstand);
						}
					}
				}
				//den Pixel auf die oben berechnete, und entsprechend der
				//Abstände korrigierte, Summe setzen
				im.setPixel(h, w, 0, (short)(sum0/z));
				im.setPixel(h, w, 1, (short)(sum1/z));
				im.setPixel(h, w, 2, (short)(sum2/z));
			}
		}
	}
	
}

Es läuft also irgendwas mit den Variablen schief, allerdings weiss ich nicht, an welchen Variablen es scheitert, und weiss auch nicht, wie ich das rausfinden soll.
Wäre über jede Hilfe dankbar ;)

MfG,
LMnd
 
Zuletzt bearbeitet:
S

SlaterB

Gast
klasse wäre noch ne main-Methode mit dem Einlesen und Abspeichern des Bildes, sonst muss man sich das immer selber zusammensammeln
 

LMnd

Mitglied
neuer Post, weil wichtig:

Es hängt anscheinend vom Verhältnis Höhe/Breite ab.

Das kleine Bild oben (Lenna) ist nämlich 512 x 512

Der Desktop 1920 x 1200.


Hab beide Bilder mal gecroppt und es klappt auf 1200 x 1200, aber zB nicht auf 512x360.

Nur wieso? Seh da grade garkeinen Zusammenhang im Code.
 

Soulfly

Bekanntes Mitglied
Das ist kein typischer Weichzeichner, den du da implementiert hast. Ich mach mir jetzt keine Gedanke um dein Problem, da es nicht dem Standard entspricht.

Investiere lieber mal in die Suche nach: Filterkernel, lineare Filter, Bildmanipulation etc.
 
S

SlaterB

Gast
deine Image-Klasse hat mich einen Haufen Nerven gekostet,

int index = 54 + clrTableSize * 4 + ((width - 1) - setWidth) * height* 3 +
3 * setHeight + setRgb;

bzw. kannst dein alignment wieder einbauen,
aber width und heigth waren bei getPixel und setPixel bei der Haupt-Index-Berechung für das Array vertauscht,
bei quadratischen Bildern fiel es verständlicherweise nicht auf

edit:
> und weiss auch nicht, wie ich das rausfinden soll.

der Grundgedanke hätte sein müssen:
es werden nicht direkt benachbarte Punkte verschmolzen, sondern versetzte Punkte aus einer Zeile
 
Zuletzt bearbeitet von einem Moderator:

LMnd

Mitglied
edit:
Es werden sehr wohl die benachbarten Pixel überprüft, nämlich die, die innerhalb einer "strength x strength Matrix" liegen, welche mit dem Mittelpunkt auf dem gerade weichzuzeichnendem Pixel liegt (darum auch strenght ungerade!).

(also gibt es (strength^2)-1 Nachbarpixel, welche gewertet an ihrem Abstand in die Berechnung einfließen.

BSP für strength = 3:
1/3,1/2,1/3
1/2,1/1,1/2
1/3,1/2,1/3

(Wobei der mittlere Pixel mein weichzuzeichnender Pixel ist. Das Ergebnis wird dann natürlich noch im Fall strength = 3 durch 13/3 geteilt.)

Trotzdem nochmal vielen Dank, es klappt jetzt.
Zwischenzeitlich wurden auch einige Änderungen an der ImageIO vorgenommen, allerdings nicht in Bezug auf das angebliche Width / Height Problem. Jaja, böses SVN... ;)

weichtest2.jpg

out_weichtest2.jpg


Das in der ImageIO ist auch nicht falschrum (was unsere Methoden und Klassen Elliptisch ausblenden, Grauwert- / Sepiafilter, Zufallsrauschen, Pixelrauschen, Drehen, Spiegeln, Morphen, Helligkeit und Kontrast, die wie vorgesehen funktionieren, bestätigen).



Vielen Dank trotzdem, so klappt es jetzt :



Code:
public class Weichzeichner extends Filter {
	int hmax;
	int wmax;
	short[][][] neu;
	
	public Weichzeichner(Image im2){
		super(im2);
		hmax = BildLae;
		wmax = BildBre;
		neu = new short[hmax][wmax][3];
	}
	
	//prüft, ob der Punkt mit den Koordinaten h,w im Bild ist
	public boolean imBild (int h, int w){
		return (h>=0 && h<hmax && w>=0 && w<wmax);
	}
	
	public void weichzeichnen(int strenght){

		//berechnet für die ungerade strenght Zahl die Mitte also zb 4 für 7
		int mitte = (strenght - 1)/2;
		//sum0 = Summe rot, sum1 = Summe Grün, sum2 = Summe Blau
		int sum0, sum1, sum2;
		//abstand 1: Abstand in Spalten vom Mittelpunkt mitte,mitte
		//abstand 2: Abstand in Zeilen
		int abstand1=0, abstand2=0;
		//abstand = 1 + Summe der Abstände / gesammt-abstand
		double abstand;
		double z; //zähler
		
		//zeilen, spalten durchlaufen
		for (int h=0; h<hmax; h++){
			for (int w=0; w<wmax; w++){
				
				//z und sum0,sum1,sum2 bei jedem Durchlauf zurücksetzen
				z = 0;
				sum0 = sum1 = sum2 = 0;
				
				//die strenght * strenght "Matrix" durchlaufen
				for (int s1=1; s1<=strenght; s1++){
					for (int s2=1; s2<=strenght; s2++){
						
						//wenn Punkt im Bild, int "abstand" berechnen
						if (imBild(h+mitte-s1,w+mitte-s2)){
							abstand1=Math.abs(mitte-s1);
							abstand2=Math.abs(mitte-s2);
							abstand = abstand1 + abstand2 +1;
							
							//zu z addieren, damit wir später wieder teilen können
							//z ist nach Schleifenbeendigung die Summe der 1/Abstände
							z=z + (1 / abstand);
							
							//die RGB Werte entsprechend der Gewichtung 1/abstand addieren
							sum0 = (int)(sum0 + im.getPixel(h+mitte-s1,w+mitte-s2,0)/abstand);
							sum1 = (int)(sum1 + im.getPixel(h+mitte-s1,w+mitte-s2,1)/abstand);
							sum2 = (int)(sum2 + im.getPixel(h+mitte-s1,w+mitte-s2,2)/abstand);
						}
					}
				}

				//das Array auf die oben berechneten, und entsprechend der
				//Abstände korrigierten, Summen setzen
				
				neu[h][w][0] = (short)(sum0/z);
				neu[h][w][1] = (short)(sum1/z);
				neu[h][w][2] = (short)(sum2/z);
			}
		}
		
		//array ins Bild schreiben
		for (int h=0; h<hmax; h++){
			for (int w=0; w<wmax; w++){
				im.setPixel(h, w, 0, (short)(neu[h][w][0]));
				im.setPixel(h, w, 1, (short)(neu[h][w][1]));
				im.setPixel(h, w, 2, (short)(neu[h][w][2]));
			}
		}
	}
}
 
Zuletzt bearbeitet:

LMnd

Mitglied
es verbarg sich noch ein kleiner fehler in der Zeile:

Code:
int mitte = (strenght - 1)/2;

Es muss natürlich

Code:
int mitte = (strenght + 1)/2;

sein.

Ausserdem gab es noch weiter kleine Verbesserungen (beeinflusst sich jetzt zB beim Durchlaufen nicht mehr selber), hier der aktuelle Code:

Code:
public class Weichzeichner extends Filter {
	int hmax;
	int wmax;
	short[][][] neu;

	public Weichzeichner(Image im2) {
		super(im2);
		hmax = BildLae;
		wmax = BildBre;
		neu = new short[hmax][wmax][3];
	}

	// prüft, ob der Punkt mit den Koordinaten h,w im Bild ist
	public boolean imBild(int h, int w) {
		return (h >= 0 && h < hmax && w >= 0 && w < wmax);
	}

	public void weichzeichnen(int strenght) {

		// berechnet für die ungerade strenght Zahl die Mitte also zb 4 für 7
		int mitte = (strenght + 1) / 2;
		// sum0 = Summe rot, sum1 = Summe Grün, sum2 = Summe Blau
		double sum0, sum1, sum2;

		// abstand = 1 + Summe der Abstände / gesammt-abstand
		double abstand;
		double z; // zähler
		int temp1, temp2;

		// zeilen, spalten durchlaufen
		for (int h = 0; h < hmax; h++) {
			for (int w = 0; w < wmax; w++) {

				// z und sum0,sum1,sum2 bei jedem Durchlauf zurücksetzen
				z = sum0 = sum1 = sum2 = 0;

				// die strenght * strenght "Matrix" durchlaufen
				for (int s1 = 0; s1 < strenght; s1++)
					for (int s2 = 0; s2 < strenght; s2++) {
						temp1 = mitte - s1;
						temp2 = mitte - s2;

						// wenn Punkt im Bild, int "abstand" berechnen
						if (imBild(h + temp1, w + temp2)) {
							abstand = Math.abs(temp1) + Math.abs(temp2) + 1;

							// zu z addieren, damit wir später wieder teilen
							// können
							// z ist nach Schleifenbeendigung die Summe der
							// 1/Abstände
							z = z + (1 / abstand);

							// die RGB Werte entsprechend der Gewichtung
							// 1/abstand addieren
							sum0 += im.getPixel(h + temp1, w + temp2, 0)
									/ abstand;
							sum1 += im.getPixel(h + temp1, w + temp2, 1)
									/ abstand;
							sum2 += im.getPixel(h + temp1, w + temp2, 2)
									/ abstand;
						}

						// das Array auf die oben berechneten, und entsprechend
						// der
						// Abstände korrigierten, Summen setzen

						neu[h][w][0] = (short) (sum0 / z);
						neu[h][w][1] = (short) (sum1 / z);
						neu[h][w][2] = (short) (sum2 / z);
					}
			}
		}

		// array ins Bild schreiben
		for (int h = 0; h < hmax; h++)
			for (int w = 0; w < wmax; w++) {
				im.setPixel(h, w, 0, (short) (neu[h][w][0]));
				im.setPixel(h, w, 1, (short) (neu[h][w][1]));
				im.setPixel(h, w, 2, (short) (neu[h][w][2]));
			}
	}
}

Das einzige Problem: Wen ich als Filtergröße eine 51 x 51 Matrix möchte, dann rechnet er doch schon recht lange (aufm Notebook bei 512x512 Originalbild dauert es eine knappe Minute).
Werde ihn also noch weiter optimieren.

Oder ist das normal? Ich meine er führt ja ca 9 * (51^2) * (512^2) Berechnungen aus ( = 6,136,528,896).
 
Zuletzt bearbeitet:

EgonOlsen

Bekanntes Mitglied
Das einzige Problem: Wen ich als Filtergröße eine 51 x 51 Matrix möchte, dann rechnet er doch schon recht lange (aufm Notebook bei 512x512 Originalbild dauert es eine knappe Minute).
Werde ihn also noch weiter optimieren.

Oder ist das normal? Ich meine er führt ja ca 9 * (51^2) * (512^2) Berechnungen aus ( = 6,136,528,896).
Sieh zu, dass du die getPixel()-Aufrufe los wirst und ersetze das durch direkte Zugriffe auf das Pixelarray des Bildes.
 
S

SlaterB

Gast
sind es quasi schon, Image ist ne eigene Klasse,

der Index für das Array wird etwas aufwendig berechnet, a la
> int index = 54 + clrTableSize * 4 + ((width - 1) - setWidth) * height* 3 + 3 * setHeight + setRgb;
aber das dürfte keine Minute ausmachen
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
Atten007 Minecraft Hilfe beim MCreator Plugin benötigt Spiele- und Multimedia-Programmierung 0
Atten007 Minecraft Hilfe beim MCreator Plugin benötigt Spiele- und Multimedia-Programmierung 5
J TreeNode erstellen [Hilfe beim Konstruktor, Zeile 16] Spiele- und Multimedia-Programmierung 2
T Hilfe beim Platzieren der Schiffe Spiele- und Multimedia-Programmierung 14
RalleYTN Brauche Hilfe beim Einlesen von PNGs Spiele- und Multimedia-Programmierung 14
O Problem beim Aufrufen des Spiels von einem Menü Spiele- und Multimedia-Programmierung 7
G LIBGDX Problem beim resizen des Frames Spiele- und Multimedia-Programmierung 3
T Android App Absturz beim Starten Spiele- und Multimedia-Programmierung 41
R Fehler beim Laden eines 2D-Bildes Spiele- und Multimedia-Programmierung 3
T LWJGL 2.9.2: Seltsamer Effekt beim Rendern (VertexShader Problem?) Spiele- und Multimedia-Programmierung 3
T Problem beim Aufbau des Spielfelds Spiele- und Multimedia-Programmierung 18
J Perfomance Probleme beim eigenen Editor Spiele- und Multimedia-Programmierung 1
K Probleme beim kompilieren von javakara Spiele- und Multimedia-Programmierung 10
S [LWJGL] schwarzer Bildschrim beim rendern von .obj Model Spiele- und Multimedia-Programmierung 2
L Probleme beim kompilieren von javakara Spiele- und Multimedia-Programmierung 3
N Problem mit Kollisionsabfrage beim Fallen Jump & Run Spiele- und Multimedia-Programmierung 5
L Problem beim Rätsellöser Spiele- und Multimedia-Programmierung 3
D Problem beim bewegen einer Figur Spiele- und Multimedia-Programmierung 2
M Beim schießen richtet sich die Kugel nach der Maus aus (Quaternion) Spiele- und Multimedia-Programmierung 5
Gossi Probleme beim Laden der Images aus dem "Tutorial für Java-Spiele" Spiele- und Multimedia-Programmierung 4
K Problem beim Anzeigen von Bildern Spiele- und Multimedia-Programmierung 5
D Problem mit Überprüfung beim Lottospiel Spiele- und Multimedia-Programmierung 6
D Problem beim Öffnen einer PHP für eine Highscore Spiele- und Multimedia-Programmierung 5
C Java3D Lichtquelle beim Beobachter Spiele- und Multimedia-Programmierung 2
W CannotRealizeException (jmf) beim abspielen eines liedes Spiele- und Multimedia-Programmierung 3
aze Problem beim Laden von Obj File Spiele- und Multimedia-Programmierung 3
N Jogl Probleme mit dem Buffer beim laden einer Textur Spiele- und Multimedia-Programmierung 2
N Totaler Absturz beim mehrmaligen Abspielen von Sounds Spiele- und Multimedia-Programmierung 5
S Problem beim laden eines Bildes in einer Methode Spiele- und Multimedia-Programmierung 14
S Probleme mit Thread beim Streaming Spiele- und Multimedia-Programmierung 1
B Problem beim Programmieren von 4Gewinnt Spiele- und Multimedia-Programmierung 5
0x7F800000 weiß einer wozu ANTLR beim build von JOGL verwendet wird? Spiele- und Multimedia-Programmierung 3
D Fehler beim Stein Scher papier Spiel Spiele- und Multimedia-Programmierung 3
G Überlagern von Strings beim zeichnen verhindern Spiele- und Multimedia-Programmierung 3
G Weiße, vertikale Streifen beim Scrollen auf der Map Spiele- und Multimedia-Programmierung 4
D Probleme beim Download von GIF-Bildern Spiele- und Multimedia-Programmierung 4
C KI beim Computergegner? Spiele- und Multimedia-Programmierung 2
G Problem beim Zeichnen von LineArrays Spiele- und Multimedia-Programmierung 9
C Problem beim picken Spiele- und Multimedia-Programmierung 10
B Problem beim Programmieren Von Mühle Spiele- und Multimedia-Programmierung 6
T Exception beim starten von Java3d Apps Spiele- und Multimedia-Programmierung 2
B problem beim Memory Logik Spiele- und Multimedia-Programmierung 13
J Problem beim Instaliren Spiele- und Multimedia-Programmierung 8
W Probleme beim entfernen von Childs im HauptSceneGraph Spiele- und Multimedia-Programmierung 8
S Sudoku Solver funktioniert beim 2. Aufruf nicht mehr Spiele- und Multimedia-Programmierung 11
B Probleme beim zeichnen Spiele- und Multimedia-Programmierung 15
N Rundenstrategiespiel - Problem beim Drehen eines Bildes Spiele- und Multimedia-Programmierung 18
C Graphische Benutzerschnittstelle, Problem beim Zeichnen Spiele- und Multimedia-Programmierung 4
0 Crashes beim Abspielen von Sounds unter Win98 Spiele- und Multimedia-Programmierung 12
G Probleme beim installieren java 3d linux Spiele- und Multimedia-Programmierung 4
T Java2D Spiel, beim Hinzufügen eines Bildes ruckelt das ganze Spiele- und Multimedia-Programmierung 3
A Bildfehler beim schnellen neuzeichnen Spiele- und Multimedia-Programmierung 2
D Pfeiltasten beim KeyListener Spiele- und Multimedia-Programmierung 1
I Beim Picking werden alle Behaviors angesprochen Spiele- und Multimedia-Programmierung 4

Ähnliche Java Themen

Neue Themen


Oben