Convolution-Filter: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K (Beispiel Faltungskerne: Bild ohne Filterung hinzugefügt)
K (Daß -> Dass)
 
(17 dazwischenliegende Versionen von 7 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 +
{{Excellent}}
 
== Convolution-Filter ==
 
== Convolution-Filter ==
 
In der Bildverarbeitung spricht man auch von ''Faltungskernen'', in Gimp ist der Begriff ''Faltungsmatrix'' üblich.  
 
In der Bildverarbeitung spricht man auch von ''Faltungskernen'', in Gimp ist der Begriff ''Faltungsmatrix'' üblich.  
Zeile 5: Zeile 6:
 
Bei Ausführung der Filterung wird das Array Pixel für Pixel auf ein Bild bzw. eine Textur anwendet. Dabei werden die Werte im Array mit den Farben des Bildes multipliziert und zusammenaddiert.
 
Bei Ausführung der Filterung wird das Array Pixel für Pixel auf ein Bild bzw. eine Textur anwendet. Dabei werden die Werte im Array mit den Farben des Bildes multipliziert und zusammenaddiert.
  
Ist z.B. ein 3x3-Array als Filterkernel gesetzt, so wird dieser auf jedes Pixel und seine 8 Nachbarpixel um diesen herum angewendet.
+
Ist z.B. ein 3x3-Array als Filterkernel gesetzt, so wird der Mittelpunkt auf jedes Pixel gesetzt und die 8 Nachbarpixel um diesen herum mit den Werten in der Matrix verrechnet. Das Ergebnis dieser Rechnung wird in das Pixel gespeichert was im Zentrum der Matrix lag.
Damit lassen sich interessante Effekte wie z.B. Kontraste, Schärfung, Weichzeichnen, finden von Kanten(Embossing) oder [[Glowing]] erzielen.
+
 
 +
Damit lassen sich interessante Effekte wie z.B. Kontraste, Schärfung, Weichzeichnen, Kantenextraktion(Embossing) oder [[Glowing]] erzielen.
 +
 
 +
 
 +
== Ein klein wenig Theorie ==
 +
Ein (diskreter) Faltungskern g wird auf ein Signal f (z.B. ein Bild) durch eine einfache Rechenvorschrift angewandt:
 +
 
 +
[[Bild:Faltung_Math.png]]
 +
 
 +
Hierbei ist D der gemeinsame Definitionsbereich von f und g. Für Bilder bietet sich hier z.B. das kartesische Quadrat der ganzen Zahlen an. Was also passiert hier? Nehmen wir zuerst den einfachsten Faltunskern
 +
 
 +
[[Bild:Faltung_OhneEffekt.png]]
 +
 
 +
Setzt man diese Funktion in die obige Definition ein, so passiert dem Signal: gar nichts, denn die Summe fällt zusammen und es bleibt immer nur (f*g)(x) = g(0)*f(x) = f(x) stehen. Erweitert man nun den Support (der Bereich, auf dem die Funktion nicht 0 ist) des Faltungskern vom Punkt 0 auf auf den Bereich [-1,1]^2
 +
 
 +
[[Bild:Faltung_Tiefpass.png]]
 +
 
 +
so addiert man durch die Faltung an einer Stelle x des Bildes f mit g, auch alle direkt benachbarten Bildpunkte auf und blendet sie so zusammen - dabei verschwinden die Details im Bild (Details haben in der Signalverarbeitung eine hohe Frequenz) und es bleiben nur die Informationen, die sich lokal um unseren Bildpunkt nicht so sehr ändern (also eine niedrige Frequenz haben); g unterdrückt also hohen Frequenzen und lässt die niedrigen durch - weshalb g ein Tiefpass-Filter genannt wird.
 +
Andererseits erkennt man, dass der Faltungskern g beschreibt, mit welchen Faktoren benachbarte Bildpunkte im Ergebnis zusammengeblendet werden. Der Bereich in dem g gleich 0 ist, ist damit aber völlig unerheblich und man beschränkt sich zum Speichern des Kerns auf dessen Support, was zu den bereits erwähnten Darstellungen mit Matrizen führt.
 +
 
 +
== Faltungskerne und OpenGL ==
 +
Um solche Kerne in OpenGL zu verwenden, gibt es die Funktionen um [[glConvolutionFilter]]. Für eine genauere Referenz der Parameter sollte man sich am besten den Funktionsartikel anschauen. Um einen Gaussischen Blur zu implementieren, ist folgender Code angemessen:
 +
<source lang="pascal">
 +
const
 +
  GaussMatrix: array [0..8] of array [0..8] of Single = (
 +
    (  1/1600,  2/1600,  4/1600,  8/1600,  16/1600,  8/1600,  4/1600,  2/1600,  1/1600),
 +
    (  2/1600,  4/1600,  8/1600,  16/1600,  32/1600,  16/1600,  8/1600,  4/1600,  2/1600),
 +
    (  4/1600,  8/1600,  16/1600,  32/1600,  64/1600,  32/1600,  16/1600,  8/1600,  4/1600),
 +
    (  8/1600,  16/1600,  32/1600,  64/1600, 128/1600,  64/1600,  32/1600,  16/1600,  8/1600),
 +
    ( 16/1600,  32/1600,  64/1600, 128/1600, 256/1600, 128/1600,  64/1600,  32/1600,  16/1600),
 +
    (  8/1600,  16/1600,  32/1600,  64/1600, 128/1600,  64/1600,  32/1600,  16/1600,  8/1600),
 +
    (  4/1600,  8/1600,  16/1600,  32/1600,  64/1600,  32/1600,  16/1600,  8/1600,  4/1600),
 +
    (  2/1600,  4/1600,  8/1600,  16/1600,  32/1600,  16/1600,  8/1600,  4/1600,  2/1600),
 +
    (  1/1600,  2/1600,  4/1600,  8/1600,  16/1600,  8/1600,  4/1600,  2/1600,  1/1600)
 +
  );
 +
  // Eine 9x9 Gaussian Blur Matrix.
 +
 
 +
// ...
 +
begin
 +
  glEnable(GL_CONVOLUTION_2D);
 +
  glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE4, 9, 9, GL_LUMINANCE, GL_FLOAT, @GaussMatrix[0, 0]);
 +
  // Textur laden
 +
