granular op• Datenarten: image2d → table
• Aufruf: import fullseye as fs; fs.ledger.repose_angle_silhouette(side, *, threshold: 'float' = 0.5, toe_frac: 'float' = 0.15, apex_frac: 'float' = 0.15, min_points: 'int' = 8, correct_ground: 'bool' = False, method: 'str' = 'edge') -> 'dict' (die Implementierung direkt: import granular; granular.repose_angle_silhouette(side, *, threshold: 'float' = 0.5, toe_frac: 'float' = 0.15, apex_frac: 'float' = 0.15, min_points: 'int' = 8, correct_ground: 'bool' = False, method: 'str' = 'edge') -> 'dict'; aus dem Register: opsdrive.get("repose_angle_silhouette"))
Liest den Schüttwinkel φ aus einem Seitenbild (Pulverbedeckung) ab — passt an die linke und rechte Flanke getrennt Geraden an, ohne Fuß und Spitze.
Ablauf (Regelung der Praxis von Sunday et al. 2020 §5.3): (1) Pulveroberflächenhöhe je Spalte = Position des Randpixels, an dem die Bedeckung threshold unterschreitet, + dessen Bedeckung (Subpixel; method="edge", Standard) (2) Boden = unterster Übergang je Spalte (gleiche Interpolation) → Bodenneigung β mit measure.fit_line. method="column_sum" ist die Spaltensumme der Bedeckung (exaktes Subpixel bei kantengeglättetem Rand, weicht der Pixelwert des Pulvers jedoch von 1 ab, ist tan φ um dieses Verhältnis verschoben: schon das Abschneiden von gleichverteiltem Rauschen ±0.1 auf [0, 1] ergab 0.62 Grad zu wenig, gemessen)
(3) Spitze = Spalte maximaler Höhe (4) nur Punkte mit Höhe über Boden von mindestens toe_frac·H und höchstens (1 − apex_frac)·H werden
links und rechts getrennt mit fit_line angepasst (totale kleinste Quadrate) (5) φ = Mittel aus links und rechts.
• correct_ground: entfernt die Neigung β der Bezugsebene durch Subtraktion der Tangenten (tan φ' = tan θ ∓ tan β; exakt für eine scherartige Datum-Neigung). Bei einem Kamera-Rollwinkel ist die Subtraktion der Winkel richtig; beide unterscheiden sich bei β = 5 Grad um mehr als 1 Grad, daher wird standardmäßig nicht korrigiert. Die Bezugsebene nur verdächtigen, wenn die Links-Rechts-Differenz asymmetry_deg groß ist.
• Rückgabe: phi_deg, phi_left_deg, phi_right_deg, asymmetry_deg, ground_deg, height_px, base_px, apex_col, left_cols / right_cols (Bereich der angepassten Spalten), rms_left / rms_right (Residuum zur Geraden [px]), n_left / n_right.
• Raises ValueError: kein Bild / Bedeckung außerhalb [0, 1] / kein Pulver sichtbar / Haufen berührt den oberen, linken oder rechten Bildrand (abgeschnitten) / weniger Anpassungspunkte als min_points (Haufen zu klein) / toe_frac + apex_frac ≥ 1 / falsch geschriebenes method.
Auflösungsrichtwert (gemessen mit gleichverteiltem Rauschen ±0.1 auf der Bedeckung, 4 Winkel × 6 Seeds): 0.007 Grad bei 400 px Haufenbreite, 0.2 Grad bei 50 px, 0.6 Grad bei 25 px.
• 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.
• poc_granular_heap_repose — py -3.11 examples/poc_granular_heap_repose.py
table als Eingabe)course_layout · course_occupancy · course_contains · world_build · world_camera · world_move · lidar_scan · rss_longitudinal_same
granular)heap_volume_cone · heap_mass · heap_volume_heightmap · beverloo_rate · beverloo_fit · discharge_synth · dispense_mass_from_video · hopper_discharge_rate
*Provenance: granular.py — DRIVE 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.