triangulate_column — 3D structured_light op

• Datenarten: image2d → depth

• Aufruf: import fullseye as fs; fs.ledger.triangulate_column(column, k_cam, k_proj, rot, trans) -> 'np.ndarray' (die Implementierung direkt: import fringe; fringe.triangulate_column(column, k_cam, k_proj, rot, trans) -> 'np.ndarray'; aus dem Register: ops3d.get("triangulate_column"))

Verwendung

Trianguliert die Tiefe Z aus der „Projektorspaltennummer“ jedes Kamerapixels (die letzte Stufe des strukturierten Lichts).

Die Geometrie eines Streifenlichtscanners selbst: ein Kamerapixel (u,v) spannt 1 Sichtstrahl auf, eine Projektorspalten- nummer u_p spannt 1 Ebene auf (die Ebene, die Projektorzentrum und diese Spalte enthält). Der Schnittpunkt von Sichtstrahl und Ebene ist der 3D-Oberflächenpunkt, und sein Z im Kamerasystem ist die Tiefe. Es ist eine geschlossene Formel, daher sind weder Iteration noch Optimierung nötig.

column: (H, W) Projektorspaltennummern (reelle Subpixelwerte). Aus der Phase abgeleitete Werte können

direkt übergeben werden. NaN = unbestimmtes Pixel (Ausgabe ebenfalls NaN).

k_cam: Intrinsische Kameramatrix 3x3 (fx, fy, cx, cy[, skew]). Pixelmitten liegen auf ganzzahligen Koordinaten

(dieselbe Konvention wie render3d.render_mesh / camera.depth_to_points).

k_proj: Intrinsische Projektormatrix 3x3. Verwendet werden nur Zeile 0 (Spaltenrichtung) und Zeile 2.

rot: 3x3-Rotation. Kamerasystem → Projektorsystem (X_proj = rot·X_cam + trans).

trans: Translation der Länge 3 (wie oben, Einheit wie die Szene). Der Nullvektor ist verboten

(Basislinie 0 = Kamera und Projektor am selben Punkt. Ebene und Sichtstrahl schneiden sich nicht, die Tiefe ist undefiniert).

Rückgabewert: (H, W) float64-Tiefenkarte (Z vor der Kamera, dieselbe Größe wie depth von render_mesh).

Pixel, deren Schnittpunkt hinten liegt (Z<=0) oder deren Sichtstrahl parallel zur Ebene ist, sind NaN.

Herleitung: X_cam = Z·d (d = K_cam⁻¹[u,v,1]). Die Spaltenbedingung auf der Projektorseite ist (K_proj[0] − u_p·K_proj[2])·X_proj = 0. Einsetzen von X_proj = rot·X_cam + trans und Auflösen nach Z ergibt Z = −(a·trans) / (a·(rot·d)), a = K_proj[0] − u_p·K_proj[2].

Raises: ValueError bei ungültigen Formen oder Matrizen, Basislinie null oder singulärer Kameramatrix.

Herkunft (öffentliche Literatur): Streifenlicht-Triangulation per Schnitt von Strahl und Ebene -- Hartley & Zisserman, *Multiple View Geometry* 2nd ed. §12 (Schnitte in der projektiven Geometrie) / Salvi et al., *Pattern Recognition* 43 2010 (Klassifikation und Dekodierung von Streifenlichtmustern).

Hintergrundwissen (Physik und Konventionen hinter diesem Operator)

• depth_sensors — Tiefensensoren — Messprinzipien, Werte realer Geräte, wie Messlücken entstehen

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.

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

• structured_light_scan — py -3.11 examples_3d/structured_light_scan.py

Typkompatible Folge-Operatoren (nehmen depth als Eingabe)

depth_to_points · tsdf_from_depth · to_points · fuse_to_voxel · depth_to_organized_points · normals_from_depth · occlusion_edges · bearing_angle_image

Gleiche Kategorie (structured_light)

wrapped_phase · unwrap_phase_2d · graycode_decode · decode_fringe · synthesize_fringes · absolute_phase


*Provenance: fringe.py — 3D 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.