6.16. Kurven und Integration¶
Die Mathematikseiten behandelten Operationen, die ein Array entgegennehmen und ein Array (oder einen Skalar) ausgeben – Arithmetik, Reduktionen, Broadcasting. Diese Seite behandelt eine andere Klasse von Operationen: solche, die das Array als abgetastete Funktion behandeln und Fragen über die Funktion selbst stellen. Zwischen Samples interpolieren, eine Kurve an sie anpassen, unter ihnen integrieren, sie mit einem anderen Puffer falten.
Alle diese nehmen ndarray-Eingaben entgegen und geben entweder einen Float-Skalar oder ein Float-ndarray zurück.
6.16.1. Interpolation¶
interp() führt eine eindimensionale lineare Interpolation durch. xp ist ein monoton steigendes eindimensionales Array unabhängiger Werte; fp sind die zugehörigen abhängigen Werte; x ist, wo die Interpolierende ausgewertet werden soll:
xp = np.array([0.0, 1.0, 2.0, 3.0])
fp = np.array([10.0, 20.0, 25.0, 30.0])
x = np.array([0.5, 1.5, 2.5])
np.interp(x, xp, fp)
# array([15.0, 22.5, 27.5])
Außerhalb des Bereichs [xp[0], xp[-1]] wird das Ergebnis jeweils auf fp[0] und fp[-1] begrenzt; die Schlüsselwörter left= und right= überschreiben diese Endpunkte.
Auf der Kamera wird dies verwendet, um eine Kalibrierungstabelle auf beliebige Sample-Positionen umzubilden – eine Temperatur-zu-Spannung-Tabelle von einem Thermistor, eine nichtlineare Pixel-Antwortkurve, eine kanalweise Gamma-Lookup. Ein Bibliotheksaufruf, ein Durchlauf über die Eingaben, keine Python-Schleife.
6.16.2. Polynomanpassung und -auswertung¶
polyfit() passt ein Polynom vom Grad deg mittels kleinster Quadrate an die Datenpunkte (x, y) an und gibt die Koeffizienten zurück (höchster Grad zuerst):
x = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
y = np.array([0.0, 1.1, 3.9, 9.1, 15.8])
coeffs = np.polyfit(x, y, 2)
# array([1.0, 0.0, 0.0]) (approximately)
Wenn x weggelassen wird, wird range(len(y)) verwendet – nützlich, um schnell ein Polynom an einen regelmäßig abgetasteten Puffer ohne zugehörige x-Achse anzupassen:
np.polyfit(y, 2)
polyval() wertet das Polynom, dessen Koeffizienten p sind, an x aus. Die Eingabe x kann ein Skalar (gibt einen Float zurück) oder ein ndarray (gibt ein ndarray zurück) sein:
p = np.polyfit(x, y, 2)
fitted = np.polyval(p, x)
Die natürliche Kombination besteht darin, polyfit einmal zur Kalibrierungszeit aufzurufen, die Koeffizienten zu speichern und polyval aufzurufen, um die resultierende Kurve in jedem Einzelbild auszuwerten. Der Polynomauswertungsschritt umfasst eine Handvoll Float-Operationen pro Sample, was selbst auf den kleinsten Kameras günstig ist.
6.16.3. Faltung¶
convolve() gibt die diskrete lineare Faltung voller Länge zweier eindimensionaler Arrays zurück. Nur der Modus full ist implementiert; die Ausgabelänge beträgt len(a) + len(v) - 1. Schneiden Sie das Ergebnis zu, um denselben Effekt wie die Modi same und valid zu erzielen, die das Desktop-numpy bietet:
a = np.array([1.0, 2.0, 3.0])
v = np.array([0.5, 0.5])
np.convolve(a, v)
# array([0.5, 1.5, 2.5, 1.5])
Nützlich für kurze FIR-Filter und Glättungskernel (Box, Dreieck, Gauß), bei denen das Einrichten einer SOS-Kette übertrieben ist. Die Laufzeit ist proportional zum Produkt der beiden Array-Längen – für kurze Kernel in Ordnung, wird aber für lange Kernel schnell teurer als eine FFT-Faltung.
6.16.4. Trapezintegration¶
trapz() integriert eine abgetastete Funktion mit der zusammengesetzten Trapezregel:
x = np.linspace(0, np.pi, num=128)
y = np.sin(x)
np.trapz(y, x) # ~ 2.0
Übergeben Sie dx=, wenn der Sample-Abstand gleichmäßig ist und nur der Schritt zählt; übergeben Sie x=, wenn die Samples nicht gleichmäßig verteilt sind. Der richtige Aufruf zum Integrieren bereits erfasster Sensordaten, bei denen die analytische Form nicht verfügbar ist.
Für Sample-Daten, die bandbegrenzt wurden (zum Beispiel ein Audiopuffer nach einem Anti-Aliasing-Filter), konvergiert die Trapezregel mit dem Quadrat der Sample-Anzahl, was bedeutet, dass eine Verdopplung der Pufferlänge den Fehler um den Faktor vier reduziert.
Wenn der Integrand kein Puffer aus Samples ist, sondern eine Python-Funktion, die die Anwendung an beliebigen Punkten auswerten kann, ist eine andere Familie von Lösern der richtige Aufruf.