vol_label_shape_stats — VOLCOLOR measure op

• Datenarten: labels → table

• Aufruf: import fullseye as fs; fs.ledger.vol_label_shape_stats(labels, spacing=None, shape: 'bool' = True) (die Implementierung direkt: import volcolor; volcolor.vol_label_shape_stats(labels, spacing=None, shape: 'bool' = True); aus dem Register: opsvolcolor.get("vol_label_shape_stats"))

Verwendung

Größen pro Komponente, die sich in linearer Zeit bestimmen lassen (Volumen, Schwerpunkt, Box, PCA-Formindizes).

Ein Geschwister von volops.vol_region_props, aber mit anderem Zweck:

• Jenes liefert surface_area und Wadell-sphericity. Dazu läuft marching cubes je Komponente, also läuft eine Python-Schleife proportional zur Anzahl der Komponenten (bei der pathologischen Eingabe 1 Label pro 1 Voxel wird es schnell schwer).

• Dieses beschränkt sich auf Größen, die allein aus gewichteten Summen von np.bincount folgen. Pro 1 Labelarray 9 Aufrufe von bincount = O(N + n). Gemessen (connectivity=26, Schachbrett mit 1 Label pro 1 Voxel = pathologische Eingabe):

16 ** 3 = 4096 Voxel / 512 Komponenten = 0.0037 s, 32 ** 3 = 32768 / 4096 =

0.0350 s, 64 ** 3 = 262144 / 32768 = 0.2556 s, 128 ** 3 = 2097152 / 262144 =

2.3122 s. Je 8-fache Voxel 9.5 / 7.3 / 9.0-fach (quadratisch wäre 64-fach),

durchgehend etwa 1.1 Mikrosekunden/Voxel. Das Färben desselben 128 ** 3 dauert 0.0357 s.

(Zum Vergleich: volops.vol_region_props(surface="faces") braucht beim selben 16 ** 3

0.0121 s -- 3.5-fach wegen der Python-Schleife je Komponente. Der Standard surface="auto", der

marching cubes nutzt, ist noch schwerer.)

Die 5 Größen label voxel_count volume centroid bbox haben dieselbe Definition und dieselben Werte wie volops.vol_region_props (fixiert mit exakter Gleichheit durch tests/test_volcolor.py::test_stats_agree_with_vol_region_props_exactly ). bbox ist (z0, z1, y0, y1, x0, x1) mit exklusiven Obergrenzen.

Zusätzlich zurückgegeben:

centroid_mm (z, y, x) physikalische Koordinaten (ohne spacing gleich voxel) ·

extent physikalische Abmessung der bbox (dz, dy, dx) · equivalent_diameter

(6V/pi)**(1/3) · touches_border ob die bbox den Volumenrand berührt ·

principal_extent Quadratwurzeln der Kovarianz-Eigenwerte (s1 >= s2 >= s3) (physikalische Einheiten) ·

linearity (l1-l2)/l1 · planarity (l2-l3)/l1 · isotropy

l3/l1 · elongation sqrt(l1/l2).

elongation kann unendlich werden (Vertrag): bei l1 > 0 und l2 == 0, also einer Komponente, die eine perfekt gerade Linie von 1 Voxel Dicke ist, wird inf geliefert. Das ist kein Unfall einer Division durch 0, sondern die Tatsache "keine Ausdehnung entlang der 2. Achse"; Runden würde die Rangfolge der Schlankheit stillschweigend vertauschen. Ein einzelnes Voxel (l1 == 0) ist ein isotroper Punkt, also 1.0.

Vergisst man spacing, ändern sich Zahlen und Schlussfolgerung. Gemessen -- eine Kugel mit Radius 6 mm, abgetastet auf einem anisotropen Gitter mit spacing = (3.0, 1.0, 1.0) mm (nur z 3-fach gröber), ergibt 293 Voxel. Die Ground Truth in geschlossener Form ist 4/3 pi 6**3 = 904.78 mm**3:

• mit spacing = 879.0 mm ** 3 (Fehler -2.85 %), isotropy = 0.7349 (fast isotrop = korrekt).

• ohne spacing = 293.0 (Voxeleinheiten; als mm ** 3 gelesen ist der Fehler -67.62 %), isotropy = 0.0817 -- die Kugel sieht aus wie eine "Platte". Wer die Anisotropie ignoriert, dessen Formkennzahlen brechen zusammen, und sie kommen auch noch als endliche, plausibel wirkende Werte zurück.

• Auch der Äquivalentdurchmesser weicht um das 1.44-Fache ab: 11.8849 mm gegen 8.2406.

Numerischer Hinweis: Die 2. Momente werden als E[x**2] - E[x]**2 berechnet, daher kann bei Komponenten mit großen Koordinaten und kleiner Ausdehnung Stellenauslöschung auftreten. An der Grenze MAX_COLOR_VOXELS (bis ~2000 je 1 Seite) ist gegenüber E[x**2] ~ 4e6 die relative float64-Genauigkeit 1e-16 = absolut 1e-10, also 10 Stellen Reserve gegenüber Varianzen in Voxeleinheiten. Größere Volumen vorher auf eine ROI zuschneiden (auch deshalb gibt es die Grenze).

Wird *shape* auf False gesetzt, entfällt die Kovarianz (6 der 9 bincounts), und die 5 Einträge ab principal_extent werden nicht geliefert -- wenn nur ein Volumenfilter gebraucht wird, sinken die O(N)-Temporärarrays auf 1.

Liefert list[dict] in aufsteigender Labelreihenfolge (nur tatsächlich vorhandene Labels -- auch bei Lücken in der Nummerierung werden keine leeren dicts bis labels.max() geliefert).

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_cold_chain_excursion — py -3.11 examples/poc_cold_chain_excursion.py

• voxel_labels_color — py -3.11 examples/voxel_labels_color.py

Typkompatible Folge-Operatoren (nehmen table als Eingabe)

—

Gleiche Kategorie (measure)

vol_label_legend


*Provenance: volcolor.py — VOLCOLOR 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.