strain_from_displacement — PIV solid op

• Datenarten: image2d × image2d → image2d

• Aufruf: import fullseye as fs; fs.ledger.strain_from_displacement(u: 'Any', v: 'Any', window: 'int', method: 'str', spacing: 'float' = 1.0) -> 'tuple[np.ndarray, np.ndarray, np.ndarray]' (die Implementierung direkt: import dic; dic.strain_from_displacement(u: 'Any', v: 'Any', window: 'int', method: 'str', spacing: 'float' = 1.0) -> 'tuple[np.ndarray, np.ndarray, np.ndarray]'; aus dem Register: opspiv.get("strain_from_displacement"))

• Rückgabewert über das Register: fullseye.ledger.strain_from_displacement(...) liefert nur den Wert des deklarierten Out-Typs image2d (die zugrunde liegende Funktion gibt zusätzlich Hilfsinformationen zurück). Wird das Verworfene gebraucht, nutze fullseye.ledger.strain_from_displacement.raw(...) oder rufe dic.strain_from_displacement direkt auf.

Verwendung

Berechnet das Verzerrungsfeld aus einem Verschiebungsfeld. Gibt (exx, eyy, exy) zurück.

Argumente (window und method haben keinen Default; der Grund steht unten)

u Verschiebungsfeld in x-Richtung (Spalten) [px]. 2-D.

v Verschiebungsfeld in y-Richtung (Zeilen) [px]. Gleiche Form wie u.

window Seitenlänge des lokalen Kleinste-Quadrate-Fensters. Einheit sind Gitterknoten (keine Pixel).

Ungerade.

method "infinitesimal" oder "green". Alles andere löst eine Ausnahme aus.

spacing Knotenabstand [px]. 1.0 (Default) für ein dichtes Feld über alle Pixel.

info["step"] für das Gitter von piv_cross_correlate.

★ Bei Übergabe aus pivops —— eine falsche Komponentenreihenfolge zerbricht still flow2d ist in der Reihenfolge (dy, dx). Richtig ist::

flow, info = piv_cross_correlate(a, b, window=32, overlap=0.75)

exx, eyy, exy = strain_from_displacement(

flow[1], flow[0], 9, "green", spacing=info["step"])

Wird flow[0] als u übergeben, vertauschen sich x und y, und ohne Ausnahme kommt eine plausible andere Antwort zurück. Nur ein unverändert übergebenes 3-D-Array lässt sich mit Korrekturhinweis ablehnen, daher wird dieser Fall geprüft.

Definition ux = ∂u/∂x usw. werden per Ebenenanpassung über window x window bestimmt, und

• "infinitesimal" (infinitesimale Dehnung, technische Dehnung) exx = ux, eyy = vy, exy = ½(uy + vx)

• "green" (Green-Lagrange) exx = ux + ½(ux² + vx²), eyy = vy + ½(uy² + vy²), exy = ½(uy + vx + ux·uy + vx·vy)

★★ Warum method keinen Default hat —— die Lüge der Starrkörperrotation Angenommen, die Probe hat sich nur um θ gedreht, und das Material hat sich nicht einmal um 1 Mikrometer gedehnt. Die wahre Dehnung ist 0. Das exakte Verschiebungsfeld einer Starrkörperrotation u = (cosθ-1)x - sinθ·y, v = sinθ·x + (cosθ-1)y direkt, ohne Umweg über Bilder eingespeist, gemessen (Einheit µε = 1e-6):

θ [Grad] cosθ-1 infinitesimal piv_velocity_gradient green

0.5 -38.1 -38.1 -38.1 5.3e-14

1.0 -152.3 -152.3 -152.3 9.3e-14

2.0 -609.2 -609.2 -609.2 2.0e-13

5.0 -3805.3 -3805.3 -3805.3 6.5e-13

-609 µε bei 2 Grad: 3 Zehntel der Fließdehnung von Stahl (etwa 2000 µε). Bei Green-Lagrange ist exx = (cosθ-1) + ½((cosθ-1)² + sin²θ) = 0 algebraisch exakt, daher fällt es auf 1e-13. Das bestehende piv_velocity_gradient liefert denselben Wert wie die infinitesimale Dehnung (= trägt dieselbe Lüge), und piv_strain_rate liefert bei 2 Grad +1218 µε (2|cosθ-1|) —— eine Größe, die für die linearisierte Fluidrotation u=-ωy, v=ωx 0 wäre, aber bei endlicher Rotation nicht 0 wird.

Umgekehrt ist in Werkstoffprüfberichten, Normen und beim Abgleich mit Dehnungsmessstreifen die infinitesimale Dehnung der Standard, und ein still geliefertes Green-Lagrange lässt die Zahlen nicht passen. Welche richtig ist, kehrt sich je nach Situation um. Darum muss man wählen.

