K
hustbaer schrieb:
Ach so, dir geht es mehr um die in dem Paper vorgestellte Technik. Die, muss ich zugeben, hab ich nicht kapiert. Fehlt mir die Mathematik. Kann man einfach erklären was da gemacht wird?
Soweit ich das verstanden habe werden erstmal die "Pixel" modifiziert (bzw. halt die "Koeffizienten" aus den Pixeln ausgerechnet), damit man die Filterfunktion dann nur mehr an Integralen Positionen sampeln muss = die Werte vorberechnen kann.
Oh, diese Frage hatte ich bis jetzt übersehen. Ich versuch's mal mit eigenen Worten. Wenn du eine kontunierliche Funktion ausgehend von einem zeit/raum-diskreten Signal rekonstruieren willst, müsstest Du ja eigentlich das diskrete Signal (was quasi ein amplituden-modulierter Kamm aus Dirac-Pulsen ist) mit der Impulsantwort eines bestimmten Tiefpass-Filters falten. Bei dem Ansatz für die B-Spline-Interpolation zerlegt man quasi die Impulsantwort des Tiefpassfilters in einen discreten Teil, den man als digitalen Filter vorher über die Daten rüberlaufen lassen kann, und einen kontinuierlichen Teil, z.B. ein kubischer Basis-spline. Das ist deswegen so flott, weil (a) der diskrete Anteil sehr effizient realisierbar ist -- es ist nur ein IIR Filter 1. Ordnung, den man bidirektional (vorwärts+rückwärts) anwendet -- und weil (b) so ein kubischer B-Spline sehr kompakt ist (kompakt im Sinne von "f(x)=0" für alle x bis auf ein sehr kleines Interval).
Beispiel: Quellsignal, 1D mit einem Puls in der Mitte
[0 0 0 0 0 ... 0 0 0 0 0 1 0 0 0 0 0 ... 0 0 0 0 0]
Nach dem "bidi-Filter" (kostet echt nur 3 Multiplikationen und 2 Additionen pro Sample, ist also super flott):
[ ... 0.0000 -0.0002 0.0006 -0.0024 0.0089 -0.0333 0.1244 -0.4641 1.7321 -0.4641 0.1244 -0.0333 0.0089 -0.0024 0.0006 -0.0002 0.0000 ... ]
Da wo nach dem ersten Schritt die 1.7321 steht, stand vorher die 1. Im Wesentlichen werden hier nur die höheren Frequenzen etwas verstärkt. Wenn man dann z.B. die Stelle im Quellsignal zwischen der 1 und der 0 rechts daneben die Mitte interpolieren will, braucht man dann nur die 4 Koeffizienten drum herum der vorgefilterten Version nehmen, also [-0.4641 1.7321 -0.4641 0.1244], und eine bestimmte gewichtete Summe dieser berechnen, wobei die Gewichte von der Subpixelposition abhängen, die man haben will. Im Falle der Mitte, wären das dann [1/48, 23/48, 23/48, 1/48]. Das macht dann 0.6002. Die Gewichte sind einfach die Werte, die man bekommt, wenn man den kubischen B-spline bei 1+p, 0+p, -1+p und -2+p abtastet, wobei p die Subpixelposition zwischen 0 und 1 ist, hier also 0.5 für die Mitte. Man faltet das vorgefilterte Ding also nur mit einem B-spline und tastet es wieder ab, was man direkt in form von Gewichten zusammenfassen kann. Wenn man genau an einer Pixelposition "interpolieren" will, würde man da die Gewichte 1/6, 4/6 und 1/6 für eine 3er-Umgebung bekommen, weil dir kubische B-spline in der Mitte bei 4/6 liegt und bei +/-1 den Wert 1/6 hat. Die 1 im Quellsignal bekomme ich also wieder: dot([-0.4641, 1.7321, -0.4641],[1, 4, 1])/6 = 1. Die Null daneben bekomme ich auch wieder: dot([1.7321, -0.4641, 0.1244],[1, 4, 1])/6 = 0. Es ist also tatsächlich eine kontinulierliche Funktion, die exakt durch die Datenpunkte läuft. Das andere Schöne dabei ist, dass man durch andere Gewichte auch die erste oder zweite Ableitung bestimmen kann. Diese Gewichte kommen dann von der analytischen Ableitung des B-splines. Die Steigung bei der 0 rechts neben der 1 ist nämlich dot([1.7321, -0.4641, 0.1244],[-0.5, 0, 0.5]) = -0.8038.