end;
 +
</source>
 +
Wie das Ergebnis aussieht ist unter [[Convolution-Filter#Gaussian_Blur|Gaussian Blur]] zu sehen.
 +
 
 +
Für normale Bearbeitungen sollte GL_LUMINANCE angemessen sein, da dort der Filterkern auf die drei Farbkanäle angewandt wird. Als Alternative kann man auch eine Matrix bauen, die für jeden Kanal ein anderes Ergebnis erzielt, indem man die Werte für Rot, Grün und Blau nacheinander in dem Faltungskern ablegt und den fünften Parameter auf GL_RGB setzt, genauso wie den zweiten.
  
 
== Beispiel Faltungskerne ==
 
== Beispiel Faltungskerne ==
  
[[Bild:Conv_Nofilter.jpg|frame|none|Beispielbild ohne Filter]]
+
[[Bild:Anaconda.jpg|frame|none|Originalbild ohne Filter]]
  
  
 
===Tiefpass / Mittelwert===
 
===Tiefpass / Mittelwert===
1 1 1
+
Es wird der Mittelwert zwischen der Farbe des aktuellen Pixels und seinen 8 Nachbarn berechnet und dem aktuellen Pixel zugewiesen. In den Zahlen drück sich dies so aus, dass alle 9 Matrix-Einträge gleichstark (1/9) in die resultierende Farbe eingehen.
1 1 1
 
1 1 1
 
  
[[Bild:Conv_Mittelwert.jpg|frame|none|Mittelwert mit Scale 1/9]]
+
1/9 1/9 1/9
 +
1/9 1/9 1/9
 +
1/9 1/9 1/9
  
 +
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 +
[[Bild:Conv_Mittelwert.jpg]]
  
 
===Schärfung===
 
===Schärfung===
Zeile 26: Zeile 75:
 
   0 -1  0
 
   0 -1  0
  
 +
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 
[[Bild:Conv_Schaerfung.jpg]]
 
[[Bild:Conv_Schaerfung.jpg]]
  
Zeile 34: Zeile 84:
 
   -1 -1 -1  
 
   -1 -1 -1  
  
 +
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 
[[Bild:Conv_Horizontal.jpg]]
 
[[Bild:Conv_Horizontal.jpg]]
  
Zeile 43: Zeile 94:
 
  0 0 -1
 
  0 0 -1
  
 +
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 
[[Bild:Conv_Embossing1.jpg]]
 
[[Bild:Conv_Embossing1.jpg]]
  
Zeile 51: Zeile 103:
 
   0 0 1
 
   0 0 1
  
 +
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 
[[Bild:Conv_Embossing2.jpg]]
 
[[Bild:Conv_Embossing2.jpg]]
  
Zeile 59: Zeile 112:
 
   1  2  1  
 
   1  2  1  
  
 +
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 
[[Bild:Conv_Sobel.jpg]]
 
[[Bild:Conv_Sobel.jpg]]
  
  
 
===Gaussian Blur===
 
===Gaussian Blur===
 +
{{Hinweis|Die hier angegebene Matrix enthält die fertig berechneten Werte. Im Code Beispiel oben finden sie die Version mit Brüchen. Diese ist leichter verständlich, und schöner anzusehen. Die hier angegebene spart allerdings die Rechenoperationen.}}
 
  0.00000067 0.00002292 0.00019117 0.00038771 0.00019117 0.00002292 0.00000067
 
  0.00000067 0.00002292 0.00019117 0.00038771 0.00019117 0.00002292 0.00000067
 
  0.00002292 0.00078633 0.00655965 0.01330373 0.00655965 0.00078633 0.00002292
 
  0.00002292 0.00078633 0.00655965 0.01330373 0.00655965 0.00078633 0.00002292
 
  0.00019117 0.00655965 0.05472157 0.11098164 0.05472157 0.00655965 0.00019117
 
  0.00019117 0.00655965 0.05472157 0.11098164 0.05472157 0.00655965 0.00019117
 
  0.00038771 0.01330373 0.11098164 0.22508352 0.11098164 0.01330373 0.00038771
 
  0.00038771 0.01330373 0.11098164 0.22508352 0.11098164 0.01330373 0.00038771
  0.00019117 0.00655965 0.05472157 0.11098164 0.05472157 0.00655965 0.00019117
+
  0.00019117 0.00655965 0.05472157 0.11098164 0.05472157 0.00655965 0.00019117
  0.00002292 0.00078633 0.00655965 0.01330373 0.00655965 0.00078633 0.00002292
+
  0.00002292 0.00078633 0.00655965 0.01330373 0.00655965 0.00078633 0.00002292
 
  0.00000067 0.00002292 0.00019117 0.00038771 0.00019117 0.00002292 0.00000067  
 
  0.00000067 0.00002292 0.00019117 0.00038771 0.00019117 0.00002292 0.00000067  
  
[[Bild:Conv_GaussianBlur2.jpg|frame|none|Gaussian Blur mit Bias 0.01]]
+
[[Bild:Anaconda.jpg|Originalbild ohne Filter]]
 +
[[Bild:Conv_GaussianBlur2.jpg|Gaussian Blur mit Bias 0.01]]
  
 
== OpenGL-Befehle ==
 
== OpenGL-Befehle ==
Zeile 78: Zeile 134:
  
 
==Siehe Auch==
 
==Siehe Auch==
[http://www.vbaccelerator.com/home/VB/Code/vbMedia/Image_Processing/Blurring__Sharpening_and_Embossing/article.asp Beschreibung einiger Faltungskerne (englisch)]
+
[http://www-user.tu-chemnitz.de/~stj/lehre/bild.pdf Bildverarbeitungsscript von Dr. Steinmüller TU Chemnitz (deutsch)] Ausführliche Beschreibung von Faltungskernen ab Kapitel 2.3
 +
 
 +
[http://www.vbaccelerator.com/home/VB/Code/vbMedia/Image_Processing/Blurring__Sharpening_and_Embossing/article.asp Beschreibung einiger Faltungskerne (englisch)

Aktuelle Version vom 18. März 2012, 17:01 Uhr

Hinweis: Dieser Artikel wurde von den Benutzern des Wikis zum exzellenten Artikel berufen!
(weitere exzellente Artikel)
Excelent.jpg

Convolution-Filter

In der Bildverarbeitung spricht man auch von Faltungskernen, in Gimp ist der Begriff Faltungsmatrix üblich.

Ein Convolution-Filter ist ein ein- bzw. zweidimensionales Array, dessen Werte Gewichtungen darstellen. Bei Ausführung der Filterung wird das Array Pixel für Pixel auf ein Bild bzw. eine Textur anwendet. Dabei werden die Werte im Array mit den Farben des Bildes multipliziert und zusammenaddiert.

Ist z.B. ein 3x3-Array als Filterkernel gesetzt, so wird der Mittelpunkt auf jedes Pixel gesetzt und die 8 Nachbarpixel um diesen herum mit den Werten in der Matrix verrechnet. Das Ergebnis dieser Rechnung wird in das Pixel gespeichert was im Zentrum der Matrix lag.

Damit lassen sich interessante Effekte wie z.B. Kontraste, Schärfung, Weichzeichnen, Kantenextraktion(Embossing) oder Glowing erzielen.


Ein klein wenig Theorie

Ein (diskreter) Faltungskern g wird auf ein Signal f (z.B. ein Bild) durch eine einfache Rechenvorschrift angewandt:

Faltung Math.png

Hierbei ist D der gemeinsame Definitionsbereich von f und g. Für Bilder bietet sich hier z.B. das kartesische Quadrat der ganzen Zahlen an. Was also passiert hier? Nehmen wir zuerst den einfachsten Faltunskern

Faltung OhneEffekt.png

Setzt man diese Funktion in die obige Definition ein, so passiert dem Signal: gar nichts, denn die Summe fällt zusammen und es bleibt immer nur (f*g)(x) = g(0)*f(x) = f(x) stehen. Erweitert man nun den Support (der Bereich, auf dem die Funktion nicht 0 ist) des Faltungskern vom Punkt 0 auf auf den Bereich [-1,1]^2

Faltung Tiefpass.png

so addiert man durch die Faltung an einer Stelle x des Bildes f mit g, auch alle direkt benachbarten Bildpunkte auf und blendet sie so zusammen - dabei verschwinden die Details im Bild (Details haben in der Signalverarbeitung eine hohe Frequenz) und es bleiben nur die Informationen, die sich lokal um unseren Bildpunkt nicht so sehr ändern (also eine niedrige Frequenz haben); g unterdrückt also hohen Frequenzen und lässt die niedrigen durch - weshalb g ein Tiefpass-Filter genannt wird. Andererseits erkennt man, dass der Faltungskern g beschreibt, mit welchen Faktoren benachbarte Bildpunkte im Ergebnis zusammengeblendet werden. Der Bereich in dem g gleich 0 ist, ist damit aber völlig unerheblich und man beschränkt sich zum Speichern des Kerns auf dessen Support, was zu den bereits erwähnten Darstellungen mit Matrizen führt.

Faltungskerne und OpenGL

Um solche Kerne in OpenGL zu verwenden, gibt es die Funktionen um glConvolutionFilter. Für eine genauere Referenz der Parameter sollte man sich am besten den Funktionsartikel anschauen. Um einen Gaussischen Blur zu implementieren, ist folgender Code angemessen:

const
  GaussMatrix: array [0..8] of array [0..8] of Single = (
    (  1/1600,   2/1600,   4/1600,   8/1600,  16/1600,   8/1600,   4/1600,   2/1600,   1/1600),
    (  2/1600,   4/1600,   8/1600,  16/1600,  32/1600,  16/1600,   8/1600,   4/1600,   2/1600),
    (  4/1600,   8/1600,  16/1600,  32/1600,  64/1600,  32/1600,  16/1600,   8/1600,   4/1600),
    (  8/1600,  16/1600,  32/1600,  64/1600, 128/1600,  64/1600,  32/1600,  16/1600,   8/1600),
    ( 16/1600,  32/1600,  64/1600, 128/1600, 256/1600, 128/1600,  64/1600,  32/1600,  16/1600),
    (  8/1600,  16/1600,  32/1600,  64/1600, 128/1600,  64/1600,  32/1600,  16/1600,   8/1600),
    (  4/1600,   8/1600,  16/1600,  32/1600,  64/1600,  32/1600,  16/1600,   8/1600,   4/1600),
    (  2/1600,   4/1600,   8/1600,  16/1600,  32/1600,  16/1600,   8/1600,   4/1600,   2/1600),
    (  1/1600,   2/1600,   4/1600,   8/1600,  16/1600,   8/1600,   4/1600,   2/1600,   1/1600)
  );
  // Eine 9x9 Gaussian Blur Matrix.

// ...
begin
  glEnable(GL_CONVOLUTION_2D);
  glConvolutionFilter2D(GL_CONVOLUTION_2D, GL_LUMINANCE4, 9, 9, GL_LUMINANCE, GL_FLOAT, @GaussMatrix[0, 0]);
  // Textur laden
end;

Wie das Ergebnis aussieht ist unter Gaussian Blur zu sehen.

Für normale Bearbeitungen sollte GL_LUMINANCE angemessen sein, da dort der Filterkern auf die drei Farbkanäle angewandt wird. Als Alternative kann man auch eine Matrix bauen, die für jeden Kanal ein anderes Ergebnis erzielt, indem man die Werte für Rot, Grün und Blau nacheinander in dem Faltungskern ablegt und den fünften Parameter auf GL_RGB setzt, genauso wie den zweiten.

Beispiel Faltungskerne

Originalbild ohne Filter


Tiefpass / Mittelwert

Es wird der Mittelwert zwischen der Farbe des aktuellen Pixels und seinen 8 Nachbarn berechnet und dem aktuellen Pixel zugewiesen. In den Zahlen drück sich dies so aus, dass alle 9 Matrix-Einträge gleichstark (1/9) in die resultierende Farbe eingehen.

1/9 1/9 1/9
1/9 1/9 1/9
1/9 1/9 1/9

Originalbild ohne Filter Conv Mittelwert.jpg

Schärfung

 0 -1  0
-1  5 -1
 0 -1  0

Originalbild ohne Filter Conv Schaerfung.jpg


Horizontale Schärfung

 -1 -1 -1
  2  3  2
 -1 -1 -1 

Originalbild ohne Filter Conv Horizontal.jpg


Embossing (Kantenfindung)

Richtung links oben

1 0 0
0 0 0
0 0 -1

Originalbild ohne Filter Conv Embossing1.jpg


Richtung rechts unten

-1 0 0
 0 0 0
 0 0 1

Originalbild ohne Filter Conv Embossing2.jpg


Sobel-Filter

-1 -2 -1
 0  1  0
 1  2  1 

Originalbild ohne Filter Conv Sobel.jpg


Gaussian Blur

Info DGL.png Die hier angegebene Matrix enthält die fertig berechneten Werte. Im Code Beispiel oben finden sie die Version mit Brüchen. Diese ist leichter verständlich, und schöner anzusehen. Die hier angegebene spart allerdings die Rechenoperationen.
0.00000067 0.00002292 0.00019117 0.00038771 0.00019117 0.00002292 0.00000067
0.00002292 0.00078633 0.00655965 0.01330373 0.00655965 0.00078633 0.00002292
0.00019117 0.00655965 0.05472157 0.11098164 0.05472157 0.00655965 0.00019117
0.00038771 0.01330373 0.11098164 0.22508352 0.11098164 0.01330373 0.00038771
0.00019117 0.00655965 0.05472157 0.11098164 0.05472157 0.00655965 0.00019117
0.00002292 0.00078633 0.00655965 0.01330373 0.00655965 0.00078633 0.00002292
0.00000067 0.00002292 0.00019117 0.00038771 0.00019117 0.00002292 0.00000067 

Originalbild ohne Filter Gaussian Blur mit Bias 0.01

OpenGL-Befehle

glConvolutionFilter1D, glConvolutionFilter2D, glConvolutionParameter, glGetConvolutionFilter, glGetConvolutionParameter


Siehe Auch

Bildverarbeitungsscript von Dr. Steinmüller TU Chemnitz (deutsch) Ausführliche Beschreibung von Faltungskernen ab Kapitel 2.3

[http://www.vbaccelerator.com/home/VB/Code/vbMedia/Image_Processing/Blurring__Sharpening_and_Embossing/article.asp Beschreibung einiger Faltungskerne (englisch)