K
Wenn Du den "Abtastpunkt" nicht verschieben willst, bietet sich die "zentrale Differenz" an, also
Eingabe: s[k] für diskrete k
Ausgabe a[k] mit a[k] = 0.5 * (s[k+1] - s[k-1])
...und das ist im Prinzip schon ein digitales Filter, welches die Amplituden und Phasen beeinflusst. Den Ableitungsoperator kann man nämlich auch als Filter verstehen, er verschiebt die Phase um 90° und die Amplitude verändert sich in Abhängigkeit der Frequenz.
d sin(f * t) / dt = f * cos(f * t)
Die recht einfache "zentrale Differenz" approximiert den idealen Differentiator aber nicht besonders gut. Für höhere Frequenzen ist dieser Ansatz nicht so gut. Es gibt auch Differentiatoren "höherer Ordnung". Das nächst bessere wäre
a[k] = (s[k-2] - 8 s[k-1] + 8 s[k+1] - s[k+2]) / 12.0
Dafür braucht man aber offensichtlich noch mehr Werte an den Rändern. Das ist ein grundsätzliches Problem.
Was ich aber auch empfehlen kann ist das Ableiten anhand einer eine kubischen B-spline Interpolation. Der vereinfacht sich zu einem "Vorfilter" (bidirektional angewandter IIR-Filter 1. Ordnung) und anschließender Zentraldifferenz. Das Randproblem wird dadurch nicht einfacher, aber die Güte ist super und das ist auch relativ CPU-schonend.
Siehe
"Image Interpolation and Resampling"
http://bigwww.epfl.ch/publications/thevenaz9901.pdf
Hier ein bisschen Matlab-Code für die B-Spline Variante:
eingabe = [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0]; % Einheitsimpuls als Test
a = [1 2-sqrt(3)]; b = sum(a); % Filter-Parameter für Vorfilter
temp = filtfilt(b,a,eingabe); % vorwärts und rückwärts angewendet
ableitung = conv2(temp,[0.5 0 -0.5],'same'); % Zentrale Differenz
Der vektor "temp" speichert hier die Skalierungskoeffizienten für die kubischen Basis-Splines. Die kann man jetzt dazu benutzen an beliebigen Stellen die Funktion auszuwerten oder ihre Ableitungen, welche bis einschließlich der zweiten immer noch überall stetig ist. Wenn man aber an genau den Stützstellen die Ableitung haben will, kann man das einfach mit [0.5 0 -0.5] falten und ist fertig. Will man die zweite Ableitung, faltet man mit [1 -2 1] statt [0.5 0 -0.5] im zweiten Schritt, wobei derselbe Vorfilter benutzt wird.
Der obige Code sollte auch unter GNU/Octave laufen.
Hier eine Abbildung, die zeigt, was die verschienenen Filter mit verschiedenen Frequenzen anstellen. Der "ideale Differentiator" ist das, was man bekommen würde, wenn man eine perfekte sinc-Interpolation durchführen und die dann ableiten würde... Das ist aber auch selten das, was man machen will.
All das funktioniert auch in höhreren Dimensionen. Man kann die einzelnen Achsen separat handhaben, z.B. erst alle Spalten für die 2. Ableitung nach y filtern und dann alle Zeilen filtern für die 1. Ableitung nach x oder sowas.