10 Schnelle Fourier-Transformation Pn 10.1 Schnelle Polynommultiplikation Mit Grad ≤ n bezeichnet. Sind p, q ∈ n−1 , so gilt mit P p(x) = an−1 xn−1 + . . . + a1 x + a0 , hatten wir den Raum der Polynome vom q(x) = bn−1 xn−1 + . . . + b1 x + b0 , für das Produkt r(x) = p(x)q(x) = 2n−2 X c l xl , cl = X j+k=l l=0 aj bk , l = 0, . . . , 2n − 2, wobei die Konvention aj , bj = 0 für j > n − 1 verwendet wurde. Da jeder Koeffizient des einen Polynoms mit jedem Koeffizienten des anderen Polynoms multipliziert wird, benötigen wir für die direkte Polynommultiplikation genau n2 Multiplikationen und O(n2 ) Additionen. Eine Alternative zur direkten Multiplikation ist die in Kapitel 5 besprochene Polynominterpolation nach Lagrange. Demnach ist ein Polynom vom Grade n − 1 durch die Werte p(xj ) an n verschiedenen Stützstellen x1 , . . . , xn eindeutig bestimmt. Da das Produkt r(x) = p(x)q(x) im Raum 2n−2 liegt, genügt es, die Polynome p und q an 2n − 1 verschiedenen Stellen auszuwerten, die 2n−1 Produkte p(xj )q(xj ) zu berechnen und anschließend das Interpolationspolynom zu diesen Produkten zu bestimmen. Da das Interpolationspolynom eindeutig bestimmt ist, wird durch diese Vorgehensweise das Produktpolynom reproduziert. Dieses Verfahren ist zunächst weniger effektiv als die direkte Methode, denn selbst wenn das Interpolationspolynom nach der Newton-Formel bestimmt wird, werden dazu O(n2 ) Operationen benötigt und die Auswertung des Newton-Polynoms kostet O(n) Operationen für jeden Interpolationspunkt. P Die Idee der schnellen Polynommultiplikation besteht in einer vorteilhaften Wahl der Stützstellen xj , die eine simultane Auswertung von p(xj ) gestattet. Dazu ist anzumerken, dass der Satz über die Lagrange-Interpolation aus Abschnitt 5.1 auch für komplexe Stützstellen richtig bleibt: Die Lagrange-Polynome lk (x) = Y x − xi (x − x1 ) . . . (x − xk−1 )(x − xk+1 ) . . . (x − xn ) = . (xk − x1 ) . . . (xk − xk−1 )(xk − xk+1 ) . . . (xk − xn ) xk − xi i6=k C P fj lj (x) löst die Interpolationsaufgabe p(xj ) = fj . sind auch für xj ∈ wohldefiniert und p(x) = Auch der Beweis der Eindeutigkeit des Interpolationspolynoms überträgt sich wörtlich aus dem reellen Fall. Um ein Polynom an n Stellen auszuwerten, verwenden wir die komplexen Einheitswurzeln ωn = exp Für diese gilt 2πi , n ωnk = exp 2kπi ωnk = ωnk+ln (10.1) n ∀l ∈ , k = 0, . . . , n − 1. Z wegen exp(z) = exp(z + 2πi). Sei nun n gerade und p ein Polynom vom Grade ≤ n − 1. Wir schreiben p(x) = an−1 xn−1 + an−2 xn−2 + . . . + a2 x2 + a1 x + a0 = (an−2 xn−2 + . . . + a2 x2 + a0 ) + x(an−1 xn−2 + . . . + a3 x2 + a1 ) = pg (x2 ) + xpu (x2 ). 104 Um p(ωnk ), k = 0, . . . , n − 1 zu bestimmen, müssen die Polynome pg und pu , die nur noch den k ausgewertet werden, mit (10.1) sind dies Grad n/2 − 1 besitzen, an den Stellen ωn2k = ωn/2 n/2−1 0 ,...,ω ωn/2 n/2 . Ferner lassen sich die Auswertungen von pg und pu zweimal verwenden, nämlich 2k+2n/2 für k = 0, . . . , n/2 − 1 und für k + n/2 wegen ωn2k = ωn . Da das beschriebene Verfahren offenbar rekursiv durchgeführt werden kann, wenn n eine Zweierpotenz ist, nehmen wir nun n = 2l an. Das Programm procedure F F T (n, p, ω, a) bestimmt die Auswertung eines Polynoms vom Grade n − 1 in den n Punkten ωn0 , . . . , ωnn−1 . Die Zweierpotenz n gibt die Länge des Problems an, in der Inputvariablen p ist das auszuwertende Polynom als n-Vektor p = (a0 , . . . , an−1 ) gespeichert. Ferner haben wir die Inputvariable ω = ωn . Das Ergebnis ist der n-Vektor a = (p(ω 0 ), . . . , p(ω n−1 )). Die schnelle Polynomauswertung kann damit folgendermaßen implementiert werden: recursive subroutine F F T (n, p, ω, a) if n = 1 then a(0) = p(0) else n2 = n/2 pg = (a0 , a2 , . . . , an−2 ) pu = (a1 , a3 , . . . , an−1 ) call F F T (n2 , pg , ω 2 , g) call F F T (n2 , pu , ω 2 , u) do k = 0, n2 − 1 a(k) = g(k) + ω k u(k) a(k + n2 ) = g(k) − ω k u(k) enddo endif end k+n/2 Zur Einsparung von Rechenoperationen wurde von der Beziehung ωn brauch gemacht. n/2 = ωnk ωn = −ωnk Ge- Nun bestimmen wir die Anzahl der Multiplikationen M (n) für diesen Algorithmus. Da die Zahlen ω k einmal berechnet und anschließend abgespeichert werden können, fallen in der DoSchleife nur die n/2 Multiplikationen ω k u(k) an. Da F F T zweimal mit Inputlänge n/2 aufgerufen wird, genügt M (n) der Rekursion n n M (n) = 2M + 2 2 für n = 2l daher M (2l ) = 2M (2l−1 ) + 2l−1 . Iterieren wir diese Beziehung l mal, so erhalten wir M (2l ) = l2l−1 + M (1)2l . Da im Then-Teil des obigen Programms keine Operationen anfallen, ist M (1) = 0 und daher M (n) = n log n, 2 wobei mit log der Logarithmus zur Basis 2 bezeichnet wird. Da für die Anzahl der Addditionen eine analoge rekursive Beziehung gilt, erhalten wir für die Gesamtzahl an Operationen ebenfalls O(n log n). 105 Nun wenden wir uns dem Interpolationsproblem zu: Zu Daten b0 , . . . , bn−1 ist ein Polynom p ∈ n−1 gesucht mit p(ωnk ) = bk für k = 0, . . . , n − 1. Wie bereits zu Anfang dieses Abschnitts gezeigt wurde, existiert ein solches Polynom und ist eindeutig bestimmt. Um dieses Problem anzugehen, deuten wir zunächst die Polynomauswertung als Multiplikation einer Matrix mit einem Vektor. Zu α = (α0 , . . . , αn−1 )T ∈ n mit paarweise verschiedenen αk definieren wir die zugehörige Vandermondsche Matrix als 1 α0 α02 · · · α0n−1 1 α1 α12 · · · α1n−1 . V (α) = . . . . . . .. .. .. .. . n−1 2 1 αn−1 αn−1 · · · αn−1 P C Für ein Polynom p(x) = n−1 X aj xj j=0 gilt dann (10.2) b := p(α0 ), . . . , p(αn−1 ) T a = (a0 , . . . , an−1 )T . = V (α)a, Die Auswertung von p an den Stellen α0 , . . . , αn−1 ist also nichts anderes als die Bestimmung von V (α)a. Die Rekonstruktion der Koeffizienten a0 , . . . , an−1 aus den Daten bk = p(αk ) (=Interpolation) ist das dazu inverse Problem und wird durch a = V (α)−1 b gelöst. Bei der speziellen Wahl α = (ωn0 , . . . , ωnn−1 )T kann die inverse Matrix zu V (α) leicht angegeben werden. Für eine komplexe Zahl β schreiben wir [β] = (β 0 , . . . , β n−1 )T . Satz 10.1 Für die n-te Einheitswurzel ωn = exp(2πi/n) gilt V ([ωn ])−1 = 1 V ([ωn−1 ]). n Beweis: Für die Matrix W = V ([ωn ])V ([ωn−1 ]) gilt wjk = n−1 X ωnjl ωn−kl = n−1 X (ωnj−k )l . l=0 l=0 Für j = k erhalten wir wjj = n. Für j 6= k ist 0 < |j − k| < n und damit ωnj−k 6= 1. Wir können daher die geometrische Summenformel anwenden, also n−1 X (ωnj−k )l = (10.3) l=0 n(j−k) wegen ωn n(j−k) ωn ωnj−k −1 −1 =0 = (ωnn )j−k = 1. Der Algorithmus zur Bestimmung des Interpolationspolynoms p ∈ b := p(1), p(ωn1 ), . . . , p(ωnn−1 ) , Pn−1 aus den Daten subroutine F F I(n, b, ω, p), hat als Input die Länge n = 2l , den n-Vektor b und ω = ωn . Das gesuchte Polynom wird auf dem n-Vektor p = (a0 , . . . , an−1 ) ausgegeben. 106 subroutine F F I(n, b, ω, p) call F F T (n, b, ω −1 , p) p = n−1 p end P Der Algorithmus zur schnellen Multiplikation von Polynomen p, q ∈ k ergibt sich nun fast von selbst. Wir bestimmen die kleinste Zahl l mit n = 2l > 2k und rufen mit ω = ωn F F T (n, p, ω, a), F F T (n, q, ω, b) auf. Anschließend berechnen wir c(k) = a(k)b(k) für k = 0, . . . , n − 1, was n Multiplikationen entspricht. Mit dem Aufruf von F F I(n, c, ω, r) stehen auf dem Vektor r die Koeffizienten des gesuchten Produkts p(x)q(x). Der gesamte Algorithmus benötigt immer noch O(n log n) und wegen n ≤ 4k auch O(k log k) Rechenoperationen. In der vorgestellten Form ist der Algorithmus aber noch problematisch. Zunächst bringt der Algorithmus nur dann einen beträchtlichen Gewinn gegenüber dem Standardverfahren, wenn grad p und grad q von gleicher Größenordnung sind. Beispielsweise hat das Standardverfahren im Extremfall grad p = 1 und grad q = n die Komplexität O(n), während die schnelle Polynommultiplikation immer noch von der Ordnung O(n ln n) ist. Dies wird man sicherlich als weniger gravierend ansehen. Bedeutsamer ist dagegen die implizit verwendete Definition des Wortes Operation“. Auch wenn ” die Koeffizienten der beteiligten Polynome ganzzahlig sind, werden im Algorithmus nicht rationale komplexe Zahlen benötigt, die auf einem Rechner gar nicht exakt dargestellt werden können. Stattdessen müssen die Operationen mit einer Gleitkommaarithmetik näherungsweise bestimmt werden und es dürfte klar sein, dass man für großes n auch eine umfangreiche Gleitkommaarithmetik benötigt. 10.2 Schnelle Multiplikation natürlicher Zahlen Liegen natürliche Zahlen a, b in einem Stellenwertsystem zur Basis g vor und besitzen diese Zahlen eine Länge ≤ K, so lassen sie sich mit O(K 2 ) Operationen multiplizieren, wobei eine Operation aus der Multiplikation zweier Ziffern oder der Addition zweier ganzer Zahlen besteht. Alternativ können wir a und b die Polynome pa (x) = K−1 X i ai x , pb (x) = K−1 X bi x i i=0 i=0 zuordnen, wobei ai , bi ∈ {0, 1 . . . , g − 1} die zugehörigen Ziffern sind. Mit der schnellen Polynommultiplikation kann pc (x) = pa (x)pb (x) bestimmt werden. pc (g) ist dann das gesuchte Produkt der beiden Zahlen, aus dem noch der Übertrag entfernt werden muss. Mit dem im vorigen Abschnitt dargestellten Multiplikationsverfahren erhalten wir aufgrund von Rundungsfehlern ein Polynom p̃c , dessen Koeffizienten Gleitkommazahlen sind. Die verwendete Gleitkommaarithmetik muss so ausgelegt sein, dass aus p̃c durch Rundung das korrekte Polynom pc entsteht. Da die Rundungsfehleranalyse der diskreten Fouriertransformation aufgrund ihrer rekursiven Struktur recht aufwendig ist, soll hier nur das Endergebnis referiert werden. Wir betrachten den Spezialfall K = 2k und g = 2l , mit dem Zahlen der Bitlänge n ≤ 21 Kl miteinander multipliziert werden können. Verwenden wir für die schnelle Fouriertransformation eine Gleitkommaarithmetik der Genauigkeit 2−m , so erhält man nach Rundung von p̃c das exakte Polynom pc , falls m ≥ 3k + 2l + log k + 7/2 erfüllt ist. Für k ≥ 7 erhalte wir hieraus die bequemere Abschätzung m ≥ 4k + 2l. 107 Um Zahlen der Bitlänge n = 213 = 8192 miteinander zu multiplizieren, können wir hier l = 8, k = 11 setzen und erhalten m = 54, was von einer doppelt genauen Gleitkommaarithmetik geleistet wird. Für die meisten praktisch relevanten Fälle lassen sich damit zwei n-stellige Zahlen in O(n log n) Gleitkommaoperationen miteinander multiplizieren. Für die Multiplikation noch größerer Zahlen kann auch die Gleitkommamultiplikation mit Hilfe der schnellen Fouriertransformation beschleunigt werden. Für den Gesamtalgorithmus haben wir dann eine Komplexität von O(n log n log(log n)), die allerdings auch nur bis zu einer sehr großen Zahl n richtig ist. In der modalen Fouriertransformation von Schönhage und Strassen (1971) werden kommutative unitäre Ringe mit n-ter Einheitswurzel verwendet, die letztlich aus ganzen Zahlen bestehen. Damit kann man zwei n-stellige Zahlen in O(n log n log(log n)) miteinander multiplizieren, in diesem Fall ohne Einschränkung an n. Im folgenden schreiben wir 10.3 Diskrete Fourier-Transformation und Bildverarbeitung einen Vektor des n in der Form C f = (f (0), f (1), . . . , f (n − 1)). Wir stellen uns f als eine eindimensionale stückweise konstante Funktion vor oder noch besser als die (reellen) Grauwerte eines eindimensionalen Bildes. n wird immer als geradzahlig vorausgesetzt. Für k = 0, . . . , n − 1 definieren wir die diskreten Wellenfunktionen φk (j) = exp 2πik j , n j = 0, . . . , n − 1, i= √ −1. Die Größe 2πk n ist die Frequenz der Wellenfunktion φk . Die Funktion φ0 ist konstant 1 und φ1 (j) führt für j = 0, . . . , n − 1 eine volle Cosinus- bzw. Sinus-Schwingung in Realbzw. Imaginärteil durch. Für beliebiges k ≥ 1 gilt θk = φ0 Re φ 1 φn−k (j) = exp(2πij(n − k)/n) = exp(2πj) exp(−2πijk/n) = φk (j). Für k < n/2 spannen daher φk und φn−k den zweidimensionalen reellen Raum φ N/2 span {cos(2πjk/n), sin(2πjk/n)} auf. Für kleine k entsprechen φk , φn−k langen Wellen, zu k ∼ n/2 gehören kurze Wellen. Auf dem n verwenden wir das Standardprodukt C (f, g)n = n−1 X f (j) g(j). j=0 Satz 10.2 Die Funktionen φk , k = 0, . . . , n − 1, bilden eine Orthogonalbasis des (φk , φl )n = nδkl . 108 Cn, es gilt Beweis: Wir zeigen zunächst n−1 X exp(2πikr/n) = k=0 ( n falls r = ln für ein l ∈ Z 0 für alle sonstigen ganzzahligen r . Für r = ln ist dies klar. Für r 6= ln können wir mit exp(2πikr/n) = exp(2πir/n)k = ω k wie in (10.3) die geometrische Summenformel anwenden, n−1 X exp(2πikr/n) = n−1 X ωk = k=0 k=0 ωn − 1 =0 ω−1 wegen ω n = 1. Aus obiger Identität folgt für k, l = 0, . . . , n − 1 (φk , φl )n = n−1 X exp(2πijk/n) exp(−2πijl/n) = j=0 n−1 X j=0 exp(2πij(k − l)/n) = nδkl . Ist {vk } eine Orthogonalbasis eines komplexen Pendlich dimensionalen Raumes mit Produkt (·, ·), so gilt für jeden Vektor u dieses Raumes u = k αk vk . Wir multiplizieren diese Identität skalar mit vl und erhalten wegen der Orthogonalität der vk X (αk vk , vl ) = αl (vl , vl ) (u, vl ) = und daher k (10.4) αl = (u, vl ) . (vl , vl ) Im Spezialfall der diskreten Fourier-Transformation sind die vk die Wellenfunktionen φk . Mit Satz 10.2 und (10.4) ist die Fourier-Transformierte Fn f ∈ n definiert durch C n−1 (10.5) 1X 1 Fn f (l) = (f, φl )n = f (j) exp(−2πijl/n), n n j=0 l = 0, . . . , n − 1. Fn ordnet jeder diskreten Funktion fPdie Amplituden der Wellenfunktionen zu: Fn f (l) ist der Koeffizient αl in der Darstellung f = l αl φl . Die Umkehrung der Fourier-Transformation sieht fast genauso aus wie die FourierTransformation selbst, es gilt für alle j (10.6) f (j) = (Fn f, φj ) = n−1 X l=0 wegen n−1 X l=0 Fn f (l)φl (j) = Fn f (l) exp(2πijl/n) = = n−1 X l=0 Fn f (l) exp(2πijl/n), n−1 1 X f (r) exp(−2πirl/n) exp(2πijl/n) n l,r=0 n−1 n−1 r=0 l=0 X 1X exp(2πil(j − r)/n) f (r) n n−1 1X = f (r) nδr,j = f (j) n r=0 109 √ √ Manchmal wird der Faktor n1 durch 1/ n ersetzt und in (10.6) ein Faktor 1/ n hinzugefügt. Auf diese Weise stehen sich der Originalraum“ und der Fourier-Raum“ vollständig symmetrisch ” ” gegenüber. Wir ordnen f das Polynom pf (x) = f (n − 1)xn−1 + . . . + f (1)x + f (0) zu. Dann gilt wegen exp(jr) = exp(r)j Fn f (l) = 1 pf (exp(−2πil/n)). n Mit ωn = exp(2πi/n) ist damit pf an den Stellen ω ln auszuwerten. Dies entspricht genau dem Algrithmus FFI aus dem letzten Abschnitt. Die Rücktransformation ist analog durch Auswertung eines Polynoms an den Stellen ωnl gegeben, was der Algorithmus FFT leistet. Wir können daher Fourier-Transformation und Rücktransformation in O(n log n) Operationen durchführen. 10.4 Abklingverhalten und diskrete Cosinus-Transformation Ist ein Datensatz f (0), . . . , f (n − 1) strukturlos, kann nicht komprimiert werden. Stellt aber f beispielsweise die Grautöne eines eindimensionalen Bildes dar, so wird f über weite Strecken nur wenig variieren mit Ausnahme von einigen Kanten. Wir bezeichnen eine solche Funktion als glatt oder stückweise glatt. Bei glatten Funktionen klingen die Amplituden, die zu Wellenfunktionen mit hoher Frequenz gehören, schneller ab als bei nichtglatten Funktionen. Daher liegt es als erste Idee für eine Bildkompression nahe, eine Fourier-Transformation durchzuführen, jedoch nur die langwelligen Amplituden abzuspeichern. Bei glatten Bildern ist eine solche Kompression mit bloßem Auge nicht mehr sichtbar, sie wird allerdings an sehr scharfen Kanten entlarvt, die durch die Kompression etwas verschmiert werden. Aus diesem Grund werden in der JPEG-Kompression alle Amplituden berücksichtigt, die höheren Frequenzen aber nur näherungsweise abgespeichert. Bevor dies genauer beschreiben können, müssen wir uns darüber klar werden, dass nicht die Glattheit der Funktion f über das Abklingverhalten entscheidet, sondern die Glattheit der periodisch fortgesetzten Funktion. Sei n der Einfachheit halber geradzahlig. In der nebenstehenden Zeichnung sehen wir eine glatte Funktion f und φn/2 , das ist die am schnellsten oszillierende Wellenfunktion. Aufgrund des glatten Verhaltens von f heben sich die Summanden in P f (j)φn/2 (j) fast gegenseitig auf. Aus dem Bild geht aber auch hervor, dass die zugehörige Amplitude noch kleiner wäre, wenn auch die auf periodisch fortgesetzte Funktion f Z f (j + k(n − 1)) = f (j), Z k∈ , glatt ist. Um die Glattheitseigenschaften der fortgesetzten Funktion zu verbessern, wird f durch symmetrische Spiegelung zu einer Funktion in 2n fortgesetzt, C (10.7) f (2n − 1 − j) = f (j), .... 0 .... N-1 2N-1 j = 0, . . . , n − 1. C Nun wird im Prinzip eine Fourier-Transformation auf 2N für dieses fortgesetzte f durchgeführt. Da die Freiheiten des Grundraumes C n durch die Spiegelung nicht erhöht wurde, muss es möglich sein, mit n Fourier-Koeffizienten für die exakte Darstellung von f auszukommen. Setzt man f zusätzlich als reellwertig voraus, was wir von nun an immer tun werden, so muss auch eine reellwertige 110 Darstellung der Fourier-Koeffizienten erreicht werden können. Wir verwenden daher die CosinusTransformation n−1 X π(2j + 1)l f (j) cos Cn f (l) = c(l) 2n j=0 mit Rücktransformation f (j) = n−1 X c(l)Cn f (l) cos l=0 p √ mit c(0) = 1/ n und c(l) = 2/n für l 6= 0. π(2j + 1)l , 2n Diese Formeln erklären sich aus der Tatsache, dass die reellen Wellenfunktionen ψl (j) = cos π(2j + 1)l 2n für l = 0, . . . , n − 1 ein Orthogonalsystem bilden bezüglich des Produkts (f, g) = n−1 X f (j)g(j). j=0 Die Cosinus-Transformation wird aus der Fourier-Transformierten für die symmetrisch fortgesetzte Funktion f bestimmt. In nF2n f (l) = 2n−1 X f (j) exp j=0 −2πijl 2n multiplizieren wir beide Seiten mit exp(−πil/(2n)) und erhalten für die beiden Koeffizienten von f (2n − 1 − j) = f (j) exp −2πi(2n − 1 − j)l −2πijl −πil + exp exp 2n 2n 2n −πil 2πi(j + 1)l −2πijl = exp + exp exp 2n 2n 2n = exp = 2 cos −πi(2j + 1)l πi(2j + 1)l + exp 2n 2n π(2j + 1)l . 2n Wir erhalten damit folgenden Algorithmus für die schnelle Cosinus-Transformation: R Seien f (0), . . . , f (n − 1) ∈ gegeben. 1. Erweitere den Datensatz durch symmetrische Spiegelung zu f (0), f (1), . . . , f (n − 2), f (n − 1), f (n − 1), f (n − 2), . . . , f (1), f (0) ∈ R2n. 2. Wende schnelle Fourier-Interpolation FFI auf den erweiterten Datensatz an. Erhalte F2n f (l), l = 0, . . . , 2n − 1. 3. Bestimme die Koeffizienten der Cosinus-Transformation aus Cn f (l) = −πil c(l)n F2n f (l) ∈ exp 2 2n R, l = 0, . . . , n − 1. Die Rücktransformation erfolgt mit ganz analogen Formeln. 111 10.5 Zweidimensionale Transformationen Sei f ∈ f (j, k), j, k = 0, . . . , n − 1. Die Wellenfunktionen Cn×n ein zweidimensionaler Datensatz, φl.m (j, k) = exp(2πi(jl + km)/n) = φl (j) φm (k), bilden ein Orthogonalsystem des Cn×n bezüglich des Produkts (f, g)n×n = n−1 X l, m = 0, . . . , n − 1, f (j, k) g(j, k), j,k=0 nämlich (φl,m , φn,o )n×n = n2 δ(l,m),(n,o) . Daraus erhalten wir die zweidimensionale Fourier-Transformation Fn×n f (l, m) = n−1 1 1 X f (j, k) exp(−2πi(jl + km)/n) = 2 (f, φl,m )n×n 2 n n j,k=0 mit Umkehrtransformation f (j, k) = n−1 X l,m=0 Fn×n f (l, m) exp(2πi(jl + km)/n). Aufgrund der Tensorproduktstruktur der Wellenfunktionen und der Fourier-Transformation kommt gegenüber dem eindimensionalen Fall nichts wirklich Neues hinzu, außer vielleicht, dass die Unterscheidung zwischen langen und kurzen Wellen nicht mehr so leicht möglich ist, weil Wellen in einer Komponente lang und in der anderen kurz sein können. Mit Fn×n f (l, m) = n−1 n−1 X 1 X f (j, k) exp(−2πijl/n) exp(−2πikm/n) n2 j=0 k=0 lässt sich die zweidimensionale Transformation auf die eindimensionale zurückführen: Wir führen zunächst für jedes k eine eindimensionale Transformation bezüglich j durch. Die obige Formel zeigt, dass die auf diese Weise erhaltene Funktion f˜(l, k) für jedes l bezüglich k transformiert werden muss. Der Aufwand für dieses Verfahren ist damit O(n2 (log n)2 ). Die zweidimensionale Cosinus-Transformation ist analog zum eindimensionalen Fall durch Bildung der Tensorprodukte definiert, (10.8) Cn×n f (l, m) = c(l)c(m) n−1 X f (j, k) cos j,k=0 π(2j + 1)l π(2k + 1)m cos , 2n 2n wobei c(l) wie oben definiert ist. Der Zusammenhang zwischen Fourier-Transformation für den gespiegelten Datensatz und Cosinus-Transformation bleibt der gleiche. 10.6 Bildkompression Ein monochromes Bild ist durch einen Datensatz f (j, k), j, k = 0, . . . , n − 1, gegeben, wobei f (j, k) den Grauton des Pixels (j, k) bezeichnet. Da für die Speicherung von f (j, k) jeweils ein Byte verwendet wird, entspricht f = 0 schwarz und f = 255 weiß. Zur Kompression wird das Bild zunächst in Teilbilder der Größe 8 × 8 oder 16 × 16 aufgeteilt. Da die JPEG-Kompression 8 × 8 verwendet, wollen wir hier nur diesen Fall weiterverfolgen. Auf jedem Teilbild wird eine Cosinus-Transformation durchgeführt und das Ergebnis als Matrix festgehalten. 112 Mit Cf = C8×8 f erhalten wir (10.9) Cf (0, 0) . . . Cf (7, 0) .. .. . . Cf (0, 7) . . . Cf (7, 7) 0 1 5 6 14 15 27 28 2 4 7 13 16 26 29 42 3 8 12 17 25 30 41 43 9 11 18 24 31 40 44 53 10 19 23 32 39 45 52 54 20 22 33 38 46 51 55 60 21 34 37 47 50 56 59 61 35 36 48 49 57 58 62 63 Das rechte Schema zeigt, wie die Koeffizienten auf einem eindimensionalen Feld abgespeichert werden. Abgesehen von Rundungsfehlern kann aus den Informationen zu diesem Zeitpunkt das vollständige Bild rekonstruiert werden. Die Kompression erfolgt nun dadurch, dass kleine und/oder hochfrequente Komponenten in der Matrix zu Null gesetzt oder grob gerundet werden. Im einfachsten Fall werden im rechten Schema nur die ersten K Komponenten berücksichtigt, das sind in etwa die K mit den längsten Wellenlängen. Im JPEG-Standard wird von den Grautönen die Zahl 128 abgezogen, was allerdings nur die Komponente (0, 0) der Cosinus-Transformation verändert. Dann wird eine Cosinus-Transformation wie in (10.8) für n = 8 durchgeführt. Jede Komponente der Matrix in (10.9) wird nun durch eine Zahl geteilt, deren Größe von der zugrundeliegenden Frequenz abhängt, aber nicht Teil des Standards ist. Anschließend werden die auf diese Weise geteilten und auf ganze Zahlen gerundeten Einträge wie in (10.9) auf einem eindimensionalen Feld abgespeichert. Dieses Feld wird in der Regel viele kleine Zahlen enthalten sowie am Ende lauter Nullen und kann daher erfolgreich komprimiert werden, was aber nicht unser Thema ist. Empfohlen wird als Teiler 16 11 10 16 24 40 51 61 12 12 14 19 26 58 60 55 14 13 16 24 40 57 69 56 14 17 22 29 51 87 80 62 18 22 37 56 68 109 103 77 24 35 55 64 81 104 113 92 49 64 78 87 103 121 120 101 72 92 95 98 112 100 103 99 Diese Zahlen wurden durch Experimente bestimmt. Es können aber auch größere oder kleinere Zahlen verwendet werden, so dass man den Grad der Komprimierung verändern kann. Bei der Rücktransformation werden die abgespeicherten Zahlen zunächst mit diesen Einträgen multipliziert, anschließend die Rücktransformation durchgeführt. 113