Richard: Sobel-Operator

Beitrag lesen

Hallo,

ich implementiere gerade ein paar Bildbearbeitungsalgorithmen in Java (wobei die Sprache für das Problem irrelevant ist) und hänge gerade etwas beim Sobel-Operator. Ich hatte den vor einiger Zeit schonmal erfolgreich in C# umgesetzt, doch leider habe ich den Code nicht aufgehoben.

Die Ergebnisbilder sehen im Prinzip richtig aus, aber bei genauerem Hinsehen merkt man (je nach Bild), das irgendetwas nicht so ganz stimmt. Einige Bilder zeigen starkes Rauschen, das ich mir nicht erklären kann, bei anderen wiederum ist das Ergebnis eigentlich perfekt.

Zur Verdeutlichung mal ein besonders schlimmes Beispiel:

Original und Ergebnis der Faltung

Hier allerdings ein Bild, das mit exakt demselben Code bearbeitet wurde, aber im Ergebnis wesentlich besser ist:

Original und Ergebnis der Faltung

Und hier der relevante Code:

  
public int[][] getYKernel() {  
    return new int[][]  
        {  
	    {1, 0, -1},  
	    {2, 0, -2},  
            {1, 0, -1}  
        };  
}  
  
public int[][] getXKernel() {  
    return new int[][]  
        {  
            {1, 2, 1},  
	    {0, 0, 0},  
	    {-1, -2, -1}  
	};  
}  
  
public final void applyOperation() {  
	final int[][] Sx = getXKernel();  
	final int[][] Sy = getYKernel();  
  
	int gx = 0, gy = 0, g = 0;  
  
	for(int y = 0; y < source.getHeight(); y++) {  
	    for(int x = 0; x < source.getWidth(); x++) {  
  
		// Farbwerte des letzten Pixels zurück auf 0 setzen  
		gx = 0; gy = 0; g = 0;  
  
		// Sx traversieren  
		for(int ySx = -1; ySx <= 1; ySx++) {  
		    for(int xSx = -1; xSx <= 1; xSx++) {  
  
			// Grenzen des Bildes prüfen  
			if(y + ySx >= 0 && y + ySx < source.getHeight() &&  
				x + xSx >= 0 && x + xSx < source.getWidth()) {  
			    /* Pixel existiert  
			     * Neuer Pixelwert ergibt sich aus der Summe der Produkte  
			     * der jeweils korrespondierenden Pixel aus Bild und Matrix  
			     */  
			    gx += source.getSample(0, x + xSx, y + ySx) *  
			    	Sx[xSx + 1][ySx + 1];  
			}  
  
		    }  
		}  
  
		// Sy traversieren  
		for(int ySy = -1; ySy <= 1; ySy++) {  
		    for(int xSy = -1; xSy <= 1; xSy++) {  
  
			// Grenzen des Bildes prüfen  
			if(y + ySy >= 0 && y + ySy < source.getHeight() &&  
				x + xSy >= 0 && x + xSy < source.getWidth()) {  
			    /* Pixel existiert  
			     * Neuer Pixelwert ergibt sich aus der Summe der Produkte  
			     * der jeweils korrespondierenden Pixel aus Bild und Matrix  
			     */  
			    gy += source.getSample(0, x + xSy, y + ySy) *  
			    	Sy[xSy + 1][ySy + 1];  
			}  
  
		    }  
		}  
  
		/* neuen Farbwert aus beiden Filtern berechnen  
		 * und auf 255 skalieren!  
		 */  
		g = (int) Math.round(Math.sqrt(gx * gx + gy * gy));  
		// neuen Pixel setzen  
		if(applyThreshold) {  
		    for(int channel = 0; channel < 3; channel++) {  
    		        destination.putSample(channel, x, y, g >= threshold ? 255 : 0);  
    		    }  
		} else {  
    		    for(int channel = 0; channel < 3; channel++) {  
    		        destination.putSample(channel, x, y, g);  
    		    }  
		}  
  
	    }  
	}  
    }

Was mache ich falsch?

Grüße
Richard