★ Aber "mit green ist man sicher" stimmt nicht —— Schätzfehler gehen unverändert durch Greens Korrekturterm ½(ux²+vx²) wird aus dem geschätzten Gradienten gebildet; ist die Gradientenschätzung schlecht, ist es auch die Korrektur. Gemessen (analytischer Speckle 256², Starrkörperrotation, Mittel ± Streuung innerhalb von MARGIN 40, Einheit µε):

θ [Grad] cosθ-1 | piv+LS w=9 infin. green | lk+LS w=31 infin. green

2.0 -609.2 | -42.9 ± 428 564.7 ± 429 | -698.8 ± 2122 -84.4 ± 2132

5.0 -3805.3 | 364.9 ± 9532 3843.4 ± 9638 | -1372.9 ±22909 2759.6 ±25685

lk bei 2 Grad ist wie im Lehrbuch (-699 ≒ die -609-Lüge → mit green auf -84 reduziert). Aber piv liefert bei 2 Grad selbst für infinitesimale Dehnung nur -42.9 —— rotierende Subsets stumpfen die Korrelation ab, sodass schon die Gradientenschätzung um ±500 µε schwankt, und die +609 µε Green-Korrektur obendrauf ergibt stattdessen +565 µε. Ab 5 Grad streuen beide Schätzer über 1e4 µε, und das Mittel ist bedeutungslos. Die Debatte um Definitionen zählt erst, wenn der Gradient mit dieser Genauigkeit gemessen wird.

★ window ist die räumliche Auflösung selbst Gemessen, eine gleichförmige Dehnung aus demselben piv-Verschiebungsfeld zurückgelesen (µε):

wahr piv_velocity_gradient w=3 w=5 w=9

100 100.4 ± 21.8 100.4 ± 16.0 100.3 ± 6.4 100.3 ± 1.7

500 501.8 ± 107.2 502.0 ± 78.9 501.4 ± 31.3 501.2 ± 8.6

2000 1996.3 ± 342.0 1996.6 ± 259.5 1994.8 ± 99.3 1995.6 ± 25.9

20000 19768.8 ± 2909.9 19768.9 ± 2210.5 19742.7 ± 790.9 19754.1 ± 209.6

Die Mittelwerte sind alle gleich. Nur die Streuung schrumpft mit w, bis auf ein 13.9-tel. Im Gegenzug betrachtet w=9 9 Knoten (72 px bei step=8) als eben, daher liest es in Dehnungsfeldern mit Krümmung, etwa an einer Kerbspitze, die Spitze zu niedrig. Kleinste Quadrate über ein symmetrisches Fenster geben Dehnungsfelder 1. Ordnung exakt wieder, gekrümmte jedoch abgestumpft. Mit einem Default entstünden Zahlen auf Grundlage eines Kompromisses, an dessen Wahl man sich nicht erinnert.

★ Umgang mit NaN —— nicht mit 0 füllen Hat u oder v ein NaN, ist die window x window- Anpassung, die diesen Punkt enthält, nicht definiert. Alle Ausgaben von Fenstern mit NaN werden NaN (1 Maske aus den Fehlstellen von u/v zusammen wird auf die 3 Komponenten angewandt). NaN als 0 zu behandeln lässt nicht gemessene Punkte als "Punkte mit Verschiebung 0" in die Anpassung eingehen und erzeugt ringsum echt wirkende falsche Dehnungsgradienten.

fail-closed

• u / v nicht 2-D, verschiedene Formen, kleiner als 4x4.

• ein ganzes flow2d der Form (2, h, w) als u übergeben (mit Korrekturhinweis abgelehnt).

• window gerade / kleiner als 3 / größer als das Feld.

• spacing nicht positiv / nicht endlich.

• method weder "infinitesimal" noch "green".

• ein Aufruf ohne window und method ergibt TypeError (es gibt keinen Default, daher scheitert er direkt am Argumentmechanismus von Python).

Ausführlicher Anwendungsleitfaden

• Leitfaden zur Familie piv_displacement

Referenzen (Beispieldaten, Literatur)

• Katalog der Beispieldaten (Download-URLs / Lizenzen) — 2-D nutzt skimage.data (BSD/Public Domain) plus synthetische Bilder, 3-D nennt Download-URLs echter Datenquellen (Stanford, PDS, …).

• Herkunft und Literatur der Operatoren — die Quellen der Forschung/Verfahren, auf denen diese Operatorfamilie beruht.

• Der kanonische Algorithmus (Autor, Jahr) und seine Anwendungen stehen im Familienleitfaden oben.

Ausführbare Beispiele (verifizierte Samples, die diesen Operator wirklich aufrufen)

• poc_dic_strain — py -3.11 examples/poc_dic_strain.py

Typkompatible Folge-Operatoren (nehmen image2d als Eingabe)

piv_cross_correlate · piv_multipass · piv_deform_pass · correlation_quality · speckle_quality

Gleiche Kategorie (solid)

correlation_quality · speckle_quality


*Provenance: dic.py — PIV Operator-Registry. Diese Notiz wird von tools/opdocs.py md erzeugt (nicht von Hand bearbeiten).*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.